//《第一部分》
Device->SetRenderState(D3DRS_STENCILENABLE, true);
Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);Device->SetRenderState(D3DRS_STENCILREF, 0x1);
Device->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
Device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
Device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
开启模板测试,模板测试是费时间的操作,没有必要的时候不要开启,开启后记得要关闭。
设置测试选项。
//end
// disable writes to the depth and back buffers
Device->SetRenderState(D3DRS_ZWRITEENABLE, false);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
// draw the mirror to the stencil buffer
Device->SetStreamSource(0, VB, 0, sizeof(Vertex));
Device->SetFVF(Vertex::FVF);
Device->SetMaterial(&MirrorMtrl);
Device->SetTexture(0, MirrorTex);
D3DXMATRIX I;
D3DXMatrixIdentity(&I);
Device->SetTransform(D3DTS_WORLD, &I);
Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);
该部分是禁止深度可写,阻止后台缓存更新,在模板缓存中标记镜面大小。表面上是往模板缓存上绘制镜面,实际是在模板缓存中标记哪个区域是下一步操作中指定的可视镜面区域。因为在该部绘制了镜面,那么在D3D内部实际是进行中模板测试。因为第一部分的设置项,绘制完和测试完后,模板缓存得到的是一块1的像素块。为啥在这一步模板测试通过了,绘制的壶没有出现在镜面上。原因就是下面的代码控制了,根据融合,当前绘制的像素是属于源像素,已绘制的像素(后台缓存中保留的像素)属于目的像素,在下面的设置就是忽略了源像素的绘制,直接保留了目的像素。实际上可以把前面先绘制的镜面去掉,同时在这里去掉融合操作,在该处统一绘制,减少了一次镜面绘制,提升效率。
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
//《第三部分》
// re-enable depth writes//恢复深度缓存可写,不恢复的话 下一次绘制的时候遮挡效果无法表现
Device->SetRenderState( D3DRS_ZWRITEENABLE, true );
// only draw reflected teapot to the pixels where the mirror
// was drawn to.
Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL);
Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
模板测试,判断指定符合区域的才把茶壶绘到镜面
//end
//《第四部分》
// position reflectionD3DXMATRIX W, T, R;
D3DXPLANE plane(0.0f, 0.0f, 1.0f, 0.0f); // xy plane
D3DXMatrixReflect(&R, &plane);
D3DXMatrixTranslation(&T,
TeapotPosition.x,
TeapotPosition.y,
TeapotPosition.z);
W = T * R;
// clear depth buffer and blend the reflected teapot with the mirror
Device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
// Finally, draw the reflected teapot
Device->SetTransform(D3DTS_WORLD, &W);
Device->SetMaterial(&TeapotMtrl);
Device->SetTexture(0, 0);
Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
Teapot->DrawSubset(0);
// Restore render states.
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
Device->SetRenderState( D3DRS_STENCILENABLE, false);
Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
//end
这里不明白为啥要特别处理背影消除,正常的情况下不是应该在镜子中绘制物品的背面吗,而物品的背面应该是没有光线,从而导致有暗影