Offscreen Rendering is a technique for rendering a 3D scene not to the screen, but to a texture buffer (FBO — Framebuffer Object), which can then be used as a texture. According to Apple Metal Documentation, 2025, offscreen rendering is used for creating shadows, reflections, post-effects, and preprocessing graphics. Offscreen Rendering allows splitting a complex scene into passes without quality loss.
Key Takeaways
Offscreen Rendering is a method of rendering graphical content to an intermediate buffer in video memory rather than to the main framebuffer that is displayed on the screen. The result of offscreen rendering is saved to a texture or renderbuffer.
The main purpose of offscreen rendering is multi-pass rendering. A complex scene is split into several passes: first the scene is rendered to a texture (offscreen), then this texture is used as input for the next pass, and so on until the final image is obtained. This approach makes it possible to achieve effects that are impossible in a single pass.
The key mechanism for offscreen rendering in OpenGL ES is the Framebuffer Object (FBO). An FBO is a container to which texture images or renderbuffer objects can be attached. After binding the FBO, all subsequent rendering commands are directed to the attached texture rather than to the screen.
Offscreen Rendering is implemented by creating a separate framebuffer object, attaching a texture or renderbuffer to it, switching the rendering context to this FBO, and executing draw commands. After the pass is complete, the context is switched back to the main framebuffer.
The process consists of three steps: creating the FBO and attaching a texture — rendering the scene to the offscreen texture — using the resulting texture in the next pass. GL_COLOR_ATTACHMENT0 determines which color texture will be rendered to.
// Creating an FBO for offscreen rendering (OpenGL ES 3.0)
GLuint fbo, offscreenTex;
glGenFramebuffers(1, &fbo);
glGenTextures(1, &offscreenTex);
glBindTexture(GL_TEXTURE_2D, offscreenTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER),
GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
offscreenTex, 0);
Offscreen Rendering is used for a wide range of graphical effects. Each technique requires one or more offscreen passes and a specific FBO configuration.
| Technique | Number of Passes | Purpose |
|---|---|---|
| Shadow Mapping | 2+ | Generating a shadow map from the light source |
| Reflection Mapping | 1-2 | Rendering reflections into a cube map |
| Bloom Effect | 3-5 | Glow effect on bright areas of the image |
| HDR Rendering | 2 | Tone mapping for HDR images |
| Depth Prepass | 1 | Pre-filling the depth buffer |
A basic technique in which the rendering result is saved to a texture for later use. Render-to-Texture is used for creating mini-maps, textures for dynamic objects, and pre-visualization of complex materials.
Complex effects (HDR, bloom, depth of field) require several sequential passes. Each pass renders the scene to an offscreen texture, applies a filter, and passes the result to the next pass. This approach allows accumulating effects without loss of final image quality.
Shadow Mapping is a classic example of using offscreen rendering. A shadow is created in two passes: first the scene is rendered from the light source's point of view into a depth texture (offscreen), then during the main rendering each fragment is compared against this depth map to determine whether it is in shadow.
First pass: the camera is positioned at the light source, the scene is rendered to an offscreen buffer, recording only depth into the texture. Second pass: main rendering with each fragment checked — if its depth is greater than the value in the depth map, the fragment is shadowed.
// Fragment Shader for shadow mapping
in vec4 vShadowCoord;
uniform sampler2D uShadowMap;
float calcShadow(vec4 coord) {
vec3 uvw = coord.xyz / coord.w;
float depth = texture(uShadowMap, uvw.xy).r;
return (uvw.z > depth + 0.005) ? 0.3 : 1.0;
}
Offscreen Rendering adds additional GPU passes, which increases the overall computational load and power consumption. In mobile development this is especially critical: each FBO switch requires a pipeline flush and additional time.
For mobile devices it is recommended to: use a renderbuffer instead of a texture if reading the result is not required (depth-only pass); choose the minimum necessary resolution for offscreen textures; merge passes where possible using MRT (Multiple Render Targets).
Offscreen Rendering on different platforms is implemented through their respective APIs. Let us consider examples for OpenGL ES and Apple Metal.
// FBO setup and rendering scene to texture
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glViewport(0, 0, texWidth, texHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(offscreenProgram);
glBindVertexArray(sceneVAO);
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0);
// Switching back to the default framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Metal: offscreen render pass to texture
MTLRenderPassDescriptor passDesc = [MTLRenderPassDescriptor renderPassDescriptor];
passDesc.colorAttachments[0].texture = offscreenTexture;
passDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
passDesc.colorAttachments[0].clearColor =
MTLClearColorMake(0.0, 0.0, 0.0, 0.0);
id<MTLCommandBuffer> cmdBuffer = [commandQueue commandBuffer];
id<MTLRenderCommandEncoder> enc =
[cmdBuffer renderCommandEncoderWithDescriptor:passDesc];
[enc drawIndexedPrimitives:MTLPrimitiveTypeTriangle
indexCount:indexCount
indexType:MTLIndexTypeUInt16
indexBuffer:indexBuffer
indexBufferOffset:0];
[enc endEncoding];
Frequently Asked Questions
Offscreen Rendering is when graphics are drawn not to the screen, but to an invisible buffer (texture). This buffer is then used as a texture for other effects. Imagine you are drawing on a transparent sheet that you then overlay onto the final image.
Offscreen rendering makes it possible to create effects that are impossible in a single pass: shadows (rendering from the light's point of view), reflections, blur, bloom, and HDR toning. Each effect requires a separate pass to an offscreen texture.
Yes, each offscreen pass doubles the amount of GPU work because the scene is rendered again. Optimization includes reducing offscreen texture resolution, using renderbuffers, and merging passes via MRT (Multiple Render Targets).
FBO (Framebuffer Object) is a container to which textures or renderbuffers are attached. Texture allows reading rendering results (needed for shadow mapping, post-effects). Renderbuffer is faster, but its contents cannot be used as a texture.
All modern graphics APIs: OpenGL ES (via FBO), Apple Metal (via MTLRenderPassDescriptor), Vulkan (via VkFramebuffer), Direct3D (via Render Target View). Conceptually the mechanism is the same — rendering to a texture instead of the screen.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also