一切为了更真实──显卡中的3D技术(三)

整机外设

  一、光照渲染效果

  现实世界中,光线往往是随着环境的改变而改变,而游戏为了模拟这种真实的环境,需要显卡做特效处理。例如向走廊中发射一枚火箭,在它穿过走廊的时候会依次照亮各个位置。当发光的火箭通过后,这些被照亮的地区会恢复原本的状态。很明显,要实现完美、自然的光照效果,需要是一个相当复杂的渲染过程。那么目前在游戏中如何实现光照效果呢?目前实现光照效果的主要方式有光照贴图(Lighting Map)和顶点光照(Vertex Lighting)。

  1.光照贴图(Lighting Map)

  光照贴图方式是最早应用的解决方案。光照贴图的工作原理是用纹理,或者是凹凸贴图去表现光源,只不过在需要光源的时候这个贴图才被激活。通常设计人员在设计游戏场景时将预先设计好的,用看上去像“光线”的纹理图片生成光照贴图,这样我们在预定的场景或即将发生的时间就能看见预先设计好的那幅光照贴图。下面我们介绍一下在游戏中如何通过光照贴图来实现动态光源的效果。以上面提到的发射火箭情形为例:如果火箭平行地通过一道砖墙,它的光芒发射出的光线将照亮墙壁,游戏会在墙壁上增加一个光源贴图显示出这种效果。光源贴图并不会改变砖块的色彩或物理外观;它只是在瞬间使砖块更亮,在火箭通过之后光源贴图就立刻被取消。这样的好处是有了光源变化的感觉,画面更真实,缺点是不属于实时渲染,图面相当死板、生硬,而且要花费大量时间去设计画面,这对于游戏开发来说无疑是浪费时间。此种方式一般应用于2D游戏和早期的3D游戏。随着GPU硬件T&L及顶点着色引擎的出现,已经将此种落后的光源渲染方式打入冷宫,一般仅用于静态光照效果。

  2.顶点光照(Vertex Lighting)

  在3D游戏中,一般的光源信息都是包含在三角形的顶点数据之中的,显卡在处理完多边形的转换之后就是开始着手处理这些光源的指令,光源的处理通常也就是Alpha混合的操作。一个三角形的顶点常常包含了不止一种类型的光源效果。最早出现的硬件T&L引擎首次加入了光源处理功能,不过硬件T&L引擎只可以处理最大单顶点8种不同的光源类型,只使用一个点光源的静态场景,如果渲染大量光源效果的话,运行速度会下降得很厉害。因此,此种光源渲染方式被后来出现的顶点着色引擎所代替──顶点光照就由此而来的。

  如果使用顶点着色引擎渲染光影效果的话,一个光影引擎可允许多达四个的光影(注:游戏中,光源分为四种类型:点光源、聚光源、方向光和平行光),可以达到34种光影环境。在定点得到光影数据前,光源的数目,光源的类型以及应用的方式(环境式、漫射式、聚光灯式),都需要设计者在使用光影引擎时加以考虑。同样以上面的火箭为例,顶点着色引擎会根据火箭发出并落到附近墙壁上的光线的位置、强度、以及光源大小进行计算。最后可以在运行3D程序时实时显示动态光源效果。

  如果场景复杂而且使用大量多边形组成的话,顶点光照的效果会更加明显,但这也会带来显示性能上的下降。如果在Quake3中选择顶点光照方式,你会发现游戏运行速度明显下降许多。这是因为Quake3使用大量多边形,而且使用的自己的软件光源引擎,当显卡处理大量多边形时使用顶点光照,性能会严重下降。不过显卡技术的发展,主流显卡都包含了硬件光源引擎技术,如NVIDIA 的Shading Rasterizer光影引擎技术(Shading Rasterizer处理引擎可以同时完成7种特殊的光源操作,能实时生成光影效果,并能从硬件上支持基于每像素的操作功能,它通过基于单个像素的动态计算,实现散射、镜面反光、斑点光源、点光源效果)、ATi的Charisma Engine Ⅱ、Truform技术,但这些都是在DirectX 8出现后才得以实现的。

  总的来说,要完全实现游戏光照渲染效果,需要两个条件:一个是游戏软件的支持,另一就是就是显卡的支持。如果你的游戏支持DirectX 9,但显卡仅仅支持DirectX 8的话,那么在游戏中显卡仅仅能以Vertex Shader1.1版本的标准来渲染光照效果。就灯光效果来说,Vertex Shader 1.1版本在处理的时候必须为每个光源设计一个独立的着色引擎、着色指令被限制在128个数量内(而DirectX 9中的Vertex Shader2.0版本拥有的指令集高达1024个,仅用一条普通的光源Shader通过调用子程序来产生具有不同的自定义色彩、形状、位置的任意数量的光源效果)。因此DirectX 8显卡不能以Vertex Shader 2.0的标准来进行动态渲染,这些原因导致与支持2.0版本的场景有相当大的差别。

  二、阴影渲染效果

  众所周知,光与影如同一对搭档相辅相成,但是我们似乎总容易被明亮绚丽的光照效果吸引,而往往忽略了增强这种表现效果的影的作用。但在目前的实时3D游戏中,要做出真实的阴影效果,是很不容易的。因为阴影是因物体遮住光源所产生的,要做出正确的阴影效果,就需要对整个场景做处理,这样才能判断出哪些物体被哪些物体遮住了。目前3D游戏中,主要以平面阴影(Planar Shadow)、体积阴影(Volumetric Shadow)这两种方式来实现阴影渲染效果。

  1.平面阴影(Planar Shadow)

  平面阴影是目前最常用的阴影渲染方法,其原理是把阴影看成是“物体投射到其他表面”来处理。在光源是平行光的时候(例如太阳光),可以看成是物体把阴影“投射”到另一个表面上。如果场景中只有一个重要的光源(即最强的光源),那可以假设只有这个光源会产生明显的阴影。以平行光源来说,只要把阴影“投射”到一个平面上就行了,往往需要一个纹理贴图就可以了。这个方法可以对任何平面做出阴影的效果,如果有多个平面,可以分别对每个平面都做一次。平面阴影的优点是简单、容易做,而且在投影面不多的时候,速度很快。但是,当投影面变多时,或是物体很复杂时,速度很快就会变得很慢,因为对每个平面都需要把投影的物体再画一次。而且它只能投影在平面上,对于不规则的表面则完全没办法。

  2.体积阴影(Volumetric Shadow)

  针对平面阴影不能渲染出阴影在不规则的表面上的真实效果,技术人员又引入自由度更高的方法──体积阴影。这个方法的优点在于,它并不是利用“把物体投影到表面”的方式来产生阴影,而是去找出场景中,有哪些像素是在阴影中。也就是说,想象一个物体挡住光时,在物体的后面会形成一个大的“阴影锥”,若一个像素在“阴影锥”之中,那它就是在阴影之中,所以基本上体积阴影的原理是很简单的,这个方法比平面阴影更能适用于不同的场景。不过,它当然也有缺点,最主要的缺点是在于它的复杂度。要做出有效率的“阴影锥”,需要对物体做相当麻烦的处理,基本上就是要找出物体在某个方向的“外缘”。虽然这并不太难做,但是还是需要GPU花费相当时间去处理。另外,为所有的物体绘制出其“阴影锥”,需要相当大量的填充率和显存频宽。若是延后渲染,例如图像渲染则影响不会这么大,特别是图像渲染可以支持一些特别的功能,来加速体积阴影的动作。现在显示芯片厂商都推出了自己的阴影引擎、将工作交到像素着色引擎来处理。如ATi的R350的像素阴影引擎能同步处理三个指令集(纹理访问、纹理寻址操作、色彩操作),可进行这三种类型的混合处理,从而在达到极佳的特效的情况下,让引擎和性能的利用率也最大。

  总的来说,整个光、影渲染特效目前主要由顶点着色引擎、像素着色引擎分工合作来完成。如果你想完全感受游戏中的逼真场景,选择一款支持DirectX 9的显卡是必需的。

  编后:《一切为了更真实──显卡中的3D技术》到此告一段落,我们希望大家在看到越来越逼真的游戏画面的同时,也看到显卡中3D技术的发展。由于文章篇幅所限,我们着重讲解了游戏中基本的、常见的3D技术。而今后我们还会为大家做 相关技术报道。如果你有什么好的建议,请来信告知。

  我们的信箱:hardware@cpcw.com