A z-buffer, also called a depth buffer, is a DirectDraw surface that stores depth information to be used by Direct3D. When Direct3D renders a 3-D scene to a target surface, it can use the memory in an attached z-buffer surface as a workspace to determine how the pixels of rasterized polygons occlude one another. The target buffer that D3D uses for rendering is an offscreen DirectDraw surface to which color values are written. The z-buffer surface that is attached to the target surface is used to store depth information which tells Direct3D how "deep" each visible pixel is in the scene.
When a 3-D scene is rendered with z-buffering enabled, each point on the rendering surface is tested. At the beginning of the test, the depth value in the z-buffer is set to the largest possible value for the scene. The color value on the rendering surface is set to either the background color value, or the color value of the background texture at that point. Each polygon in the scene is tested to see if it intersects with the current coordinate x,y on the rendering surface. If it does, the z value at the current point is tested to see if it is smaller than the z value stored in the z-buffer. If the z of the polygon value is smaller, it is stored in the z-buffer and the color value from the polygon is written to the current point on the rendering surface. If the z value of the polygon at that point is larger, the next polygon in the list is tested.
Steps 1-3 are illustrated in the code fragments given in the section entitled Creating the Direct3D Device. The surface to be used for the z-buffer is created by calling the IDirectDraw2::CreateSurface function. It is attached to the rendering target using the IDirectDrawSurface3::AddAttachedSurface function.
Step 4 is accomplished by using the IDirect3DDevice2::SetRenderState function. When setting the render state to enable z-buffering, the dwRenderStateType parameter must be set to D3DRENDERSTATE_ZENABLE, and the dwRenderState parameter should be set to 1.
By default, the D3D system is allowed to write to the z-buffer. Most applications should leave z-buffer writes enabled. However, there are some special effects that can be achieved by not allowing the D3D system to write to the z-buffer. Disabling z-buffer writes is done by calling the IDirect3DDevice2::SetRenderState function with the dwRenderStateType parameter set to D3DRENDERSTATE_ZWRITEENABLE and the dwRenderState parameter should be set to 0.
When depth testing using z-buffers is performed on a rendering surface, the D3D system searches for the smallest z value for each point on the rendering surface by default. This default can be changed for customize rendering by calling the IDirect3DDevice2::SetRenderState function with the dwRenderStateType parameter set to D3DRENDERSTATE_ZFUNC. The dwRenderState parameter should be set to one of the values in the D3DCMPFUNC enumeration.
Polygons that are coplanar in your 3-D space can be made to appear as if they are not coplanar by adding a z-bias to each one. This is a technique commonly used to ensure that shadows in a scene are displayed properly. For instance, a shadow on a wall has the same z value as the wall. However, it must appear on the wall for the scene to look correct. To add a z-bias to a polygon, call the IDirect3DDevice2::SetRenderState function just before IDirect3DDevice2::DrawPrimitive is called to render the polygon. Set the dwRenderStateType parameter to D3DRENDERSTATE_ZBIAS. Set the dwRenderState parameter to a value between 0-16 inclusive. A higher z-bias value will increase the likelihood that the particular polygon will be visible when displayed with coplanar polygons.
D3D also provides a specialized variant of z-buffering called z-checking. When z-checking is enabled, polygons are culled in groups instead of one at a time. The IDirect3DDevice2::SetRenderState function is used to enable z-checking. Set the dwRenderStateType parameter to D3DRENDERSTATE_ZVISIBLE.
Whenever a z-buffer surface is created, a pointer to it should be maintained by the application until it shuts the D3D system down. The z-buffer surface should be released just before the rendering surface is released.
Z-buffering requires overhead during rendering. Various techniques can be used to optimized rendering when z-buffering is used. For details, see Z-Buffer Performance.