In this tutorial, we use stencel to implement a mirror reflection effect.
1. First, we need to add several member variables and functions in d3dclass.
Id3d11depthstencilstate * m_depthstencilstatemirror;
Id3d11depthstencilstate * m_depthstencilstatereflect;
M_depthstencilstatemirror is the depth stencer State used when rendering the mirror. We set the stencer function to d3d11_comparison_always. In this way, stencer can always pass, and then the pass operation is fail, the Set ref value is used to fill the stencel buffer.
Depthstencildesc. depthenable = true;
Depthstencildesc. depthwritemask = d3d11_depth_write_mask_all
Depthstencildesc. depthfunc = d3d11_comparison_less;
Depthstencildesc. stencilenable = true;
Depthstencildesc. stencilreadmask = 0xff;
Depthstencildesc. stencilwritemask = 0xff;
// Template operations for front face pixels.
Depthstencildesc. frontface. stencilfailop = d3d11_stencil_op_keep;
Depthstencildesc. frontface. stencildepthfailop = d3d11_stencil_op_keep;
Depthstencildesc. frontface. stencilpassop = d3d11_stencil_op_replace;
Depthstencildesc. frontface. stencilfunc = d3d11_comparison_always;
// Template operation mode for back face pixels.
Depthstencildesc. backface. stencilfailop = d3d11_stencil_op_keep;
Depthstencildesc. backface. stencildepthfailop = d3d11_stencil_op_decr;
Depthstencildesc. backface. stencilpassop = d3d11_stencil_op_replace;
Depthstencildesc. backface. stencilfunc = d3d11_comparison_always;
// Create a deep template to make it take effect
Result = m_device-> createdepthstencilstate (& depthstencildesc, & m_depthstencilstatemirror );
If (failed (result ))
{
HR (result );
Return false;
}
M_depthstencilstatereflect is used to render the reflected objects in the mirror. Depth test is forbidden at this time, so that depth test is always passed. The stenpencil function is used to compare the current stenpencil ref value with the value in stenpencil buffer, if the value is equal to the value of pass stencel test.
// Set the reflect object depth template status description.
Depthstencildesc. depthenable = true;
Depthstencildesc. depthwritemask = d3d11_depth_write_mask_zero; // d3d11_depth_write_mask_zero disable deep write buffer
Depthstencildesc. depthfunc = d3d11_comparison_always;
// Template operations for front face pixels.
Depthstencildesc. frontface. stencilpassop = d3d11_stencil_op_keep;
Depthstencildesc. frontface. stencilfunc = d3d11_comparison_equal;
// Create a deep template to make it take effect
Result = m_device-> createdepthstencilstate (& depthstencildesc, & m_depthstencilstatereflect );
If (failed (result ))
{
HR (result );
Return false;
}
M_alphaenableblendingstate state variable creates an Alpha blend state, which is mainly used when rendering objects in the mirror, because our mirror is represented by a texture, alpha blend combines the mirror texture with the rendered object.
// Create an Alpha blend status.
Blendstatedescription. rendertarget [0]. blendenable = true;
// Blendstatedescription. rendertarget [0]. srcblend = d3d11_blend_one;
Blendstatedescription. rendertarget [0]. srcblend = d3d11_blend_blend_factor;
Blendstatedescription. rendertarget [0]. destblend = d3d11_blend_inv_blend_factor;
Blendstatedescription. rendertarget [0]. blendop = d3d11_blend_op_add;
Blendstatedescription. rendertarget [0]. srcblendalpha = d3d11_blend_one;
Blendstatedescription. rendertarget [0]. destblendalpha = d3d11_blend_zero;
Blendstatedescription. rendertarget [0]. blendopalpha = d3d11_blend_op_add;
Blendstatedescription. rendertarget [0]. rendertargetwritemask = d3d11_color_write_enable_all; // 0x0f;
// Create an Alpha blend state with the descriptor
Result = m_device-> createblendstate (& blendstatedescription, & m_alphaenableblendingstate );
If (failed (result ))
{
Return false;
}
Another function is changebackcullmode (bool B), which is used to change the rendering state and set the front face to clockwise rendering. Because when rendering an object in a mirror, the front of the object in the mirror actually corresponds to the opposite of the object, which requires changing the rendering order.
The following functions are used to change the new States.
Void turnonalphablending ();
Void turnoffalphablending ();
Void changebackcullmode (bool B );
Void enabledefaultdepthstencel ();
Void enableincludepthstenpencil ();
Void enablereflectdepthstenpencil ();
2. The beginsence function in d3dclass is slightly changed. The stencer value is cleared before each frame is rendered to 0.
Void d3dclass: beginscene (float red, float green, float blue, float alpha)
{
...
// Clear the buffer depth.
M_devicecontext-> cleardepthstencilview (m_depthstencilview, d3d11_clear_depth | d3d11_clear_stencer, 1.0f, 0 );
Return;
}
3. added a built-in modelclass class to indicate the mirror mesh.
4. Rendering objects in sequence in the graphicsclass class
First render the ground, wall, and box
M_d3d-> enableincludepthstencel ();
Render mirror
M_d3d-> enabledefaultdepthstencel ();
Define the mirror reflection plane and calculate the reflection matrix. Note that when d3dxmatrixreflect calculates the reflection matrix, the plane is normalized, so I added a translation operation.
D3dxplane serial plane (0.0, 0.0, 10.99, 0.0 );
D3dxmatrix R;
// Obtain the reflection matrix based on the plane.
D3dxmatrixreflect (& R, & mirrorplane );
// The box is at the origin and remains unchanged. Its world coordinate matrix is worldmatrix.
D3dxmatrix W = worldmatrix * R;
D3dxmatrixtranslation (& worldmatrix1, 0.0, 0.0,-18.0 );
W = worldmatrix1 * W;
Next, set the status
M_d3d-> enablereflectdepthstenpencil ();
M_d3d-> turnonalphablending ();
M_d3d-> changebackcullmode (true );
Rendering box in mirror
M_d3d-> enabledefaultdepthstencel ();
M_d3d-> turnoffalphablending ();
M_d3d-> changebackcullmode (false );
The final effect of the program is as follows:
Complete code can be found:
Project File mytutoriald3d11_43
Download Code:
Http://files.cnblogs.com/mikewolf2002/d3d1139-49.zip
Http://files.cnblogs.com/mikewolf2002/pictures.zip