throw cGameError(L"Could not create render target view");
r = m_pDevice->QueryInterface(
__uuidof(ID3D10InfoQueue), (LPVOID*)&m_pMessageQueue);
throw cGameError(
L"Could not create IDirect3DDevice10 message queue");
m_pMessageQueue->SetMuteDebugOutput(false); // No muting
m_pMessageQueue->SetMessageCountLimit(-1); // Unlimited messages
The cGraphicsLayer::CreateDeviceAndSwapChain() function is called from
Step 2: Creating a Depth/Stencil Buffer
We’ll look at how to use depth and stencil buffers a little later. For now,
though, we need to set one up in order to be able to render properly. What
is important to know is that a depth buffer is used to provide pixel accu-
rate depth testing so that when you render an object in front of another
object they don’t come out all mangled up. Stencil buffers are used for
advanced effects like volume shadowing.
To create a depth/stencil buffer we start by creating a 2D texture with
the same resolution as our back buffer. We do this by filling out a D3D10_
TEXTURE2D_DESC structure, which we saw in Chapter 2. This time, how-
ever, we will fill it out like this:
D3D10_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = m_rcScreenRect.right;
descDepth.Height = m_rcScreenRect.bottom;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D10_USAGE_DEFAULT;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
The main points to note are that the width and height are exactly the same
size as the back buffer. Also notice the format is set to DXGI_FORMAT_
D24_UNORM_S8_UINT, which in English means a 32-bit buffer, with 24
bits allocated to the depth buffer and 8 bits allocated to the stencil buffer.
The buffer holds unsigned integer data. When the structure is all filled out,
we can pass it as a parameter to ID3D10Device::CreateTexture2D(), which
has the following prototype:
302 n Chapter 7: Direct3D Fundamentals
HRESULT CreateTexture2D(
const D3D10_TEXTURE2D_DESC *pDesc,
const D3D10_SUBRESOURCE_DATA *pInitialData,
ID3D10Texture2D **ppTexture2D
The first parameter takes the address of our D3D10_TEXTURE2D_DESC
structure that we just filled out. The second parameter takes initial data to
load the texture with, which we are not interested in and can therefore set
to NULL. The third parameter takes the address of a pointer to a texture,
which will be filled in by Direct3D when the texture is created. Here is the
r = m_pDevice->CreateTexture2D(&descDepth, NULL, &m_pDepthStencilBuffer);
So now we have a texture set up to use as our depth/stencil buffer, but
Direct3D doesn’t know anything about it yet. The next step is to fill in a
D3D10_DEPTH_STENCIL_DESC structure, which looks like this:
typedef struct D3D10_DEPTH_STENCIL_DESC {
BOOL DepthEnable;
D3D10_DEPTH_WRITE_MASK DepthWriteMask;
BOOL StencilEnable;
UINT8 StencilReadMask;
UINT8 StencilWriteMask;
DepthEnable Flags whether the depth part of the buffer is enabled. We’ll set this to true.
DepthWriteMask This can be set to D3D10_DEPTH_WRITE_MASK_ZERO or D3D10_
DEPTH_WRITE_MASK_ALL. We’ll be setting it to D3D10_DEPTH_
WRITE_MASK_ALL, which means all of the depth buffer is available for
DepthFunc A function for comparing depth data. This can be set to any one of the
D3D10_COMPARISON_FUNC enumerated values:
D3D10_COMPARISON_NEVER—Test always fails
D3D10_COMPARISON_LESS—Pass if source data is less than destination
D3D10_COMPARISON_EQUAL—Pass if source data is equal to
destination data
D3D10_COMPARISON_LESS_EQUAL—Pass if source data is less than
or equal to destination data
D3D10_COMPARISON_GREATER—Pass if the source data is greater
than destination data
D3D10_COMPARISON_NOT_EQUAL—Pass if the source data is not
equal to destination data
Chapter 7: Direct3D Fundamentals n 303
D3D10_COMPARISON_GREATER_EQUAL—Pass if the source data is
greater than or equal to destination data
D3D10_COMPARISON_ALWAYS—Always pass the test
We’ll be using D3D10_COMPARISON_LESS.
StencilEnable Flags whether the stencil buffer portion of the depth stencil buffer is
enabled, which we’ll set to true.
StencilReadMask Sets the portion of the stencil buffer for reading, which we’ll set to all, or
StencilWriteMask Sets the portion of the stencil buffer for writing, which we’ll set to all, or
FrontFace Sets how the results of the depth test should be used for triangles facing
the camera in the stencil buffer. There are three D3D10_STENCIL_OP
members, which can be set to test for when the stencil fails, when the
stencil passes and depth testing fails, and for when they both pass. Finally,
there is a D3D10_COMPARISON_FUNC, which is set to a test to compare
data. For now we’ll set these to D3D10_STENCIL_OP_KEEP,
D3D10_COMPARISON_ALWAYS, respectively.
BackFace This member is the same as FrontFace except it defines what to do for
triangles that are not facing the camera. For now we’ll set this to
Here is the code to fill out the depth stencil buffer:
ZeroMemory(&descDS, sizeof(descDS));
descDS.DepthEnable = true;
descDS.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
descDS.DepthFunc = D3D10_COMPARISON_LESS;
// Stencil test values
descDS.StencilEnable = true;
descDS.StencilReadMask = (UINT8)0xFFFFFFFF;
descDS.StencilWriteMask = (UINT8)0xFFFFFFFF;
// Stencil op if pixel is front
descDS.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
descDS.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
descDS.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
descDS.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
// Stencil op if pixel is back
descDS.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
descDS.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
descDS.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
descDS.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
304 n Chapter 7: Direct3D Fundamentals

Get Advanced 3D Game Programming with DirectX 10.0 now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.