(Note: "D3d11 game Programming" study Note series by CSDN author Bonchoix wrote, reproduced please indicate the source: Http://blog.csdn.net/BonChoix, thank you ~)
Template buffers (stencil buffer) are an off-screen buffer (off-screen buffer) in the same size as the back buffer, which is used primarily to implement some effects. Each pixel in the template buffer is pi,j, and the pixel pi,j in the back buffer corresponds to one by one. Functionally, similar to the depth buffer, it is used to control whether a fragment can be further processed by the corresponding stage of the 3D rendering pipeline. The difference is that the template buffer is not the same as the depth buffer used to control whether the fragment is being used. For depth buffers, it is determined by comparing each fragment to the depth value at the corresponding pixel in the current buffer, if it is less than the depth value is passed, otherwise the fragment is discarded, and the template buffer uses other judgments, which we will cover in detail later. 1. Template buffer Related data format
In fact, a template buffer is a "physical buffer" with a depth buffer, that is, there is only one buffer, where two kinds of information are stored at any pixel in the buffer: the depth value and the template value. For example, a pixel occupies 4 bytes (32 bits), then the depth value may occupy the previous several, the template value occupies a few later. In D3d11, the following data formats are defined for this buffer:
Dxgi_format_d32_float_s8x24_uint: In this format, each pixel is 8 bytes (64 bits), with a depth value of 32 bits and a float type. The template value is 8 bits, which is the integer type in [0,255], the next 24 bits have no purpose, pure alignment;
Dxgi_format_d24_unorm_s8_uint: In this format, each pixel is 4 bytes (32 bits), where the depth value is 24 bits and is mapped to [0,1]. The template value is 8 bits, which is the integer type in [0,255];
In most cases, we use the second format, which is exactly what we used in all of our sample programs. When initializing D3D, we need to specify the appropriate format for the depth/template buffer when it is created, corresponding to the following code (corresponding to the Dsdesc.format section):[CPP] View Plain copy d3d11_texture2d_desc dsdesc; Dsdesc.format = dxgi_format_ d24_unorm_s8_uint; dsdesc.width = m_clientwidth; dsDesc.Height = m_ clientheight; dsdesc.bindflags = d3d11_bind_depth_stencil; DsDesc.MipLevels = 1; dsdesc.arraysize = 1; dsdesc.cpuaccessflags = 0; dsdesc.sampledesc.count = g_x4msaaquality<1?1:4; dsDesc.SampleDesc.Quality = g_x4MsaaQuality<1?0:g_x4MsaaQuality-1; dsdesc.miscflags = 0; dsdesc.usage = d3d11_usage_default; hr = m_d3ddevice->createtexture2d (& Dsdesc,0,&m_depthstencilbuffer); if (FAILED (HR)) { messagebox (null,_t ("create depth stencil buffer failed!"), _T ("ERROR"), MB_OK); &Nbsp; return false; } hr = m_d3ddevice-> Createdepthstencilview (M_depthstencilbuffer,0,&m_depthstencilview); if (FAILED (HR)) { messagebox (null,_t ("create depth stencil view failed!") , _t ("ERROR"), MB_OK); return false; } m_ Devicecontext->omsetrendertargets (1,&m_rendertargetview,m_depthstencilview);
2. Template test to determine the basis
As the depth buffer uses the depth value of the fragment as a basis for judging whether the fragment is passed, the template buffer has its own unique justification, as shown in the following formula:
The judgment consists of two parts: the left and the right part of the comparison.
Stencilref a reference value set for the programmer, Stencilreadmask reads the mask for the template value, and the reference value "bitwise AND" as the left side of the result; In general, we set the mask to 0xFF, that is, the result of the connection is the template reference value itself;
Value is the current value at the corresponding position in the template buffer, as well as the result value on the right with the mask bitwise AND after;
The results of the left and right two parts of the equation are determined by the intermediate comparison operation "COMPARISON", in D3d11, the comparison operation is defined as the following enumeration type:[CPP] View Plain copy typedef enum d3d11_comparison_func { d3d11_ comparison_never = 1, d3d11_comparison_less = 2, D3D11_COMPARISON_EQUAL = 3, d3d11_comparison_less_equal = 4 , D3D11_COMPARISON_GREATER = 5, D3D11_COMPARISON_NOT_EQUAL = 6, D3D11_COMPARISON_GREATER_EQUAL = 7, d3d11_ comparison_always = 8 } D3d11_comparison_func;
By name it is easy to think of its meaning, we omit the prefix:
Never: The judgment operation forever fails, namely the fragment all does not pass through the template test;
Less: The judgment is "<" operation, that is, the left < right side of the test pass;
EQUAL: "=" operation, that is, when the left and right sides are equal, the test passes;
Less_equal: "<=" operation, when the left <= to the right of the test pass;
GREATER: ">" operation, when left > right, test Pass;
Not_equal: "! =" operation, when the left and right sides are not equal when the test passes;
Greater_equal: ">=" operation, when the left >= to the right of the test pass;
Always: Forever through, that is, regardless of the left and right side of the value, constant pass.
The enumeration type here also adapts to the setting of the comparison operation in the depth buffer.
Give an example of the process of template testing:
For example, we set the template reference value to 1, the mask value is 0xFFFFFFFF, for a fragment, if the corresponding template buffer in the current template value is 0, the above formula,
left = 1 & 0xFF = 1;
right = 0 & 0xFF = 0;
1. If the comparison operation we set to always, then the template test pass the fragment (regardless of the left and right side of what value);
2. If the comparison operation we set to less, then because 1 < 0 is wrong, so the template test of the fragment failed, the fragment is discarded;
3. If the comparison operation we set to greater, because 1 > 0 is correct, so the template test succeeds, the fragment passes.
Other comparison operations, in turn, are simple.
3. Update of template buffers
after the template test in the previous step, the template buffers are updated appropriately, regardless of whether the clips pass the test. As for how to update, it depends on the programmer's settings. The update operation for the template buffers in D3D11 defines the following enumeration types: [CPP] View plain copy typedef enum d3d11_ stencil_op { d3d11_stencil_op_keep = 1, D3D11_STENCIL_OP_ZERO = 2, D3D11_STENCIL_OP_REPLACE = 3, d3d11_ stencil_op_incr_sat = 4,