【Visual C++】游戏开发笔记四十五 浅墨DirectX教程十三 深度测试和Z缓存专场

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。  

文章链接: http://blog.csdn.net/zhmxy555/article/details/8607864

作者:毛星云(浅墨)    邮箱: happylifemxy@163.com  



在游戏三维场景中,想创造出唯美而具画面感和真实感的画面,常常需要绘制大量的物体。而这些物体之间通常都存在着遮挡的关系,离观察点较远的物体,会因为近处物体的遮挡而不可见,或者只有部分可见。在Direct3D中,微软为我们提供了,深度缓存(或称Z缓存),配套着深度测试技术,来专门实现这种效果。下图是本篇文章配套程序的一个截图,可以发现,利用了深度测试,才能让战士与这个矩形墙面水乳交融,表达出这个战士似乎是从墙面中穿越而出的真实视觉效果。


 

 

所以,想要绘制出真实的游戏三维场景,深度测试便是必须之物。

本篇文章里,我们就来探究一下深度测试的方方面面。





 

一、形象化理解深度测试



首先奉上浅墨一直对深度测试的形象化理解。

把深度测试看做在一口井的井口处向井中观望。把所有物体都赋予一个深度值,放到井中来显示。深度越深的物体,离井口就越远。深度越浅的物体,离井口就越近。井表面的深度值为0。离井口近而深度浅的物体,可能会把离井口远的物体遮挡住。最终显示在屏幕上的开启深度测试后的画面,就如在井口处向井中观望里面物体显示出的遮挡与层次的效果一样。

(每次想到这里,浅墨就会联想起美剧《行尸走肉》第二季里面的农场里的那口井,可惜井中掉下去一个行尸,把井水污染了。。。。。)

当然,离井口的深度就是每个物体在世界坐标系中的矩阵的Z坐标值了。

 

 

然后,我们看一下深度测试的具体概念。



二、深度测试相关概念讲解



而想要理解深度测试,首先需要理解深度缓冲区。

深度缓冲区,也常常称为Z缓存,是Direct3D中用来存储绘制到屏幕上的每个像素点的深度信息的一块内存缓冲区,是一个只含有特定像素深度信息而不含图像数据的表面,深度缓存为最终绘制的图像中的每一个像素都保留了一个深度值,如果我们绘制屏幕的分辨率为800×600像素的话,那么深度缓存的大小也为800×600。

当Direct3D讲一个场景渲染来目标表面上时,它使用深度缓冲区来决定光栅化后各个多边形的像素前后的遮挡关系,最终决定哪个颜色值会被绘制出来。

所以可以这样理解,Direct3D通过比较当前绘制的像素点的深度和对应深度缓冲区的点的深度值来决定是否绘制当前像素。如果深度测试的结果为TRUE,就会绘制当前像素,并用当前像素点的深度值来更新一下深度缓冲区,反之,则不予绘制。而在通常情况下,深度缓冲区对应于屏幕大小的一块二维区域。

比如,我们在三维场景中同时绘制了一把长剑和一个盾牌两个立体模型。如果长剑的深度值为30,盾牌的深度值为60(  如取景变换中摄像机的位置矩阵在Z轴上为负值D3DXVECTOR3 vEye(0.0f, 1.0, -100.0f),长剑模型的世界矩阵为(0.0f,0.0f,30.0f),盾牌的世界矩阵为(0.0f,0.0f,60.0f)),那么就是表示长剑的盾牌的前面。Direct3D会首先绘制长剑和盾牌中的其一,而当绘制剩下的那个3D模型的时候,Direct3D会将当前3D模型位于同一位置的像素与已经绘制的像素(如果两者在该位置都有像素的话)进行测试,若当前像素比原来的像素更近(即深度值更小),那么将用当前像素来更新掉原来的像素(前提是),否则不予更新。

 

当Direct3D将一个场景渲染到目标表面的时候,它使用深度缓冲区决定光栅化后每个多边形的像素前后的遮挡关系,最终决定哪个颜色值被绘制出来,对于一个启用了深度缓冲区的场景进行光栅化操作时,表面上的每个值都要进行深度测试。

 

 

 

 

三、深度测试使用四步曲



在Direct3D中,使用深度测试有一个四步曲,但是这仅仅是一个按部就班的四步曲,后三步的顺序可以随意,只要在渲染前就可以了。而且由于Direct3D默认开启深度测试,甚至后面三步根本就不需要,就可以在程序中畅通无阻地使用深度测试。

但是,我们本着学知识的态度,依然是要介绍并掌握一下,这样在实现某些特殊渲染效果的时候才有“招”可用。就像现在有了游戏引擎,想要快速做一款游戏的话,完全可以去直接用现成的游戏引擎。但是那毕竟是别人的东西,是别人写出来的东西。如果本着学知识的态度的话,我们应该了解引擎的底层实现,知其然并知其所以然。这样,日积月累,才会显得功力比那些做表层学问的人们来得深厚,才能成为真正的技术大牛,实现起游戏画面优化来游刃有余,甚至有能力写出属于自己的游戏引擎。

好像一下扯远了,囧,还是拉回来吧。深度测试使用四步曲如下:


1.创建深度缓冲区

2.开启深度测试

3.设置深度测试函数

4.更新深度缓冲区

 

下面我们分别来详细讲解。

 

1.创建深度缓冲区


关于深度缓冲区的创建,因为是在Direct3D初始化时顺手创建的,所以我们在之前讲解Direct3D初始化时,在《【Visual C++】游戏开发笔记三十三 浅墨DirectX提高班之二 化腐朽为神奇:DirectX初始化四步曲》一文"Direct3D初始化四步曲之三:填内容"中就有提到。

回忆之前的Direct3D初始化四步曲知识,四步曲之三,其实从头到尾其实就是在填充一个D3DPRESENT_PARAMETERS结构体,下面我们先贴出这个结构体的原型:

 

  1. typedef struct D3DPRESENT_PARAMETERS {  
  2.  UINT               BackBufferWidth;  
  3.  UINT               BackBufferHeight;  
  4.  D3DFORMAT           BackBufferFormat;  
  5.  UINT               BackBufferCount;  
  6.  D3DMULTISAMPLE_TYPE MultiSampleType;  
  7.  DWORD              MultiSampleQuality;  
  8.  D3DSWAPEFFECT       SwapEffect;  
  9.  HWND                hDeviceWindow;  
  10.  BOOL                Windowed;  
  11.  BOOL                EnableAutoDepthStencil;  
  12.  D3DFORMAT          AutoDepthStencilFormat;  
  13.  DWORD               Flags;  
  14.  UINT               FullScreen_RefreshRateInHz;  
  15.  UINT               PresentationInterval;  
  16. } D3DPRESENT_PARAMETERS,*LPD3DPRESENT_PARAMETERS;  

 

其中的第十和第十一个参数是我们今天深度测试相关的。

       

◆第十个参数,BOOL 类型的EnableAutoDepthStencil,表示Direct3D是否为应用程序自动管理深度缓存,这个成员为TRUE的话,表示需要自动管理深度缓存,这时候就需要对下一个成员AutoDepthStencilFormat进行相关像素格式的设置。

◆第十一个参数,D3DFORMAT类型的AutoDepthStencilFormat,上面刚介绍过,如果我们把EnableAutoDepthStencil成员设为TRUE的话,在这里就需要指定AutoDepthStencilFormat的深度缓冲的像素格式。具体格式可以在结构体D3DFORMAT中进行选取。我们列举一些可以选取的值:

D3DFMT_D16 深度缓存用16位存储每个像素的深度值

D3DFMT_D24X8 深度缓存用24位存储每个像素的深度值

D3DFMT_D32深度缓存用32位存储每个像素的深度值

 

想要在之后绘制时使用深度测试的话,在这里就要把第十个参数EnableAutoDepthStencil设为true,表示让Direct3D创建并自行管理一个深度缓冲区。而第十一个参数AutoDepthStencilFormat用于设置一下深度缓存的格式,16位,24位,32位等等格式任选。


2.开启深度测试


这一步的主角依旧是我们的老朋友SetRenderState,我们在之前已经用过它和介绍过他无数遍了。因为这个函数的一个参数可以取各式各样的渲染状态和类型,所以注定了它是一个多面手。下面将要介绍的深度使用四步曲的后三步,全都拜倒在了SetRenderState的“石榴裙”之下。

先看一下我们正在讲解的第二步,开启深度测试。自然就是给SetRenderState两个参数取不同的值就可以了。将第一个参数设为D3DRS_ZENABLE,表示第二个参数将对深度测试的开启或者关闭进行设置,第二个参数设为TRUE或者FALSE,表示开启或者关闭深度测试。

我们这步的目的当然就是要开启深度测试,也就是这样写: 

  1. g_pd3dDevice->SetRenderState(D3DRS_ZENABLE,true);  //开启深度测试  

当然,要关闭深度测试的话,把第二个参数取false就可以了: 

  1. g_pd3dDevice->SetRenderState(D3DRS_ZENABLE,false); //关闭深度测试  

3.设置深度测试函数


还是那个神通广大的SetRenderState函数。对应于这一步的任务,我们把它的第一个参数设为D3DRS_ZFUNC,第二个参数设为想要进行使用的深度测试函数,在D3DCMPFUNC枚举类型中取值,这个D3DCMPFUNC枚举类型我们可以在MSDN中查到定义如下:

 

  1. typedef enum D3DCMPFUNC {  
  2.  D3DCMP_NEVER          = 1,  
  3.  D3DCMP_LESS           = 2,  
  4.  D3DCMP_EQUAL          = 3,  
  5.  D3DCMP_LESSEQUAL      = 4,  
  6.  D3DCMP_GREATER        = 5,  
  7.  D3DCMP_NOTEQUAL       = 6,  
  8.  D3DCMP_GREATEREQUAL   = 7,  
  9.  D3DCMP_ALWAYS         = 8,  
  10.  D3DCMP_FORCE_DWORD    = 0x7fffffff  
  11. } D3DCMPFUNC, *LPD3DCMPFUNC;  

 

下面我们通过一个表格,对这些枚举类型中的成员进行讲解说明:

枚举类型值

精析

D3DCMP_NEVER

深度测试函数总是返回FALSE

D3DCMP_LESS

测试点深度值小于深度缓冲区中相应值时,返回TRUE,为默认值

D3DCMP_QUAL

测试点深度值等于深度缓冲区中相应值时,返回TRUE

D3DCMP_LESSEQUAL

测试点深度值大于等于深度缓冲区中相应值时,返回TRUE

D3DCMP_GREATER

测试点深度值大于深度缓冲区中相应值时,返回TRUE

D3DCMP_NOTEQUAL

测试点深度值不等于深度缓冲区中相应值时,返回TRUE

D3DCMP_GREATEREQUAL

测试点深度值大于等于深度缓冲区中相应值时,返回TRUE

D3DCMP_ALWAYS

深度测试函数总是返回TRUE

D3DCMP_FORCE_DWORD

这个枚举值一般不用,保证将D3DCMPFUNC枚举类型编译为32位

 

一般我们都将深度测试函数设为D3DCMP_LESS,表示当测试点深度值小于深度缓冲区中相应值时,通过测试并绘制相关像素,这样没有被遮挡的物体才显示,被遮挡住的物体是不显示的。

这步里面也就是一句SetRenderState代码:

 

  1. g_pd3dDevice->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESS);  

 

4.更新深度缓冲区


配合第三步设置的深度测试函数,还需要设置深度测试成功时对深度缓冲区如何操作,是保持原来的深度值“按兵不动”呢,还是用当前像素的深度值来更新对应的数值“与时俱进”。

还是那个神通广大的SetRenderState函数。对应于这一步的任务,我们把它的第一个参数设为D3DRS_ZWRITEENABLE,表示在第二个参数里面将对深度缓冲区更改与否做出选择。第二个参数设为TURE的话,表示深度测试成功之后,用当前像素的深度值更新深度缓冲区对应的数值。第二个参数设为TURE是设置更新深度缓冲区时最常用的设置,同时也是默认值。反之,第二个参数设为FALSE,则表示尽管深度测试成功,还是不更新深度缓冲区对应的数值。

代码书写方面,就是这样写:

  1. g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true);   //深度测试成功后,更新深度缓存  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值