用模版缓存实现镜面效果
一直不知道那一堆长长的代码是什么意思,今天上课无聊的时候就在那里想,一不留神就想通了,真是谢天谢地!首先将模版缓存清空
Device->Clear( 0,
0,
D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, //清空模版缓存,深度缓存
0ff000000,//颜色
1.0f,
0)//清空后的模版缓存值
//接下来就是模版缓存进行设置
Device->SetRenderState(D3DRS_STENCILENABLE,true) //开启模版缓存
Device->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);//将模版测试设置为总是成功,因为我们是在画镜面,不管镜面如何,都要画上去
Device->SetRenderState(D3DRS_STENCILREF,0x1);//设置模版参考值为1,这样将会用0x1来标记镜面区域
Device->SetRenderState(D3DRS_STENCILMASK,0xffffffff);//设置模版掩码,0xffffffff表示不屏蔽任何位
Device->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff)//模版写掩码
Device->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE);//当模版测试成功时,便用模版参考值(0x1)去替换缓存中的值
Device->SetRenderState(D3DRS_ZWRITEENALBE,false);//关闭深处缓存的写功能,以便阻止对深缓存的更改
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);//开启ALPHA混合功能
Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);//将源融合因子设置为(0,0,0,0);
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);//将目标融合因子设置为(1,1,1,1);
//在这里画镜面,此时的镜面会通过模版缓存进行绘制,并且模版缓存中的代表镜面的部分被标记为0x1,而其它区域为0;
//接下来就要绘制我们的物体了
Device->SetRenderState(D3DRS_ZWRITEEABLE,true);//重新开启ZWRITE
Device->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);//将模版测试规则设置为相等
Device->SetRenderState(D3DRS_STENCILZFAIL,D3DSTENCILOP_KEEP);
Device->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_KEEP);//这两排表示如果深度和模版测试失败,则不对模版中的内容作更改
Device->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);//若测试成功也不对其作更改
//使用D3DXMatrixReflect(&R,&plane);求出物体的镜像,其中plane为镜面平面;
//若此时绘画我们会看不到物体,因为物体的深度大于镜面的深度,于是我们要清空深度缓存
Device->Clear(0,0,D3DCLEAR_ZBUFFER,0,1.0f,0);
//为了能达到物体在镜子中的效果,我们依然要用到ALPHA混合
Device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTCOLOR);//(Rd,Gd,Bd,Ad)
Device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);//(0,0,0,0);
//由于物体在镜面中的显示为物体的像,于是我们要变改镜像绘制时的背面消隐模式
Device->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);//顺时针
最后的工作就是绘制出你的物体,然后关闭开启的功能,并恢复消隐模式
Device->SetRenderState(D3DRS_ALPHABLEND,false);
Device->SetRenderState(D3DRS_STENCILENABLE,false);
Device->SetRenderState(D3DRS_CULLMODE,CCW);//恢复默认(逆时针)