Direct3D学习手记八:模板技术【镜面效果】
2013-12-28 14:15
204 查看
本文介绍模板技术并实现镜面效果
模板缓存:
模板缓存和深度缓存是同时创建的,在指定深度缓存格式的时候,模板缓存的格式也被同时指定了,语句如下:d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;//24位深度缓存,8位模板缓存模板缓存的分辨率与深度缓存和后台缓存的分辨率大小相同,
屏幕上的某个像素点都对应着模板缓存、深度缓存和后台缓存中的某个像素值。
模板缓存与深度缓存类似,都需要通过特定的比较来判断是否更新后台缓存的像素,即也有模板测试过程。
启用模板缓存:
要使用模板缓存必须开启其状态,默认为关闭状态,g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,true);//开启模板缓存另外在执行清屏动作时,还要使用D3DCLEAR_STENCIL清除模板缓存:
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,D3DCOLOR_XRGB(80,80,80),1.0,0);
模板测试:
模板测试的效果与深度测试类似,都是通过特定的比较方式判断某个像素是否应该被写入后台缓存。测试表达式:
result=(ref & mask) OP (value & writemask)result为比较结果,ref为模板参考值,mask为模板参考值的掩码,value为当前像素的值,writemask为当前像素的掩码
设置模板参考值:
g_pd3dDevice->SetRenderState(D3DRS_STENCILREF,0x1);//设置模板参考值
设置模板参考值的掩码:
g_pd3dDevice->SetRenderState(D3DRS_STENCILMASK,0xffffffff);//设置模板测试掩码
设置当前像素的掩码:
g_pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff);//设置模板写掩码
OP为比较方式为D3DCMPFUNC枚举成员:
typedef enum D3DCMPFUNC { D3DCMP_NEVER = 1, D3DCMP_LESS = 2, D3DCMP_EQUAL = 3, D3DCMP_LESSEQUAL = 4, D3DCMP_GREATER = 5, D3DCMP_NOTEQUAL = 6, D3DCMP_GREATEREQUAL = 7, D3DCMP_ALWAYS = 8, D3DCMP_FORCE_DWORD = 0x7fffffff, } D3DCMPFUNC, *LPD3DCMPFUNC;设置比较方式:
g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_ALWAYS);//设置比较方法
更新模板缓存:
在测试完成判断某个像素是否写入后台缓存后,要更新模板缓存,必须为其制定更新方式:1.在模板测试失败时更新
g_pd3dDevice->SetRenderState(D3DRS_STENCILFAIL,StencilOperation);2.在深度测试失败时更新
g_pd3dDevice->SetRenderState(D3DRS_STENCILZFAIL,StencilOperation);3.在模板测试和深度测试都成功时更新
g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,StencilOperation);其中,StencilOperation为D3DSTENCILOP枚举的成员:
typedef enum D3DSTENCILOP { D3DSTENCILOP_KEEP = 1, D3DSTENCILOP_ZERO = 2, D3DSTENCILOP_REPLACE = 3, D3DSTENCILOP_INCRSAT = 4, D3DSTENCILOP_DECRSAT = 5, D3DSTENCILOP_INVERT = 6, D3DSTENCILOP_INCR = 7, D3DSTENCILOP_DECR = 8, D3DSTENCILOP_FORCE_DWORD = 0x7fffffff, } D3DSTENCILOP, *LPD3DSTENCILOP;
镜面效果:
实现步骤:
1.执行清屏操作Clear,指定D3DCLEAR_STENCIL标志清除模板缓存
//Step 1:清屏,颜色设为灰色,深度缓存置为1.0,模板缓存置为0 g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,D3DCOLOR_XRGB(80,80,80),1.0,0);
2.禁用模板缓存,绘制一般场景,包括镜面
//绘制镜面 D3DXMatrixTranslation(&matWorld1,0.0F,0.0F,6.0F); D3DXMatrixRotationY(&Ry,D3DX_PI/4.0F); D3DXMatrixMultiply(&matWorld1,&Ry,&matWorld1); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1); g_pd3dDevice->SetMaterial(&g_Materials[0]); g_pWallMesh->DrawSubset(0); //绘制茶壶 D3DXMatrixTranslation(&matWorld2,-1.0F,1.0F,1.0F); D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F); D3DXMatrixMultiply(&matWorld2,&matWorld2,&Ry); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld2); g_pd3dDevice->SetMaterial(&g_Materials[1]); g_pTeapotMesh->DrawSubset(0); //绘制球体 D3DXMatrixTranslation(&matWorld3,-1.0F,-1.0F,1.0F); D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F); D3DXMatrixMultiply(&matWorld3,&matWorld3,&Ry); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld3); g_pd3dDevice->SetMaterial(&g_Materials[2]); g_pSphereMesh->DrawSubset(0);
3.启用模板缓存,并对模板参考值,模板掩码,更新方式进行设置
//Step 3:设置模板 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_STENCILPASS,D3DSTENCILOP_REPLACE);//设置模板测试成功后更新模板的方式为替换
4.关闭向深度缓存的写操作,开启融合技术,源融合因子设为0,目标融合因子设为1,最终得到目标颜色值
//Step 4:关闭向深度缓存的写操作,开启融合技术,源融合因子设为0,目标融合因子设为1 g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,false);//关闭向深度缓存的写操作 g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);//开启融合 g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);//源融合因子设为0 g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);//目标融合因子设为1
5.绘制镜面到模板缓存中
//绘制镜面 g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1); g_pd3dDevice->SetMaterial(&g_Materials[0]); g_pWallMesh->DrawSubset(0);
6.开启向深度缓存的写操作,重新设置模板的比较方式与更新方式
//Step 6.1 g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true);//开启向深度缓存的写操作 g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);//设置比较方法 g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);//设置模板测试成功后更新模板的方式
7.清空深度缓存,让镜像与镜面相融合
g_pd3dDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(80,80,80),1.0F,0); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTALPHA);//源融合因子设为目标Alpha g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);//目标融合因子设为0
8.重新设置消隐方式,因为镜像为物体的背面,其图元为逆时针,默认会被消隐,即看不到
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);//镜像翻转绘制背面,设置消隐方式为顺时针
9.设置镜面及镜面变换矩阵
D3DXMATRIX matReflect,matMirror; D3DXPLANE plane(1.0F,0.0F,1.0F,-6.0F);//平面 (x)+0*y+(z-6)=0即x+z-6=0; D3DXMatrixReflect(&matReflect,&plane);
10.绘制物体的镜像
//茶壶镜像 D3DXMatrixMultiply(&matMirror,&matWorld2,&matReflect); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror); g_pd3dDevice->SetMaterial(&g_Materials[1]); g_pTeapotMesh->DrawSubset(0); //球体镜像 D3DXMatrixMultiply(&matMirror,&matWorld3,&matReflect); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror); g_pd3dDevice->SetMaterial(&g_Materials[2]); g_pSphereMesh->DrawSubset(0);
Render函数源码:
/**************************************************************** *函数名 : Render *功能 : 场景绘制 *输入 : 无 *输出 : 无 *返回值 : 无 ****************************************************************/ void Render() { //Step 1:清屏,颜色设为灰色,深度缓存置为1.0,模板缓存置为0 g_pd3dDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,D3DCOLOR_XRGB(80,80,80),1.0,0); if(SUCCEEDED(g_pd3dDevice->BeginScene()))//开始绘制 { /*在此绘制其他*/ //Step :2:先绘制一般物体,先禁用模板缓存 g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE,false);//禁用模板缓存 //设置世界变换矩阵 D3DXMATRIX matWorld1,matWorld2,matWorld3,Ry; //绘制镜面 D3DXMatrixTranslation(&matWorld1,0.0F,0.0F,6.0F); D3DXMatrixRotationY(&Ry,D3DX_PI/4.0F); D3DXMatrixMultiply(&matWorld1,&Ry,&matWorld1); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1); g_pd3dDevice->SetMaterial(&g_Materials[0]); g_pWallMesh->DrawSubset(0); //绘制茶壶 D3DXMatrixTranslation(&matWorld2,-1.0F,1.0F,1.0F); D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F); D3DXMatrixMultiply(&matWorld2,&matWorld2,&Ry); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld2); g_pd3dDevice->SetMaterial(&g_Materials[1]); g_pTeapotMesh->DrawSubset(0); //绘制球体 D3DXMatrixTranslation(&matWorld3,-1.0F,-1.0F,1.0F); D3DXMatrixRotationY(&Ry,timeGetTime()/500.0F); D3DXMatrixMultiply(&matWorld3,&matWorld3,&Ry); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld3); g_pd3dDevice->SetMaterial(&g_Materials[2]); g_pSphereMesh->DrawSubset(0); //Step 3:设置模板 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_STENCILPASS,D3DSTENCILOP_REPLACE);//设置模板测试成功后更新模板的方式为替换 //Step 4:关闭向深度缓存的写操作,开启融合技术,源融合因子设为0,目标融合因子设为1 g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,false);//关闭向深度缓存的写操作 g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true);//开启融合 g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ZERO);//源融合因子设为0 g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);//目标融合因子设为1 //Step 5:绘制镜面到模板缓存中 //绘制镜面 g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld1); g_pd3dDevice->SetMaterial(&g_Materials[0]); g_pWallMesh->DrawSubset(0); //Step 6:绘制物体镜像 //Step 6.1 g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true);//开启向深度缓存的写操作 g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_EQUAL);//设置比较方法 g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_KEEP);//设置模板测试成功后更新模板的方式 //Step 6.2:清空深度缓存 g_pd3dDevice->Clear(0,NULL,D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(80,80,80),1.0F,0); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_DESTALPHA);//源融合因子设为目标Alpha g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ZERO);//目标融合因子设为0 //Step 6.3:设置镜面变换矩阵 D3DXMATRIX matReflect,matMirror; D3DXPLANE plane(1.0F,0.0F,1.0F,-6.0F);//平面 (x)+0*y+(z-6)=0即x+z-6=0; D3DXMatrixReflect(&matReflect,&plane); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);//镜像翻转绘制背面,设置消隐方式为顺时针 //茶壶镜像 D3DXMatrixMultiply(&matMirror,&matWorld2,&matReflect); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror); g_pd3dDevice->SetMaterial(&g_Materials[1]); g_pTeapotMesh->DrawSubset(0); //球体镜像 D3DXMatrixMultiply(&matMirror,&matWorld3,&matReflect); g_pd3dDevice->SetTransform(D3DTS_WORLD,&matMirror); g_pd3dDevice->SetMaterial(&g_Materials[2]); g_pSphereMesh->DrawSubset(0); g_pd3dDevice->EndScene();//结束绘制 } g_pd3dDevice->Present(NULL,NULL,NULL,NULL);//翻转,显示 }
程序运行结果:
源代码及工程文件下载地址:
百度网盘相关文章推荐
- Direct3D学习手记七:Alpha融合技术
- Direct3D学习手记二:绘制简单3D物体
- 利用模板缓存绘制镜面效果
- 网络技术学习手记2——数据链路层
- DirectX学习笔记(八):Direct3D融合技术详解及物体透明效果的实现
- Direct3D学习手记十一:网格二【从.x文件中加载网格】
- 网络技术学习手记4——路由
- Direct3D学习手记一:实现Direct3D程序框架
- Direct3D学习手记三:绘制彩色3D物体
- DirectX 9.0c游戏开发手记之“龙书”第二版学习笔记之6: Chap8: Drawing in Direct3D ---- Part II
- Atlas学习手记(13):使用TextBoxWatermark为TextBox加上水印效果
- accp6.0 《使用javascript增强交互效果》学习笔记ch6 表单基本验证技术
- mangos 学习笔记之一 ------ 模板技术使用
- 网络技术学习手记5——TCP/IP
- Atlas学习手记(13):使用TextBoxWatermark为TextBox加上水印效果
- DirectX 9.0c游戏开发手记之“龙书”第二版学习笔记之5: Chap7: Drawing in Direct3D ---- Part I
- Atlas学习手记(13):使用TextBoxWatermark为TextBox加上水印效果
- Direct3D学习手记九:字体
- Direct3D学习手记五:纹理映射
- Smarty模板技术学习