Z-buffer
The Z Buffer
The Z buffer (also known as a depth buffer) records the depth of a pixel when it is rendered. Because the final transform applied to our geometry takes the data from 3D view space into the 2D screen space all depth information is lost. We are left with x, y screen positions but no z position. Direct3D needs to know the depth so that it can hide geometry that is behind other geometry. It can also be useful for doing our own advanced rendering techniques.
Graphic cards have provided Z buffers for many years, more recently a new buffer has been added called a stencil buffer. This buffer can be used by the programmer for their own purposes. A common reason to use it is to write values in a render pass and then test the stencil values in the next pass and draw or not depending on the result. An example use is for drawing shadows, look at the stencil shadow sample with the SDK.
Once a Z buffer is defined Direct3D will automatically avoid rendering triangles that are behind other triangles.
Creating a Z Buffer
The stencil buffer and z buffer are often combined together in the graphic card. To use a z buffer you need to fill in information in your presentation parameters structure you specify when creating your device. e.g.
D3DPRESENT_PARAMETERS presParams;
ZeroMemory(&presParams,sizeof(presParams));
presParams.Windowed=TRUE;
presParams.SwapEffect=D3DSWAPEFFECT_DISCARD;
presParams.BackBufferFormat=D3DFMT_UNKNOWN;
presParams.EnableAutoDepthStencil = TRUE;
presParams.AutoDepthStencilFormat = D3DFMT_D16;
gD3dObject->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presParams, &gD3dDevice);
Most of this is described in the Direct3D Setup notes, the new information now added that is required to use a z buffer is:
presParams.EnableAutoDepthStencil = TRUE;
presParams.AutoDepthStencilFormat = D3DFMT_D16;
- EnableAutoDepthStencil - if set to TRUE Direct3D will create and manage depth buffers for your game. As mentioned stencil and depth buffers are often combined so this creates the facility to use both. If this is TRUE you must also define:
- AutoDepthStencilFormat - allows you to specify the format of the buffer in terms of how many bits are used to store each value. Beware that certain graphic modes will not allow you to specify anything better than a 16 bit format. Generally you use D3DFMT_D16
Enabling the Z buffer
There is one further thing you need to do in order to get Direct3D to automatically use the Z buffer and that is to turn it on:
// Turn on the zbuffer
gD3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
For further info. on the Z buffer states that can be made see here: Render States
Clearing the Z buffer
The Z buffer is filled each render loop. It is filled with values ranging from 0.0f (as close as you can get) to 1.0f (as far away as you can get). At the beginning of each render loop we need to clear the buffer to 1.0f ready for the next render. We use the clear function that we have already used to clear our screen (target), see the Direct3D Setup notes.
gD3dDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,255,255),1.0f,0);
This time we are specifying that we want to clear both the target (D3DCLEAR_TARGET) and the z buffer (D3DCLEAR_ZBUFFER). We are clearing the screen to white and the z buffer to 1.0f (as far away as you can get). The final value in this call is where you could specify a value to clear the stencil buffer to.
That is all there is to enabling a z buffer in Direct3D. After the above process the Z buffer will be used automatically by Direct3D.
Further information on the clear method can be found in the MSDN help here: MSDN Clear