Shadow Volume!
打从Doom3资料被公布的第一天起,人们就开始关注这个词汇了。这个Shadow Volume究竟是什么?注意了,这就是和Doom3那几可乱真的阴影技术相关的重要名词——“阴影锥”!比较酷一点的说法叫做“阴影容积”,不过反而更难以理解了^^
09-ShadowVolume
如图9这种解释阴影锥的图片已经太多太多了。很多人认为这是一种跨时代的技术,其实早在Quake3时代,这种阴影技术就已经开始使用了。在Quake3中有3种阴影:
第一种是人物脚下一个黑斑,这个其实不能算实时阴影。
第二种是平面阴影(Planar Shadow),它把物体映射在一个平面上,然后很据光线数据把这个阴影“贴”在它应该在的表面上。这种方法在环境简单时非常不错,比如球场上的球员阴影。但其缺点在于,被映射的物体形状越复杂,计算效率越低,且不能把阴影映射在曲面上。
第三种就是Doom3所采用的体积阴影技术,当时因为计算能力限制,只能简单运用在人物身上,外加场景复杂度不够,所以并未产生惊人效果。
随着硬件和游戏引擎的飞速发展,体积阴影技术终于在Doom3引擎上大规模应用,我们就来看看体积阴影技术究竟有什么秘密:
名词解释:体积阴影,测定投影空间式阴影,Volumetric Shadow。该算法最早于1977年提出,其基本原理是根据光源和遮蔽物的位置关系计算出场景中会产生阴影的区域,即阴影锥。然后对所有物体进行检测,以确定其会不会受阴影的影响。这个方法的要点在于,它不是利用“把物体投影到环境表面”的方式来产生阴影,而是去找出场景中有哪些像素是在阴影中。
如图10,我们可以做个实验:拿一个小球,正对光源(比如一盏台灯)。光线是向四面八方直线传播的,既然小球不透光,那么小球必然会在挡住朝小球方向的光线,在小球的逆光面形成一个锥形的无光线区域,也就是阴影锥。很明显的,只要任何物体或物体的部分位于这个区域以内,就会处在阴影之中。
现在我们深入一些,假设有一个已经绘制完成的3D场景,因为使用Z轴缓冲(Z buffer,用以表现场景的深度)的关系,对每一个像素而言都有一个Z值,即表示该像素和观察者的距离的值。假设现在有一个三角形物体,把阴影投射到这个场景中,并画出这个物体的阴影锥。因为物体是一个三角形,所以它的阴影锥也是一个三角锥。那么,要如何知道场景中有哪些像素会受这个阴影锥的影响,从而处在阴影内呢?
其实方法很简单:想象许多射线,由观察者射向每个像素。如果射线和阴影锥完全没有交集,它所对应的像素当然就不会受阴影锥影响,就不会处于阴影中。不过,即使是射线和阴影锥有交集,并不一定表示该射线对应的像素就一定受阴影锥影响,因为射线可能会穿越阴影锥。所以,只有在射线射入阴影锥之后,在离开阴影锥之前就遇到其对应的像素时,才表示这个像素和受阴影锥影响,处于阴影之中。
我们以图11来讲解这几种不同的情形:
11-阴影锥分析
图中的(1)和(2)都是面对观察者的面,它们所涵盖的像素,是“射线会射入阴影锥”的像素。而(3)是背对观察者的面,它所涵盖的像素是“射线会离开阴影锥”的像素。所以,会受阴影锥影响,处于阴影中的像素,就是(1)+(2)-(3)的那些像素,也就是阴影所在的位置。
要怎么在3D绘图中,得到(1)+(2)- (3)的结果呢?这就需要OpenGL的模板缓冲区(Stencil Buffer)。OpenGL的模板缓冲区可以让显卡进行“加1”和“减1”的计算。所以,只要把模板缓冲区设定成在绘制(1)和(2)的面时,让模板缓冲区加1;而在绘制(3)的面时,让模板缓冲区减1。这样一来,在绘制完(1)至(3)时,那些模板值不为0的像素就是阴影了。最后,把所有模板不为0的像素亮度降低,就可以达到绘制阴影的效果。
体积阴影最主要的缺点是在于它过于复杂。要做出有效率的“阴影锥”,需要对物体做相当麻烦的处理,基本上就是要找出物体在某个方向的 “外缘”(Silhouette)。这需要花费相当的显卡核心处理时间。另外,为所有的物体绘制出阴影锥,需要耗费相当大的填充率、显存带宽甚至是CPU 占用率——这显然不适合需要一定帧数率的Doom3。
那么,我们就要看看Doom3是怎样加速阴影生成的:
没错,又是Vertex Shader)!顶点引擎的可编程特性可以让生成Shadow Volume的工作由显卡核心完成,这样可以大幅度减轻CPU的运算负担。与此同时,借助顶点引擎的寄存器组,连数据的来回传输都省略了,这样就可以带来惊人的速度提升。
此外还有Ultra Shadow技术。它是NVIDIA在NV35以后的GPU中增加的功能,关于此技术对提升Doom3运行效能的作用在本杂志今年第6期GeForce 6显卡介绍文章中有详细介绍,这里就不复述了。不过,Doom3默认并未开启Ultra Shadow技术,我们可以在Doom3安装目录下的Doomconfig文件中加入“set r_usedepthboundstest 1”语句来开启Doom3对Ultra Shadow技术的支持。不过,使用NV35以下GPU的用户就不要做无意义的尝试了。
值得一提的是,Ultra Shadow技术是开放的,所以有可能会有其它厂商采用。当然,这其中很多优化特性依靠软件也可以执行,仅仅速度的提升不如GPU直接参于那么明显罢了。
12-没有体积阴影的架子
13-打开体积阴影的架子