19 12
发新话题
打印

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

高光环境反射贴图

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

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

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

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


环境贴图

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

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


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

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

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

TOP

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

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


加入高光环境贴图的效果

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

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


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

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


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


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

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


c 叠加了高光的场景

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



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

TOP

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

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

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

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


环境光立方体

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

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

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



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

TOP

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







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

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


法线贴图

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



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



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


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

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


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

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



b 没有凹凸贴图

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



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



加了凹凸贴图



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



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



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

TOP

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


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

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

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

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

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



离屏渲染

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

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



示意:加入扰动

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

TOP

《半条命2》中的水

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


a 反射贴图

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


b 折射贴图

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


c 最终效果

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

TOP

4.小结



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



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

TOP

谢谢大家 不好意思 文章中忘了说,实际上所有这些贴图的混合都是要靠pixel shader的,光靠以前传统的多重贴图混合是极难办到的... 不靠piexl shader的话,极难在每个象素的级别上 按 照 法 线 贴 图 来从 多 张 光照图中取不同的象素颜色并进行混合。实际上混合的工作在hl2中都是在pixel shader中完成的,而且是在贴贴图画每个像素的过程中就混合了(包括对高光的叠加过程),而不是先渲出分开的画面然后再像photoshop那样的合成,这点没有说清,还请大家见谅(当然如果在较低版本的pixel shader中可能要用到多遍渲染)...本来准备分析一些pdf中的shader代码的... 另外,偶不是美工...偶也没做过什么cg作品(无论是静帧还是动画)...偶是程序员...

TOP

谢谢大家 不好意思 文章中忘了说,实际上所有这些贴图的混合都是要靠pixel shader的,光靠以前传统的多重贴图混合是极难办到的... 不靠piexl shader的话,极难在每个象素的级别上 按 照 法 线 贴 图 来从 多 张 光照图中取不同的象素颜色并进行混合。实际上混合的工作在hl2中都是在pixel shader中完成的,而且是在贴贴图画每个像素的过程中就混合了(包括对高光的叠加过程),而不是先渲出分开的画面然后再像photoshop那样的合成,这点没有说清,还请大家见谅(当然如果在较低版本的pixel shader中可能要用到多遍渲染)...本来准备分析一些pdf中的shader代码的... 另外,偶不是美工...偶也没做过什么cg作品(无论是静帧还是动画)...偶是程序员...

TOP

 19 12
发新话题