Offscreen Rendering represents a rendering process which ignores the standard visible frame buffer and stores rendered data in an alternative buffer not being displayed after rendering. This buffer is called the render target. The case of using a texture as render target is thus called render to texture (RTT). Multiple-Render-Targets describes the utilization of more than one buffer.
This technique forms the basis for most rendering processes used in game engines or in deferred shading frameworks. Deferred shading first acquires geometric data (position, normals etc.) and stores them in several render targets. Shading computation is then performed on this data in a later step. Any post processing steps work on rendered data being saved in render targets.
In the context of SSAO multiple render targets are used to store normals and linear depth for later computation of the occlusion value by a shader program. The resulting AO is again stored in a texture target to be blurred using the following render passes before the actual frame buffer is addressed.
Example in OpenGL:
//set variables for textures, depth buffer and render buffer
GLuint textures[2];
GLuint depth_rb;
GLuint fb1;
//set openGL texture mode and create 2 texture
glEnable(GL_TEXTURE_2D);
glGenTextures(2, textures);
//creating texture 1 for offscreen rendering – example for floating point 16F
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, res_x, res_y, 0, GL_RGBA, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
//texture 2 for offscreen rendering – example for floating point [0,1]
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, res_x, res_y, 0, GL_RGBA, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
glGenRenderbuffersEXT(1, &depth_rb);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, res_x, res_y);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glGenFramebuffersEXT(1, &fb1);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb1);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textures[1], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, textures[0], 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
[…]
//set variables for mutliple render targets
GLenum mrt[2];
mrt[0] = GL_COLOR_ATTACHMENT0_EXT;
mrt[1] = GL_COLOR_ATTACHMENT1_EXT;
//rendering method
void geometryPass() {
//initialize projection, camera etc.
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(…);
//Shader nutzen (optional)
glUseProgram(program0);
//render to FrameBufferObject
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb1);
glDrawBuffers(2, mrt);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,res_x,res_y);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//draw geometry
glCallList(…);
}