【寒江雪】模板技术
2017-01-08 18:09
204 查看
模板缓存
模板缓存是一个专门用于制作特效的离屏缓存。模板缓存的分辨率与之前讲过的后台缓存和深度缓存的分辨率完全相同,模板缓存的像素与后台缓存,深度缓存中的像素一一对应。正所谓人如其名,模板缓存,它能让我们动态地,有针对性地决定是否将某个像素写到后台缓存中。模板测试
在运用模板技术来进行特效的绘制时,需要精确到每个像素。我们会根据每个像素的模板缓存的值,进行一些检查,最后判断该点是否需要绘制。最终实现一些特殊效果。而这个检查的过程就是模板测试。模板测试的使用
创建模板缓冲区
Direct3D在创建深度缓存的同时创建了模板缓存,并且将深度缓冲区的一部分作为模板缓冲区使用。回忆一下创建深度缓存的时候是在Direct3DDevice初始化的时候,在结构体中填写了第十个参数EnableAutoDepthStencil和第十一个参数AutoDepthStencilFormat。
第十一参数可以从D3DFORMAT中取值,一般我们可以以下值中选取:
D3DFMT_D16 //深度缓存用16位存储每个像素的深度值 D3DFMT_D24S8 //深度缓存用24位存储每个像素的深度值,其中8位用于模板缓存 D3DFMT_D32 //深度缓存用32位存储每个像素的深度值
清除模板缓冲区
清除模板缓冲区涉及到IDirect3DDevice::Clear这个方法.这个方法在每次渲染之前都要先调用一次,这里再提一遍:
HRESULT Clear( [in] DWORD Count, [in] const D3DRECT *pRects, [in] DWORD Flags, [in] D3DCOLOR Color, [in] float Z, [in] DWORD Stencil );
调用Clear的时候,需要指定我们要清理的缓冲区.在第三个参数DWORD Flags中指定,该参数的值可以用 | 连接。我们可以这么填:
D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL
这表示清空后台缓存,深度缓存和模板缓存
模板测试相关参数介绍
使用模板测试实现各种各样效果的关键是正确设置与模板测试相关的各种渲染状态.设置渲染状态使用IDirect3DDevice::SetRenderState方法完成。它的第一个参数在庞大的枚举类型D3DRENDERSTATETYPE中取值,该枚举类型的部分构成如下:
typedef enum D3DRENDERSTATETYPE { ....................................... D3DRS_STENCILENABLE = 52, D3DRS_STENCILFAIL = 53, D3DRS_STENCILZFAIL = 54, D3DRS_STENCILPASS = 55, D3DRS_STENCILFUNC = 56, D3DRS_STENCILREF f271 = 57, D3DRS_STENCILMASK = 58, D3DRS_STENCILWRITEMASK = 59, ........................................ D3DRS_TWOSIDEDSTENCILMODE = 185, D3DRS_CCW_STENCILFAIL = 186, D3DRS_CCW_STENCILZFAIL = 187, D3DRS_CCW_STENCILPASS = 188, D3DRS_CCW_STENCILFUNC = 189, ......................................... } D3DRENDERSTATETYPE, *LPD3DRENDERSTATETYPE;
D3DRS_STENCILENABLE:这个渲染状态用于启用或禁用模板处理功能.
D3DRS_STENCILFALL:这个渲染状态表示模板测试失败时进行的模板操作。默认操作为D3DSTENCILCAPS_KEEP
D3DRS_STENCILZFAIL:该渲染状态表示模板测试通过,但深度测试失败时进行的模板操作。默认的操作时D3DSTENCILCAPS_KEEP
D3DRS_STENCILPASS:这个渲染状态表示模板测试通过时进行的模板操作。进行的摸默认操作时D3DSTENCILCAPS_KEEP
D3DRS_STENCILFUNC:这个渲染状态可以指定用于模板测试的比较函数。比较函数是D3DCMPFUNC枚举常量之一,该比较函数将通过模板掩码的模板参考值与模板缓冲区中当前像素模板值比较,如果为TRUE,则通过模板测试。
D3DRS_STENCILREF:这个渲染状态用于设置模板参考值,默认为0
D3DRS_STENCILMASK:这个渲染状态用于设置模板掩码,决定对模板参考值和模板缓冲区值的哪位进行比较。默认值为0xffffffff
D3DRS_STENCILWRITEMASK:这个渲染状态用于指定写入模板缓冲区中的数值的掩码,默认值为0xffffffff
D3DRS_TWOSIDEDSTENCILMODE:这个渲染状态英语激活或启用双面缓冲区
D3DRS_CCW_STENCILFAIL:这个渲染状态用于设置在启用了双面模板缓冲区后,顶点按照逆时针顺序组成的多边形当模板测试失败时进行的模板操作。
D3DRS_CCW_STENCILZFAIL:这个渲染状态用于设置在启用了双面模板缓冲区后,顶点按照逆时针顺序组成的多边形当模板测试通过但深度测试失败时进行的模板操作。
D3DRS_CCW_STENCILPASS:这个渲染状态用于设置在启用了双面模板缓存后,顶点按照逆时针顺序组成的多边形当模板测试成功时进行的模板操作。
D3DRS_CCW_STENCILFUNC:这个渲染状态指定了模板测试的比较函数。在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, /* force 32-bit size enum */ } D3DCMPFUNC;
枚举类型值 | 说明 |
---|---|
D3DCMP_NEVER | 深度测试函数总是返回FASLE |
D3DCMP_LESS | 测试点深度值小于深度缓冲区中相应值时,返回TRUE,默认值 |
D3DCMP_EQUAL | 测试点深度值等于深度缓冲区中相应值时,返回TRUE |
D3DCMP_LESSEQUAL | 测试点深度值小于等于深度缓冲区相应值时,返回TRUE |
D3DCMP_GREATER | 测试点深度值大于深度缓冲区相应值时,返回TRUE |
D3DCMP_NOTEQUAL | 测试点深度值不等于深度缓冲区相应值时,返回TRUE |
D3DCMP_GREATEREQUAL | 测试点深度值大于等于深度缓冲区相应值时,返回TRUE |
D3DCMP_ALWAYS | 测试始终为TRUE |
D3DCMP_FORCE_DWORD | 这个枚举一般不用,保证将D3DCMPFUNC枚举类型编译为32位 |
上面我们讲到的渲染状态D3DRS_STENCILFAIL,D3DRS_STENCILZFAIL,D3DRS_STENCILPASS定义了模板测试,深度测试失败或者通过时进行的模板操作,它们也是在一个枚举类型中取值,这个枚举类型是D3DSTENCILOP,其定义如下:
typedef enum D3D11_STENCIL_OP { D3DSTENCILOP_KEEP = 1, D3DSTENCILOP_ZERO = 2, D3DSTENCILOP_REPLACE = 3, D3DSTENCILOP_INCR_SAT = 4, D3DSTENCILOP_DECR_SAT = 5, D3DSTENCILOP_INVERT = 6, D3DSTENCILOP_INCR = 7, D3DSTENCILOP_DECR = 8, D3DSTENCILOP_FORCE_DWROD=0x7fffffff } D3DSTENCILOP,*LPD3DSTENCILOP;
枚举类型值(模板操作) | 精析 |
---|---|
D3DSTENCILOP_KEEP | 是默认的选项。表示不更新模板缓冲区中的值 |
D3DSTENCILOP_ZERO | 将模板缓存中的值置零 |
D3DSTENCILOP_REPLACE | 用模板参考值替换模板缓冲区中对应的值 |
D3DSTENCILOP_INCR_SAT | 增加模板缓冲区中的对应数值,如果大于最大值则取最大值 |
D3DSTENCILOP_DECR_SAT | 减小模板缓冲区中的对应数值,如果小于最小值则取最小值 |
D3DSTENCILOP_INVERT | 倒置模板缓冲区中对应的数据位 |
D3DSTENCILOP_INCR | 增加模板缓冲区中对应的数值,如果大于最大值则取0 |
D3DSTENCILOP_DECR | 减小模板缓冲区中对应的数值,如果小于0则等于最大值 |
D3DSTENCILOP_FORCE_DWROD | 这个枚举值一般不用,用于保证将D3DCMPFUNC枚举类型编译为32位 |
对模板测试的理解
模板测试使用模板参考值,模板掩码,模板比较函数和当前像素在模板缓冲区中的模板值作为参数,判断某个像素是否被写入到后台缓冲区中。模板测试的表达式如下:result=(ref & maskref)OP(value & maskwrite)
其中的ref表示模板参考值,mask表示模板掩码,value表示模板缓冲中的值,OP表示模板比较函数.
在Direct3D进行模板测试之前,我们需要对模板测试的模板参考值,模板掩码和模板比较函数做一下设置。模板参考值的默认值是0,需要我们另外设置。
镜面效果示例代码
//绘制镜面 g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_BoxWorld); g_pd3dDevice->SetMaterial(&g_pBoxMat); g_pBoxMesh->DrawSubset(0); g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, true);//开启模板缓存 g_pd3dDevice->SetRenderState(D3DRS_STENCILREF, 0x1); //设置模板参考值 g_pd3dDevice->SetRenderState(D3DRS_STENCILMASK, 0xffffffff);//设置模板掩码 g_pd3dDevice->SetRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);//设置模板写掩码 g_pd3dDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);//设置比较函数,这里取总是通过 g_pd3dDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);//设置通过后的操作,这里设置为将参考值写入模板缓存 g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, false);//禁用深度缓存 g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);//开启混合模式 g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); //绘制镜面 这里只写模板缓存 g_pd3dDevice->SetTransform(D3DTS_WORLD, &g_BoxWorld); g_pd3dDevice->SetMaterial(&g_pBoxMat); g_pBoxMesh->DrawSubset(0); g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, 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); D3DXMATRIX matReflect; D3DXPLANE planeXY(0.0f, 0.0f, 1.0f, 0.0f); D3DXMatrixReflect(&matReflect, &planeXY); matHero = matHero*g_matWorld; //计算镜像相对于本体的位置 matWorld = matReflect*matHero; //绘制镜像 g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld); for (DWORD i = 0; i < g_dwNumMtrls; i++) { g_pd3dDevice->SetMaterial(&g_pMaterials[i]); g_pd3dDevice->SetTexture(0, g_pTextures[i]); g_pMesh->DrawSubset(i); } //恢复渲染状态 g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, false); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
Copyright© by 寒江雪
Date:2017.1.8
相关文章推荐
- 【寒江雪】模板技术实现镜面特效
- 网站内容管理平台java利用模板技术生成静态html
- STL运用的C++技术(3)——模板实参推断 .
- 技术QA:如何找回丢失的证书模板或将独立CA转换成企业CA?
- 【转】ASP模板技术
- 利用PHP与Smarty模板技术生成分页静态页面的代码
- [导入] * 网站首页 * 技术论坛 * 书籍收藏 * 日志标签 * 网友评论 * 友情链接 * 注册 * 登录 Visual Studio创建项模板心得
- MVC框架视图及页面跳转分析-模板技术
- php模板技术
- Smarty模板技术
- Smarty模板技术、安装以及Smarty中的变量
- 项目模板与项模板技术 -- VS2008
- OSCommerce_3 使用的模板技术介绍(英文)
- 基于Freemarker模板技术的分页组件设计
- 我的C++实践(4):trait与policy模板技术
- 用友致远协同办公系统(OA)A6标准方案模板(解决方案、技术方案)
- C++模板技术实例(2) 静态多态
- ATL布幔下的秘密之模板技术 模板模拟编译时多态
- 基于模板的通用代码生成器LKGenerator(四)-核心技术之各种数据库查询表信息sql整理
- 写技术文档,要不要用文档模板?