模板缓存和深度缓存是同时创建的,在指定深度缓存格式的时候,模板缓存的格式也被同时指定了,语句如下:
d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;//24位深度缓存,8位模板缓存
模板缓存的分辨率与深度缓存和后台缓存的分辨率大小相同,
屏幕上的某个像素点都对应着模板缓存、深度缓存和后台缓存中的某个像素值。
模板缓存与深度缓存类似,都需要通过特定的比较来判断是否更新后台缓存的像素,即也有模板测试过程。
要使用模板缓存必须开启其状态,默认为关闭状态,
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,true);//开启模板缓存
另外在执行清屏动作时,还要使用
D3DCLEAR_STENCIL
清除模板缓存:
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,D3DCOLOR_XRGB(80,80,80),1.0,0);
模板测试的效果与深度测试类似,都是通过特定的比较方式判断某个像素是否应该被写入后台缓存。
result=(ref & mask) OP (value & writemask)
result为比较结果,ref为模板参考值,mask为模板参考值的掩码,value为当前像素的值,writemask为当前像素的掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILREF,0x1);//设置模板参考值
g_pd3dDevice->SetRenderState(D3DRS_STENCILMASK,0xffffffff);//设置模板测试掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);//设置模板写掩码
OP为比较方式为D3DCMPFUNC枚举成员:
typedef enum D3DCMPFUNC
{
D3DCMP_NEVER = 1,
D3DCMP_LESS = 2,
D3DCMP_EQUAL = 3,
D3DCMP_LESSEQUAL = 4,
D3DCMP_GREATER = 5,
D3DCMP_NOTEQUAL = 6,
D3DCMP_GREATEREQUAL = 7,
D3DCMP_ALWAYS = 8,
D3DCMP_FORCE_DWORD = 0x7fffffff,
} D3DCMPFUNC, *LPD3DCMPFUNC;
设置比较方式:
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);//设置比较方法
在测试完成判断某个像素是否写入后台缓存后,要更新模板缓存,必须为其制定更新方式:
1.在模板测试失败时更新
g_pd3dDevice->SetRenderState(D3DRS_STENCILFAIL,StencilOperation);
2.在深度测试失败时更新
g_pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL,StencilOperation);
3.在模板测试和深度测试都成功时更新
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,StencilOperation);
其中,
StencilOperation
为
D3DSTENCILOP
枚举的成员:
typedef enum D3DSTENCILOP
{
D3DSTENCILOP_KEEP = 1,
D3DSTENCILOP_ZERO = 2,
D3DSTENCILOP_REPLACE = 3,
D3DSTENCILOP_INCRSAT = 4,
D3DSTENCILOP_DECRSAT = 5,
D3DSTENCILOP_INVERT = 6,
D3DSTENCILOP_INCR = 7,
D3DSTENCILOP_DECR = 8,
D3DSTENCILOP_FORCE_DWORD = 0x7fffffff,
} D3DSTENCILOP, *LPD3DSTENCILOP;
//Step 1:清屏,颜色设为灰色,深度缓存置为1.0,模板缓存置为0
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,D3DCOLOR_XRGB(80,80,80),1.0,0);
//绘制镜面
D3DXMatrixTranslation(&matWorld1,0.0F,0.0F,6.0F);
D3DXMatrixRotationY(&Ry,D3DX_PI/4.0F);
D3DXMatrixMultiply(&matWorld1,&Ry,&matWorld1);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1);
g_pd3dDevice->SetMaterial(&g_Materials[0]);
g_pWallMesh->DrawSubset(0);
//绘制茶壶
D3DXMatrixTranslation(&matWorld2,-1.0F,1.0F,1.0F);
D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F);
D3DXMatrixMultiply(&matWorld2,&matWorld2,&Ry);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld2);
g_pd3dDevice->SetMaterial(&g_Materials[1]);
g_pTeapotMesh->DrawSubset(0);
//绘制球体
D3DXMatrixTranslation(&matWorld3,-1.0F,-1.0F,1.0F);
D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F);
D3DXMatrixMultiply(&matWorld3,&matWorld3,&Ry);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld3);
g_pd3dDevice->SetMaterial(&g_Materials[2]);
g_pSphereMesh->DrawSubset(0);
//Step 3:设置模板
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,true);//开启模板缓存
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);//设置比较方法
g_pd3dDevice->SetRenderState(D3DRS_STENCILREF,0x1);//设置模板参考值
g_pd3dDevice->SetRenderState(D3DRS_STENCILMASK,0xffffffff);//设置模板测试掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);//设置模板写掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE);//设置模板测试成功后更新模板的方式为替换
//Step 4:关闭向深度缓存的写操作,开启融合技术,源融合因子设为0,目标融合因子设为1
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,false);//关闭向深度缓存的写操作
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);//开启融合
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);//源融合因子设为0
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);//目标融合因子设为1
//绘制镜面
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1);
g_pd3dDevice->SetMaterial(&g_Materials[0]);
g_pWallMesh->DrawSubset(0);
//Step 6.1
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true);//开启向深度缓存的写操作
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);//设置比较方法
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);//设置模板测试成功后更新模板的方式
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(80,80,80),1.0F,0);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTALPHA);//源融合因子设为目标Alpha
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);//目标融合因子设为0
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);//镜像翻转绘制背面,设置消隐方式为顺时针
D3DXMATRIX matReflect,matMirror;
D3DXPLANE plane(1.0F,0.0F,1.0F,-6.0F);//平面 (x)+0*y+(z-6)=0即x+z-6=0;
D3DXMatrixReflect(&matReflect,&plane);
//茶壶镜像
D3DXMatrixMultiply(&matMirror,&matWorld2,&matReflect);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror);
g_pd3dDevice->SetMaterial(&g_Materials[1]);
g_pTeapotMesh->DrawSubset(0);
//球体镜像
D3DXMatrixMultiply(&matMirror,&matWorld3,&matReflect);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror);
g_pd3dDevice->SetMaterial(&g_Materials[2]);
g_pSphereMesh->DrawSubset(0);
/****************************************************************
*函数名 : Render
*功能 : 场景绘制
*输入 : 无
*输出 : 无
*返回值 : 无
****************************************************************/
void Render()
{
//Step 1:清屏,颜色设为灰色,深度缓存置为1.0,模板缓存置为0
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,D3DCOLOR_XRGB(80,80,80),1.0,0);
if(SUCCEEDED(g_pd3dDevice->BeginScene()))//开始绘制
{
/*在此绘制其他*/
//Step :2:先绘制一般物体,先禁用模板缓存
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,false);//禁用模板缓存
//设置世界变换矩阵
D3DXMATRIX matWorld1,matWorld2,matWorld3,Ry;
//绘制镜面
D3DXMatrixTranslation(&matWorld1,0.0F,0.0F,6.0F);
D3DXMatrixRotationY(&Ry,D3DX_PI/4.0F);
D3DXMatrixMultiply(&matWorld1,&Ry,&matWorld1);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1);
g_pd3dDevice->SetMaterial(&g_Materials[0]);
g_pWallMesh->DrawSubset(0);
//绘制茶壶
D3DXMatrixTranslation(&matWorld2,-1.0F,1.0F,1.0F);
D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F);
D3DXMatrixMultiply(&matWorld2,&matWorld2,&Ry);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld2);
g_pd3dDevice->SetMaterial(&g_Materials[1]);
g_pTeapotMesh->DrawSubset(0);
//绘制球体
D3DXMatrixTranslation(&matWorld3,-1.0F,-1.0F,1.0F);
D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F);
D3DXMatrixMultiply(&matWorld3,&matWorld3,&Ry);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld3);
g_pd3dDevice->SetMaterial(&g_Materials[2]);
g_pSphereMesh->DrawSubset(0);
//Step 3:设置模板
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,true);//开启模板缓存
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);//设置比较方法
g_pd3dDevice->SetRenderState(D3DRS_STENCILREF,0x1);//设置模板参考值
g_pd3dDevice->SetRenderState(D3DRS_STENCILMASK,0xffffffff);//设置模板测试掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);//设置模板写掩码
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE);//设置模板测试成功后更新模板的方式为替换
//Step 4:关闭向深度缓存的写操作,开启融合技术,源融合因子设为0,目标融合因子设为1
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,false);//关闭向深度缓存的写操作
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);//开启融合
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);//源融合因子设为0
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);//目标融合因子设为1
//Step 5:绘制镜面到模板缓存中
//绘制镜面
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1);
g_pd3dDevice->SetMaterial(&g_Materials[0]);
g_pWallMesh->DrawSubset(0);
//Step 6:绘制物体镜像
//Step 6.1
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true);//开启向深度缓存的写操作
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);//设置比较方法
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);//设置模板测试成功后更新模板的方式
//Step 6.2:清空深度缓存
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(80,80,80),1.0F,0);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTALPHA);//源融合因子设为目标Alpha
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);//目标融合因子设为0
//Step 6.3:设置镜面变换矩阵
D3DXMATRIX matReflect,matMirror;
D3DXPLANE plane(1.0F,0.0F,1.0F,-6.0F);//平面 (x)+0*y+(z-6)=0即x+z-6=0;
D3DXMatrixReflect(&matReflect,&plane);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);//镜像翻转绘制背面,设置消隐方式为顺时针
//茶壶镜像
D3DXMatrixMultiply(&matMirror,&matWorld2,&matReflect);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror);
g_pd3dDevice->SetMaterial(&g_Materials[1]);
g_pTeapotMesh->DrawSubset(0);
//球体镜像
D3DXMatrixMultiply(&matMirror,&matWorld3,&matReflect);
g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror);
g_pd3dDevice->SetMaterial(&g_Materials[2]);
g_pSphereMesh->DrawSubset(0);
g_pd3dDevice->EndScene();//结束绘制
}
g_pd3dDevice->Present(NULL,NULL,NULL,NULL);//翻转,显示
}
百度网盘