下面是我对模板缓存创建的理解:

1. 模板缓存是和深度缓存一起被创建的,将深度缓存的一部分作为模板缓存使用。

深度缓存和模板缓存是在Direct3D初始化时创建的,D3DPRESENT_PARAMETERS结构便包含了深度缓存和模板缓存的格式

typedef struct D3DPRESENT_PARAMETERS {
UINT BackBufferWidth;
UINT BackBufferHeight;
D3DFORMAT BackBufferFormat;
UINT BackBufferCount;
D3DMULTISAMPLE_TYPE MultiSampleType;
DWORD MultiSampleQuality;
D3DSWAPEFFECT SwapEffect;
HWND hDeviceWindow;
BOOL Windowed;
BOOL EnableAutoDepthStencil;
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags;
UINT FullScreen_RefreshRateInHz;
UINT PresentationInterval;
} D3DPRESENT_PARAMETERS,*LPD3DPRESENT_PARAMETERS;

D3DFORMAT          AutoDepthStencilFormat;

可以有以下取值:

D3DFMT_D24S8    创建一个32位深度/模版缓存,其中24位为深度缓存,8位为模版缓存。

D3DFMT_D24X4S4    创建一个32位深度/模版缓存,其中24位为深度缓存,4位为模版缓存,还有4位留着不用。

D3DFMT_D15S1    创建一个16位深度/模版缓存,其中15位为深度缓存,1位为模版缓存。

2. 使用模板缓存前需要启用模板缓存

下面是启用和关闭模板缓存代码

Device->SetRenderState(D3DRS_STENCILENABLE, true);
... // do stencil work
Device->SetRenderState(D3DRS_STENCILENABLE, false);

使用IDirect3DDevice9::Clear方法来清除模板缓存并让其拥有默认值。

Device->Clear(, ,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,
0xff000000, 1.0f, );

此时模板缓存中的模板值(Value)已被初始化为0

3. 模板缓存是用来阻止像素被写入后台缓存中的,如果像素不能被写入后台缓存,那么它也不能被写入深度缓存。

阻止像素被写入是通过模板测试来决定的,表达式为:

(ref & mask) ComparisonOperation (value & mask)

模版测试是对每个像素进行的,假设模版是被允许。将有两个操作:

  • 左手边操作数(LHS=ref&mask
  • 右手边操作数(RHS=value&mask

模版测试比较LHS和RHS,通过比较运算来指定。全部的运算都得到一个布尔值(true/false)。假如测试的结果是true,那么我们把像素写入后缓存。假如测试的结果是false,我们就阻止像素被写入后缓存。
设置渲染状态:

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);

设置模版比较运算为D3DCMP_ALWAYS,这就是说让所有模版测试都通过。

假如深度测试失败了,我们指定D3DSTENCILOP_KEEP,它表明不更新模版缓存入口,保存当前值。这样做的原因是假如深度测试失败了,那么就意味着像素被“模糊”了。我们不想渲染被“模糊”的反射像素。

同样假如模版测试失败了,我们也指定D3DSTENCILOP_KEEP。但是在这里这样做不是必须的,因为我们指定的是D3DCMP_ALWAYS,当然这样的测试也就永远不会失败。

假如深度测试和模版测试都通过了,我们就指定D3DSTENCILOP_REPLACE,更新模版缓存入口,设置模版参考值为0x1。

4. 更新模板缓存,因为测试总是通过,所以被渲染的部分替换为0x1,其他部分为0

更新模板缓存前,先阻止向深度缓存写入

 // 禁用向模板 深度(Z)缓冲区进行写
Device->SetRenderState(D3DRS_ZWRITEENABLE, false);
Device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

将源融合因子和目标融合因子分别指定为D3DBLEND_ZERO和D3DBLEND_ONE防止对后台缓存进行更新,

    //设置 源融合因子和 目标融合因子
Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

将镜子写入模板缓存

Device->SetStreamSource(, VB, , sizeof(Vertex));
Device->SetFVF(Vertex::FVF);
Device->SetMaterial(&MirrorMtrl);
Device->SetTexture(, MirrorTex);
D3DXMATRIX I;
D3DXMatrixIdentity(&I);
Device->SetTransform(D3DTS_WORLD, &I);
Device->DrawPrimitive(D3DPT_TRIANGLELIST, , );

在模版缓存中,符合镜子可视像素的为0x1,其他像素为0

至此,模板缓存已创建完成。

......

D3D 模板缓存的创建过程的更多相关文章

  1. [ZZ] D3D中的模板缓存(3)

    http://www.cppblog.com/lovedday/archive/2008/03/25/45334.html http://www.cppblog.com/lovedday/ D3D中的 ...

  2. mybatis缓存创建过程

    带着 上篇 的问题,再来看看mybatis的创建过程 1.从SqlSessionFactoryBuilder解析mybatis-config.xml开始 对文件流解析 XMLConfigBuilder ...

  3. ASP.NET Web API 控制器创建过程(二)

    ASP.NET Web API 控制器创建过程(二) 前言 本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病 ...

  4. ASP.NET Web API 控制器创建过程(一)

    ASP.NET Web API 控制器创建过程(一) 前言 在前面对管道.路由有了基础的了解过后,本篇将带大家一起学习一下在ASP.NET Web API中控制器的创建过程,这过程分为几个部分下面的内 ...

  5. .NET/ASP.NET MVC Controller 控制器(IController控制器的创建过程)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...

  6. IController控制器的创建过程

    .NET/ASP.NET MVC Controller 控制器(二:IController控制器的创建过程)   阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactor ...

  7. 三、ASP.NET MVC Controller 控制器(二:IController控制器的创建过程)

    阅读目录: 1.开篇介绍 2.ASP.NETMVC IControllerFactory 控制器工厂接口 3.ASP.NETMVC DefaultControllerFactory 默认控制器工厂 4 ...

  8. spring的bean创建过程

    Spring的bean创建过程 步骤 执行过程 描述 1 ThreadLocal.set bean创建之前将beanName的一些属性放进ThreadLocal,避免多线程创建bean导致问题,并发创 ...

  9. 0003 - 基于xml的Spring Bean 的创建过程

    一.目录 前言 创建 Bean 容器 加载 Bean 定义 创建 Bean Spring Bean 创建过程中的设计模式 总结 二.前言 2.1 Spring 使用配置 ApplicationCont ...

随机推荐

  1. ACM常用算法及练习(1)

    ACM常用算法及练习 第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来. 1.最短 ...

  2. C++之路进阶——bzoj1468(tree)

    F.A.Qs Home Discuss ProblemSet Status Ranklist Contest ModifyUser  gryz2016 Logout 捐赠本站 Notice:由于本OJ ...

  3. strcpy  复制字符串函数

    #include<stdio.h> #include<assert.h> char *strcopy(char * strDest , const char * strSrc) ...

  4. vs2010的快捷键

    vs2010的快捷键 VS2008快捷键大全 Ctrl+m+Crtr+o折叠所有大纲Ctrl+M+Crtr+P: 停止大纲显示Ctrl+K+Crtr+C: 注释选定内容Ctrl+K+Crtr+U: 取 ...

  5. c语言 typedef

      在C和C++编程语言中,typedef是一个关键字.它用来对一个资料类型取一个新名字.目的是为了使源代码更易于阅读和理解. 来看以下程式码: int coxes; int jaffa; ... c ...

  6. [Ubuntu] Remove Byte Order Mark (BOM) from files recursively [Forward article]

    Original article: http://www.yiiframework.com/wiki/570/remove-byte-order-mark-bom-from-files-recursi ...

  7. sp_addlinkedserver 方法应用

    EXEC  sp_addlinkedserver      @server='DBVIP',--被访问的服务器别名       @srvproduct='',      @provider='SQLO ...

  8. oracle的面试问题

    1. Oracle跟SQL Server 2005的区别? 宏观上: 1). 最大的区别在于平台,oracle可以运行在不同的平台上,sql server只能运行在windows平台上,由于windo ...

  9. SQL 基础语法(创建表空间、用户、并授予权限、数据的增删改查) --(学习笔记)[转]

    --创建表空间 名:lyayzh_test create tablespace lyayzh_test --创建表数据文件 名:lyayzh_test_data.dbf 必须以dbf为后缀 dataf ...

  10. CSS的样式合并与模块化

    by zhangxinxu from http://www.zhangxinxu.com 原文地址:http://www.zhangxinxu.com/wordpress/?p=931 一.引言 本文 ...