directx初第十二卷

模版

声明变量

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,会直接崩溃。。。

文章目录
  1. 1. 模版
    1. 1.1. 声明变量
    2. 1.2. 创建模版缓冲区
    3. 1.3. 清除模版缓冲区
    4. 1.4. 模版参数
    5. 1.5. 绘制场景
    6. 1.6. 绘制镜像