模版
声明变量
ID3DXMesh* Teapot = 0;
ID3DXMesh* Mirror = 0;
创建模版缓冲区
跟深度一样
清除模版缓冲区
//其中D3DCLEAR_STENCIL清除模版区缓存
g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0L);
模版参数
D3DRS_STENCILENABLE //开启模版处理
D3DRS_STENCILFAIL //模版测试失败时操作
D3DRS_STENCILZFAIL //模版测试通过,但深度测试失败时操作
D3DRS_STENCILPASS //模版测试通过时操作
D3DRS_STENCILFUNC //模版测试比较
D3DRS_STENCILREF //模版参考值
D3DRS_STENCILMASK //模版掩码
D3DRS_STENCILWRITEMASK //写入模版缓存区的数值掩码
绘制场景
D3DXMATRIX MirrorW, TeapotW;
D3DXMatrixTranslation(&TeapotW, 1, 0, -2);
g_pd3dDevice->SetTransform(D3DTS_WORLD, &TeapotW);
g_pd3dDevice->SetMaterial(&red_mtrl);
Teapot->DrawSubset(0);
// 绘制出镜子
D3DXMatrixTranslation(&MirrorW, 0.0f, 0.0f, 0.0f);//给墙面的世界矩阵初始化
g_pd3dDevice->SetTransform(D3DTS_WORLD, &MirrorW);//设置墙面的世界矩阵
g_pd3dDevice->SetMaterial(&white_mtrl);//设置材质
Mirror->DrawSubset(0); //绘制墙面
//启用模板缓存
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_STENCILZFAIL, D3DSTENCILOP_KEEP);
g_pd3dDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
//进行融合操作,以及禁止向深度缓存和后台缓存写数据
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
// 绘制出镜子
D3DXMatrixTranslation(&MirrorW, 0.0f, 0.0f, 0.0f);//给墙面的世界矩阵初始化
g_pd3dDevice->SetTransform(D3DTS_WORLD, &MirrorW);//设置墙面的世界矩阵
g_pd3dDevice->SetMaterial(&white_mtrl);//设置材质
Mirror->DrawSubset(0); //绘制墙面
绘制镜像
//重置,将镜像与镜面进行融合运算,并清理一下Z缓存
g_pd3dDevice->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
D3DXPLANE planeXY(0.0f, 0.0f, 1.0f, 0.0f); // xy平面
D3DXMATRIX matReflect;
//标准化平面
D3DXPlaneNormalize(&planeXY, &planeXY);
//计算镜像变换矩阵
D3DXMatrixReflect(&matReflect, &planeXY);
D3DXMatrixTranslation(&TeapotW, 1, 0, -2);
D3DXMATRIX W = TeapotW * matReflect;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &W);
g_pd3dDevice->SetMaterial(&red_mtrl);
Teapot->DrawSubset(0);
//恢复渲染状态
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, false);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
效果
奇葩的Bug
D3DXMATRIX matReflect;
D3DXPLANE planeXY(0.0f, 0.0f, 1.0f, 0.0f); // xy平面
如果是先声明matReflect,会直接崩溃。。。