泡泡网服务器频道 PCPOP首页      /      正文

DX9压榨专家 半条命2神奇渲染引擎揭

    编者按:本篇文章系PCPOP特约作者刘宏春供稿。刘宏春现正攻读软件工程硕士学位,他从大学本科期间开始研究计算机图形学以及DirectX编程,2004年他作为队长和3D渲染引擎主程序员,率领【北京工业大学放飞技术网】共4名队员参加微软“创新杯”大赛DirectX 9渲染项目,从全世界几十个参赛队中脱颖而出参加在巴西进行的决赛,并且在决赛中以富有民族气息的作品《龙之传说》一举夺得全球总冠军。与很多玩家一样,刘宏春平时酷爱FPS类游戏,这次PCPOP在FPS超级大作《半条命2》发布之际所做的【相关专题】大受读者欢迎,因此特约他写出一篇专业性、权威性很强的《半条命2》核心渲染技术分析以回报广大读者们的支持,同时为我们的专题划上一个圆满的句号。

    本篇文章力图深入浅出的分析讲解《半条命2》使用的核心渲染技术,以及革命性的Source引擎是如何创造性的将DirectX 9的优势发挥到极至。我们的目标绝对不是让所有人都看不懂而大喊深奥,而是让游戏玩家、DirectX程序员以及3D建模人员等不同层次和领域的读者都能够有所收获。因此我建议大家慢慢看完本篇文章,你们一定会有所收获!

    今年冬天,Valve给我们带来了2004年最令人期待的游戏大作之一——《半条命2》。相信玩过该游戏的玩家都对其中自然的光影效果、丰富的细节有着很深的印象,下面就让我们来看一看《半条命2》 的世界是如何呈现在大家的屏幕上的吧。

1.  《半条命2》中的创新理念-光能传递凹凸贴图 (Radiosity Normal Mapping)

    使光影效果更加真实自然——“光能传递(Radiosity)”

    为了使场景中的光照效果真实自然,《半条命2》 中对光影的处理使用了一种叫“光能传递”的技术。光能传递简单来说就是光的能量通过不断反射、折射,而在各个物体的表面间互相传递的过程。

    各位读者都知道,我们所在的真实世界中,不仅仅是像镜子这样表面光滑的物体能够反射光线,而是基本上所有的物体的表面都会或多或少的把照射到上面的光线反射出去,这些光线就可以再照亮附近的其他物体。

    所以一个物体表面被照亮的时候,它接受到的光不仅来自于各种光源,而且还来自于由其他物体表面反射过来的光线;这样我们就可以把照射到物体表面的光线分为两类:直接光照和间接光照。直接光照是从光源直接来的光照,而间接光照就是指从其他物体的表面反射过来的光照。

    由于物体表面会被附近其他的物体遮挡住,根据遮挡程度不同,所受到的间接光照的光能也不均匀,造成角落里比较暗,平面的地方比较亮的效果。这就是光能传递最明显的特点。

    不要小看这个光能传递过程,它是在真实的漫反射光照中最为复杂的一个过程,也是在渲染计算机动画时提升画面真实度的极为重要的一个因素。<

    我们可以通过下面简单的两幅图来比较一下在三维动画软件中使用光能传递与否会给画面带来什么样的区别。

    这是一个十分简单的房间场景,房间的天花板上只有一个简单的聚光灯。两幅画面都是通过3DS MAX的默认渲染器渲染的:

 图1.a

    没有使用光能传递,场景只受到直接光照;没被聚光灯照到的地方就是一片漆黑,光照效果十分简单、生硬。

 图1.b

    使用光能传递算法渲染的效果,场景既受到聚光灯直接光照,也受到间接光照;即使没有受到灯光直射的天花板和墙壁上半部分也被从地面和墙壁下部反射过来的光线照亮。而且这些受间接光照的部分也是明暗不一的,比如墙角、柱子的顶部与天花板相接的部分就比墙面暗,因为这些部位接受到的间接光照能量比其他部位少。和图1.a相比,场景明暗层次丰富,光照效果柔和自然,真实感大大提高,但是实际上场景数据没做任何改动。

    在《半条命2》的渲染引擎中,就使用了这种光能传递技术。我们可以通过下面两张截图来对比一下,打开和关闭间接光照时游戏中的效果。

 图2.a

    只有直接光照,不使用光能传递。场景比较阴暗,明暗分界比较强烈和生硬,不自然。

 图2.b

    加入了间接光照。画面中即使没被灯光照亮的部分也比较明亮,且其明暗层次更加丰富一些,更接近于人的真实感受。

    目前计算光能传递的算法有很多种,其本质是计算出每个物体表面上每一点面积所接受到的全部的光能。接受到的光能越强,该点面积就越亮。而计算光能的关键步骤,实际上就是计算前面提到的间接光照效果的过程。

    尽管算法很多,可是无论哪一种都是十分复杂的。虽然现在的显示硬件性能已经大幅提高,但是像光能传递这种极为复杂的算法还是很难完全在游戏进行时用实时的方法来实现。

    所以,目前在游戏中一般是通过三维动画软件或者游戏开发者自己编写的光能传递计算程序,将场景中的静态光影效果事先计算好,并保存在关卡场景模型的光照贴图上或顶点颜色信息里,在游戏运行时直接使用这些贴图或顶点颜色就行了。<

    比较典型的例子是《波斯王子-时之沙》,该游戏的做法就是在3DS MAX中使用光能传递算法和美工手动调节相结合,把光照效果预先保存在关卡场景网格模型的每个顶点颜色中,从而在游戏中达到一种奇幻、柔和、自然的光影效果。

 图3.abcd 《波斯王子-时之沙》中基于顶点的静态光效<

    除了保存在顶点的颜色信息里,保存在光照图中也是一个好办法。现在的主流三维动画软件如3DS MAX、Maya、SoftImage等等基本上都支持将光照效果直接渲染到场景物体的贴图上。下面就是一个使用光照贴图的简单例子。

 图3.e 物体本身材质贴图

 图3.f光照贴图

 图3.g使用该光照贴图后的效果

    使场景细节更加丰富-“凹凸贴图”

    相信大家都已经对“凹凸贴图”的概念不陌生了,尤其是在ID的大作《DOOM III》推出之后。可以说该游戏对凹凸贴图的使用已经到了登峰造极的地步。我们可以比较一下在DOOM III中打开和关闭凹凸贴图的效果对比:

 图4.a 打开凹凸贴图

 图4.b 关闭凹凸贴图

    在众多种类的凹凸贴图中,最主要的一种就是“法线贴图”了。《半条命2》、DOOM III和虚幻引擎3中使用的都是这种贴图。<

    “法线”的概念大家一定都很熟悉,一个平面的法线就是垂直于这个平面的向量。在计算机渲染图像时,法线的作用就在于计算平面的亮度。我们都知道,在一定光线照射下,一个平面的亮度是和光线入射角度有关的,光线越接近垂直入射,平面就越亮。

    由于平面的法线可以代表这个平面的方向,所以计算机就是通过比较平面法线向量和入射光线向量的方向来计算平面亮度的。

    我们可以想象一个平面上有着密密麻麻的法线;如果所有这些法线都朝向同一个方向,那么计算得到的这个平面的亮度就是一致的;但是如果人为的给这些法线加一些扰动,使他们朝向不同的方向,那么计算得到这个平面的亮度就是明暗不一的了,给人一种凹凸不平的感觉。

    但是,“扰动”并不是随便乱加的。为了控制对法线扰动的布局和程度,可以使用“法线贴图”。所谓的“法线贴图”,就是用来记录下物体表面各点的法线的贴图。

     

图5 DOOM III 中的法线贴图

    在本站的另一篇文章【纹理压缩的奇妙之旅 漫谈X800的3Dc技术】中,对法线贴图的概念有详细的阐述。

    在新一代的游戏引擎中,为了使物体凹凸效果逼真,大部分物体(尤其是角色模型)的法线贴图都是通过比较高、低多边形数量的两个版本的模型来生成的。拿虚幻引擎3的角色模型来说,高多边形版本的模型(简称高多边形模型)一般都会有几百万个面,拥有丰富的细节;而低多边形模型只有几千个面。真正在游戏中使用的是低多边形的模型。

 图6.a 虚幻引擎3中的高多边形模型

 图6.b 虚幻引擎3中的低多边形模型

    在制作法线贴图时,将高多边形模型上每个多边形的法线和低多边形模型对应部位法线相比较,得出的差值再置入法线贴图中。通过把这张法线贴图赋予低多边形模型,并实时计算光照,就可以使得渲染出的低多边形模型的凹凸感与高多边形模型十分接近。

 图6.c 虚幻引擎3中低多边形角色实时光影效果<

    新的理念:“光能传递”和“凹凸贴图”的有机结合,《半条命2》渲染的核心技术

    正如前面所述,实际上在《半条命2》出现以前,就有一些游戏中已经使用到了光能传递技术和凹凸贴图技术了。但是,还没有一款游戏能把这两种技术很好的结合起来。因为光能传递技术是比较侧重对场景中的静态光照进行预先处理和场景的整体光照效果;而凹凸贴图技术则相反,只有在动态光照的情况下,它的效果才会比较明显,而且比较侧重物体表面细节;确实是很难将这两种技术很有效的用在一起既表现出可信的光影效果,同时又照顾到物体表面细节的。

    所以我们不得不说Valve在其Source引擎中使用的这种光能传递凹凸贴图技术是一项创举。它实现了两者的有机结合,同时发挥了光能传递技术和凹凸贴图技术的优点,而且具有很高的执行效率。所以这项技术成为了Half-Life2/Valve Source引擎的关键核心技术。

    那么,在下面的部分中我们就来看一看这种技术的具体实现吧。<

    2.照亮《半条命2》的世界-区分对待静态场景和动态模型

    在《半条命2》/Valve Source引擎中,静态的世界场景(地形,建筑……)和动态的模型(角色,箱子,车辆……)是被分开对待的,因为他们有着不同的特性。静态世界场景是那些不变的、规模比较巨大的三维网格模型;而动态模型是那些较小的、无论是在场景中的位置还是自身形状会变化的三维网格模型。对于前者的绘制,Source引擎使用一种称为“光能传递光照贴图(Radiosity light maps)”的技术;对于后者,使用一种称为“环境光立方体(Ambient cube)”的技术。

    在分别介绍这两种技术之前,先对“光能传递法线贴图(Radiosity Normal Mapping)”作一个整体的介绍。在传统的法线贴图技术中,一般每渲染一次物体的时候只能使用一盏灯光,这是由于受到光照算法的约束;当场景中有多盏灯光时,就只能把每次计算得到的光照效果叠加起来。下面的示意图说明了这种情况:

 图7.a 先画出一盏灯光的效果

 图7.b 另一盏灯光,需要再画一遍物体

  图7.c 两图叠加

    这种做法最典型的例子就是DOOM III了。在DOOM III中由于针对每盏灯光,都要重新绘制一遍物体,所以在同一帧里每个物体同时受到的光源个数是有限制的。这也是为什么DOOM III 的场景都做得比较昏暗的原因。<

    而使用“光能传递法线贴图”技术的《半条命2》,在每一帧绘制物体的时,都允许它受到任意多盏灯光的照射。这就是它比较先进的地方。但是有一个前提就是这些灯光必须都是静态的,也就是说,无论位置、颜色和亮度都不能变。

    前面已经提到过“光照贴图”这种技术了。在以前通过传统的光能传递算法来计算光照贴图时,都是仅仅根据所接受到的光线的颜色和亮度计算出物体表面上每一点对应到光照图中一个象素的一份颜色值,也就是说一个面上同时只有一张光照图。而在“光能传递法线贴图”技术中,每一个面同时都对应着三张光照图。那么为什么会是三张光照图呢?

    原来为了在用光照图的同时使用凹凸贴图,Valve的程序员们为场景的每个多边形本身加上了一个小的局部三维坐标系。我们都知道一个三维坐标系(或坐标空间)是由三条互相垂直的轴来确定的,而与这三条轴方向相同并且长度是1的三根向量,就称为这个坐标空间的三个基向量(Basis)。

    在《半条命2》中,这个局部三维坐标系是这样的:

 图8.b 《半条命2》 每个多边形上的局部坐标系和基向量。

    使用这三个基向量所代表的三个方向,Valve的程序员们在每个方向上计算一次光能传递的效果,就形成了三张不同的光照贴图。具体的光能传递算法,Valve并没有透露。

    总之就是根据这三个方向,将原来的一张光照图分为对应的三张光照图,而且保证当物体表面的某个法线越偏向于其中一个方向时,它所应该接受到的光照颜色就越接近于对应的光照图上的颜色。
 
    下面我们就来看一下针对静态场景和动态模型,Source引擎是如何分别使用光能传递法线贴图技术的。<

    《半条命2》静态场景的光影效果

    这是一张使用《半条命2》渲染技术的典型的静态场景截图。除了火焰之外,场景中其他部分全是静态的。前面说过,对于这种大型静态场景,Source引擎使用基于光照贴图(Radiosity light maps)的光能传递凹凸贴图技术。


 
 图9 所要达到的最终渲染效果

    从这张图中可以看出,场景里既有比较真实的光能传递的整体光照效果,石壁表面又有十分细致的凹凸贴图细节。


    核心技术-基于光照贴图(Radiosity light maps)的光能传递凹凸贴图技术

    我们先来看一下使用以前传统的光能传递算法计算出的单一光照贴图贴到场景中物体表面的效果(为了清楚的表现出光照,去掉了表面本身的贴图):

图10.a 单一光照贴图的效果

    前面说道,为了加入凹凸贴图效果,在《半条命2》 Source引擎中,对应场景里多边形本身局部坐标系的三个基向量,会预先计算出三张光照贴图来。当分别把它们贴到场景中时看起来是这样的:

 图10.b 针对第一个基向量计算的光照贴图的效果

 图10.c 针对第二个基向量计算的光照贴图的效果

 图 10.d 针对第三个基向量计算的光照贴图的效果

     我们可以看出,在这三张光照图中,同一部位上的光强和颜色都是不一样的。那么,这三张光照贴图又是如何结合起来的呢?这就需要通过物体表面法线贴图中的法线来从它们之间取值了。<

   我们先在场景里每个多边形上贴上法线贴图看看,结果是这个样子的:

 

 图11 物体表面的法线贴图

    看上去很诡异……实际上,法线贴图不是这样简单的贴到物体表面上去的,因为它保存的不是颜色颜色信息,而是物体表面上很多的三维法线向量。

    在绘制一帧图像中的每个象素时,Source引擎都将从法线贴图里取出这个象素对应到物体多边形表面上那个点的法线向量,与多边形的局部空间的每个基向量做点乘(点积)操作,得到一个0到1之间的浮点数。由于法线向量和基向量都是单位向量(长度为1的向量),而两个单位向量方向越接近,点乘的结果就越大(最大到1),所以就可以通过这个浮点数来“过滤”从该光照贴图里读出的颜色。我们用下面的公式来表示一下可能会更清楚:

象素的最终的颜色 =
第一张光照贴图中取出的颜色 × 法线与第一个基向量点积的结果
   + 第二张光照贴图中取出的颜色 × 法线与第二个基向量点积的结果
          + 第三张光照贴图中取出的颜色 × 法线与第三个基向量点积的结果

    这样就保证了象素上的法线越接近于哪个基向量,对应的从哪张光照图取出这个象素的颜色占的比重就越大。

    通过这步关键的计算,就可以把凹凸贴图和光照贴图结合起来了。这时的场景看起来像下面的样子:

 图12 通过法线贴图过滤组合后的光照效果,表面凹凸细节的效果已很明显

    下面的一张是最开始的单一光照贴图效果,拿过来比较一下:

    而物体表面本身也是有材质贴图的:

 图13 物体本身的材质贴图,没有加入光照

    然后,再用有凹凸细节的光照效果和物体表面本身的材质贴图相混合,就得到了漫反射部分的完整图像:

 图14 材质贴图混合了光照后的结果。

    实际上,在混合时只要把算出的光照颜色和材质本身颜色的红绿蓝三个通道分别相乘就行了。

    我们可以再将上面这张图和最开始只使用传统的单一光能传递光照图获得的效果作一个比较:

 图15 只使用单一光照图,很多沟壑的凹凸细节都没有

    OK,漫反射部分的实现原理基本就是这样了。下面我们来总结一下这个流程。

 图16.a 截取一部分图像来说明这个流程

 图16.b

    从左到右:首先使用法线贴图在三张光照贴图中取颜色值,混合成带有凹凸细节的光照贴图,然后乘以物体本身的材质颜色贴图,得到右边最终的效果。<

高光环境反射贴图

    前面说过,光照图法线贴图技术只适用于与玩家观察角度无关的漫反射光照。那么,在场景中物体表面的高光又是如何绘制的呢?

    如果按照传统的算法,对物体表面高光和反射的计算是整个光照计算中比较复杂的过程。它需要较多的向量运算和浮点数的乘方运算,而且由于它与玩家的视线方向有关,所以几乎每帧都要更新。

    为了提升效率,Valve的技术人员不使用传统的高光算法,而是使用性能较好的高光环境反射贴图的方法。

    所谓的环境反射贴图,就是把一个物体周围的环境投影到包围在这个物体的一个立方体上。我们可以把这个过程想象成在这个物体的位置上放一个90度视野的照相机,用它向东、南、西、北、天、地六个方向各拍一张照片,糊在一个房间的六个对应内壁上,这样当我们站在房间中间看时,就好像能看见所拍摄到的整个的环境一样。

 图18 环境贴图

    如果我们在这个房间的中间放置一个金属物体,那么它反射墙壁上的照片中的景象,与把它放在真正的景物环境中反射的景象就十分相似了。在计算机中,墙壁上的照片就相当于是环境贴图了。用这些“照片”来代替真正的景物来计算反射效果,会使计算量大大减轻。

    在《半条命2》中整个的工作流程是这样的:Valve的美工们先使用地图编辑器在关卡地图中放置一些“取样点”,实际上就是用来放置摄像机拍摄环境贴图的地方。具体放置的位置一般是在那些有高光和反射效果的物体附近。

 图19 美工在《半条命2》地图编辑器中向一个场景里放置的
环境贴图“取样点”

    然后,地图编辑器自动在场景的这些地方放置“摄像机”并预先“拍摄(渲染)”出环境贴图来。每一个点都有六个方向的贴图。

    在场景中有高光和环境反射效果的物体会根据离自己最近的“取样点”来决定使用哪张环境贴图。如果自动获得的效果不是很理想,美工也可以手动的将某个环境贴图赋给某个物体的某个多边形上。<

    在游戏进行中,Source引擎把环境贴图贴到物体上,并根据物体表面的法线以及游戏者的视线方向对贴图进行扭曲,使物体表面看起来好像在反射环境。

    下面这张图是最开始那个场景仅贴上环境贴图的效果。

 图20 加入高光环境贴图的效果

    可能有读者会问了:怎么这么黑呀?其实这是因为这些高光是要叠加到原来的画面上的。我们实际上是用高光贴图去“加亮”原来漫反射得到的颜色,所以这里黑的地方就相当于保持原来漫反射颜色不变,而亮的地方就是使原来的部分更亮。

    由于在从环境反射贴图中取哪个位置的象素的颜色是和物体表面法线有关的,所以仍然可以使用法线贴图中的法线信息,得到更细致的高光效果:

 图21 应用法线贴图来“扭曲”后的环境反射效果,
可以看出凹凸不平的表面上高光的感觉

    另外在材质不均匀的物体的表面上,并不是所有的地方都有高光效果的。有的地方高光就强烈一些,有的地方就弱一些。所以,Valve的技术人员会再加上一层贴图来“过滤”物体表面的高光。

 图22.a 物体表面的高光强度贴图,其中越白的地方高光强度就越大

  图22.b用高光强度贴图过滤高光后的效果,只有很少的高光被保留了下来

    最后,把高光叠加到场景中去,得到最终的效果:


 图22.c 叠加了高光的场景

    OK,现在让我们来补完一下整个的渲染流程吧:

 图23

    从左到右:首先通过法线贴图(Normal)来寻址环境反射贴图(Cube Map)和三张光照贴图(Lightmaps),得到的结果分别与高光强度贴图(Specular Factor)和物体材质颜色贴图(Albedo)混合相乘,得到物体表面颜色的高光部分和漫反射部分,这两部分再相加得到最终的效果。<

    《半条命2》动态物件和人物模型的光影效果

    前面介绍了静态场景的光影效果,下面我们来看看在《半条命2》中的动态模型是如何绘制的。

    核心技术-基于环境光立方体 (Ambient cube)的光能传递凹凸贴图技术

    由于动态模型的位置和形状都有可能发生变化,所以就不能像静态场景那样处理了。动态模型所受到的光照也是由直接光照和间接光照组成的。在Source引擎中,只能从照射一个模型的所有直接光源中选出有两个最主要的来使用比较复杂的光照公式进行实时计算,而其他比较次要的直接光源以及场景中的间接光源都会被预先保存到一个称为“环境光立方体”的东西中。

 图24 环境光立方体

    首先Valve的技术人员在关卡场景中放置一个虚拟的立方体,然后地图编辑器就分别对立方体的每个面计算出垂直通过这个面的环境光的颜色和强度。场景里那些比较次要(远或暗)的直接光源,也被计算在内。

    对于每个面都计算一个光照颜色,可以得到六个颜色,基本上代表了从四面八方射来的穿过这个体积中的所有比较次要的光线的信息。这六个颜色是可以预先计算出来保存在关卡场景数据里的。

    通过模型表面的法线来决定取这六个颜色的比重并将它们混合,就可以得到一种类似于光能传递的效果。在环境光立方体的六个面中,必然有至少三个面会在法线的相反方向,这些面的颜色忽略不计。所以一般只有另外三个面的颜色会用到。法线方向越正对哪个面,这个面对应颜色所占的比重就越大。

 图25

    用环境光立方体技术渲染的蚁狮模型,虽然没有加入凹凸贴图,但是已经有一种类似光能传递的效果。<

    在前面说道为了结合使用法线贴图,对于静态场景,一个面对应着三张光照贴图。而在这里也是类似的,一个动态模型对应着三个环境光立方体。这三个环境光立方体面上的颜色是分别根据各面局部坐标系的三个基向量来计算出来的。具体的算法由于太核心了,Valve目前也没有公布出来。

 图26.a.b.c分别使用相对于三个基向量的环境光照图和环境光立方体的效果

    我们把法线贴图贴到场景中看一看:

 图27 法线贴图

    按照和静态场景类似的方法用法线贴图来寻址环境光立方体的颜色,就可以得到下面的效果了:

    和前面没有凹凸细节的图对比一下吧:

    不要忘了,模型本身也是有材质贴图的。我们把它贴上去看一看:

 图29 模型自身的材质贴图,没有光照

    如果把光照效果和它混合,就成了这个样子:

 图30.a 混合操作依然是颜色各通道相乘。角色表面具有凹凸细节。

    和没有使用法线贴图的效果对比一下:

 图30.b 没有凹凸贴图

    漫反射的部分完成后,就该加入高光了。对于角色的高光,Source引擎仍然使用高光环境反射贴图。

 图31 完全的高光环境反射,也没有加入凹凸贴图,好一只光滑的金属蚁狮

 图32 加了凹凸贴图

 图33 高光强度贴图,也是越白的地方高光越强,
我们可以看出蚁狮表面的高光并不是很强的

 图34 用高光强度贴图去过滤高光

 图35 把高光叠加到漫反射部分上去,得到最后的效果<

    3.制造一个透明的世界——水、玻璃窗、反射和折射特效

 图37 《半条命2》中的反射、折射

    充分发挥DirectX9的动力-离屏渲染、反射和折射贴图技术

    在实现玻璃、水这样的反射和折射特效时,同很多DX9游戏一样,《半条命2》 Source引擎中活用了离屏渲染、反射和折射贴图技术。

    我们知道一般来说游戏的每一帧画面都是为了画到屏幕上的。但是现在的显示硬件不仅能够往屏幕上画,还能往贴图上画。这些贴图就可以再次赋到场景中的物体上去——这就是所谓的“离屏渲染”。

    这种技术可以实现很多有意思的效果,比如DOOM III和《半条命2》中实时的监视器屏幕、电视屏幕等等。它们就是通过先把监视器看到的场景或电视中的场景实时绘制到一张贴图上,再把它们贴到监视器或电视屏幕上去(还记得《半条命2》一开始出现在各种屏幕上的那个喋喋不休的老头吗?)

 图38 离屏渲染

    如果我们把场景中的一个多边形面所挡住的东西画到贴图上,再贴到这个面上去,那么这个面看起来就是透明的了;如果我们在贴这个贴图时做一个扰动,比如加一些水波或者凹凸的扰动,那么这个面看起来就像是水面或者凹凸不平的玻璃的折射的效果了。借助法线贴图和最新的DirectX 9.0 Pixel Shader技术,加入这个扰动的过程十分容易实现。

    我们不妨把要贴到这个面上的贴图叫做折射贴图;在向屏幕上绘制这个面的每一个象素时,根据这个象素的位置在面的法线贴图上得到一个法线,根据这个法线算出一个偏移后的位置,再根据它去折射贴图上取一个象素的颜色画到当前的这个象素上。这样就实现了“偏移”并可以用法线贴图来控制扰动的图案了。

 图39 示意:加入扰动

    下面我们就具体的看看《半条命2》中的水的效果是怎么实现的。<

    《半条命2》中的水

    首先我们来看反射。Source引擎首先将水面上要反射的景物上下颠倒地画在一张贴图上。

 图40.a 反射贴图

    然后是折射。将水下的景物画在另一张贴图上。

 图40.b 折射贴图

    然后将这两张贴图贴到水面的多边形上,同时根据凹凸贴图,使用Pixel Shader分别加入扰动,得到水的最终效果!简单吧。

 图40.c 最终效果

    如果没有DirectX 9.0中的Pixel Shader技术,想对反射和折射贴图进行象素级的扰动来实现这样的水面效果是十分困难的。<

    4.小结

    总之,Half Life2/Valve Source引擎对于大规模室外场景的光影表现是有着其独到之处的。尽管使用光能传递凹凸贴图技术只能达到一种“近似”真实而非“严格”真实的视觉效果(实际上现在的游戏引擎基本上不可能做到严格的真实),但是《半条命2》的图像从色彩、光影和各种特效上来说基本上算是比较“养眼”了。

    另外,在Source引擎中对DirectX 9.0技术的大量使用,给我们带来了很多与以前的游戏所不一样的视觉感受,例如场景中令人难忘的水面效果。可以说,《半条命2》是目前最能体现DirectX 9.0技术的游戏之一。<

0人已赞

关注我们

泡泡网

手机扫码关注