|
void RenderScene()
{
。。。。。。//省略了// draw the floor,// draw the walls
// draw the mirror
Device->SetMaterial(&MirrorMtrl);
Device->SetTexture(0, MirrorTex);
Device->DrawPrimitive(D3DPT_TRIANGLELIST, 18, 2);
}
void RenderMirror()
{
//
// Draw Mirror quad to stencil buffer ONLY. In this way
// only the stencil bits that correspond to the mirror will
// be on. Therefore, the reflected teapot can only be rendered
// where the stencil bits are turned on, and thus on the mirror
// only.
//
HRESULT hr = NOERROR;
hr = Device->SetRenderState(D3DRS_STENCILENABLE, true);
hr = Device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
hr = Device->SetRenderState(D3DRS_STENCILREF, 0x1);
hr = Device->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);
hr = Device->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
hr = Device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
hr= Device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
hr = Device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
// 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);
// 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);
// position reflection
D3DXMATRIX 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);
}
第一次的在RenderScene()draw the mirror是绘制到Back buffer.
第二次的draw the mirror,由于Device->SetRenderState(D3DRS_STENCILENABLE, true);
所以导致第二次的draw the mirror绘制到了stencil buffer。(这个理解时咱论坛的一个大哥指导后想到的
也不知对不对)
经过一系列的设置后,我们没有必要更新depth and back buffers,我们只想要 模版buffers.所以就有了下面的
设置
// 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);
之后,我们要画反射茶壶了,但是我们要
// re-enable depth writes
Device->SetRenderState( D3DRS_ZWRITEENABLE, true );
否则反射茶壶和茶壶将得到一样的 Z buffer(我想是这个样子的,虽然还不是很理解)
在下面这几句话中Clear是最最重要的,我想它仅仅Clear 反射茶壶的Z buffer,使它和镜子获得相同的 Z buffer
(这个是我猜想,请高手指正),要不怎么会Blend 啊?
// 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);
上面都好了,下面的三句话句话,决定了最后成败的关键,但是想不通为什么请高手指点
// Restore render states.
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
Device->SetRenderState( D3DRS_STENCILENABLE, false);
Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
还有就是上面分析都是我的猜想,请高手指正! |
|