就如同现实生活中使用的模板,D3D中的模板缓冲也是用来挡住一些像素,使之不能绘制到后台缓冲区。我们通过ID3DDepthStencilState接口控制模板缓冲区和深度缓冲区。下面从创建到使用介绍ID3DDepthStencilState接口。
注意:同混合和渲染状态一样,深度模板状态既可以在C++程序中定义,也可以在效果文件中定义。下面是在C++文件中定义的例子。
在C++程序中,步骤可以分为:创建接口,填充描述结构体,根据描述初始化接口,绑定接口到管线,释放接口
//创建ID3DDepthStencilState接口
ID3D10DepthStencilState* mDrawMirrorDSS;
//填充描述结构体
//深度设置
D3D10_DEPTH_STENCIL_DESC dsDesc;
dsDesc.DepthEnable = true; //启用深度测试
dsDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;//启用深度缓存写入功能
dsDesc.DepthFunc = D3D10_COMPARISON_LESS; //深度测试函数(该值为普通的深度测试)
//模板设置
dsDesc.StencilEnable = true; //启用模板测试
dsDesc.StencilReadMask = 0xff; //模板测试(读取)时的掩码
dsDesc.StencilWriteMask = 0xff; //更新(写入)模板的掩码
//下面两部分是关键
//告诉模板缓冲区如何处理朝前的三角片
dsDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_REPLACE;
dsDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
//如何处理朝后的三角片
dsDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_KEEP;
dsDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_REPLACE;
dsDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
//使用描述创建深度模板缓冲区
md3dDevice->CreateDepthStencilState(&dsDesc, &mDrawMirrorDSS);
//绑定到管线
md3dDevice->OMSetDepthStencilState(mDrawMirrorDSS, 1);
//释放接口
mDrawMirrorDDS->release();
mDrawMirrorDDS = 0;
在效果文件中,则显得简单许多
DepthStencilState NoDepthWritesDSS { DepthEnable = false; DepthWriteMask = Zero; StencilEnable = true; StencilReadMask = 0xff; StencilWriteMask = 0xff; FrontFaceStencilFunc = Always; FrontFaceStencilPass = Incr; FrontFaceStencilFail = Keep; BackFaceStencilFunc = Always; BackFaceStencilPass = Incr; BackFaceStencilFail = Keep; } SetDepthStencilState(NoDepthWritesDSS,0);
其中很多设置项的名字都和C++中差不多,区别只在于前面的D3D_前缀罢了,接下来我照着书上的例程,把使用模板缓冲协助渲染镜面效果的过程写下来。将使用前面学到的ALPHA混合技术还有上面的模板技术。
PS:我个人感觉模板缓状态的设置应该放在C++程序中较为方便,如果写在效果文件中,几乎每个物体都要有自己的效果文件或者渲染通道进行特殊的渲染,并且是固定的。如果是设置在C++程序中,我们可以很方便的切换状态。