next up previous contents
Next: 9. Antialiasing Up: 8. Blending and Compositing Previous: 8.6 The Stencil Buffer

8.7 Compositing Images with Depth

Compositing separate images together is a useful technique for increasing the complexity of a scene [24]. Section 8.1 discusses algorithms for compositing two images together using alpha values to control how pixels are merged. One drawback of this method is that only simple visibility information can be expressed using mattes or masks. Using the stencil buffer, it is possible to merge images using the original depth information from the images. Both color and depth images can be independently saved to memory and later drawn to the screen using glDrawPixels(). This is sufficient for 2D style composites, where objects are drawn on top of each other to create the final scene. To do true 3D compositing, it is necessary to use the color and depth values simultaneously, so that depth testing can be used to determine which surfaces are obscured by others.

The stencil buffer can be used for true 3D compositing in a two pass operation. The color buffer is disabled for writing, the stencil buffer is cleared, and the saved depth values are copied into the framebuffer. Depth testing is enabled, insuring that only depth values that are closer to the original can update the depth buffer. glStencilOp() is called to set a stencil buffer bit if the depth test passes.

The stencil buffer now contains a mask of pixels that were closer to the view than the pixels of the original image. The stencil function is changed to accomplish this masking operation, the color buffer is enabled for writing, and the color values of the saved image are drawn to the frame buffer.

This technique works because the fragment operations, in particular the depth test and the stencil test, are part of both the geometry and imaging pipelines in OpenGL. Here is the technique in more detail. It assumes that both the depth and color values of an image have been saved to system memory, and are to be composited using depth testing to an image in the framebuffer:

Clear the stencil buffer using glClear(), or'ing in GL_STENCIL_BUFFER_BIT.
Disable the color buffer for writing with glColorMask().
Set stencil values to 1 when the depth test passes by calling glStencilFuncGL_ALWAYS, 1, 1(GL_ALWAYS, 1, 1), and glStencilOpGL_KEEP, GL_KEEP, GL_REPLACE(GL_KEEP, GL_KEEP, GL_REPLACE).
Ensure depth testing is set; glEnableGL_DEPTH_TEST(GL_DEPTH_TEST), glDepthFuncGL_LESS(GL_LESS).
Draw the depth values to the framebuffer with glDrawPixels(), using GL_DEPTH_COMPONENT for the format argument.
Set the stencil buffer to test for stencil values of 1 with glStencilFuncGL_EQUAL, 1, 1(GL_EQUAL, 1, 1) and glStencilOpGL_KEEP, GL_KEEP, GL_KEEP(GL_KEEP, GL_KEEP, GL_KEEP).
Disable the depth testing with glDisableGL_DEPTH_TEST(GL_DEPTH_TEST).
Draw the color values to the framebuffer with glDrawPixels(), using GL_RGBA as the format argument.

At this point, both the depth and color values will have been merged, using the depth test to control which pixels from the saved image would update the framebuffer. Compositing can still be problematic when merging images with coplanar polygons.

This process can be repeated to merge multiple images. The depth values of the saved image can be manipulated by changing the values of GL_DEPTH_SCALE and GL_DEPTH_BIAS with glPixelTransfer(). This technique could allow you to squeeze the incoming image into a limited range of depth values within the scene.

next up previous contents
Next: 9. Antialiasing Up: 8. Blending and Compositing Previous: 8.6 The Stencil Buffer
David Blythe