【转】阴影锥(shadow volume)原理与展望

转记:找了不少关于shadow volume原理的资料,还是这个帖子讲解的一目了然,转帖在这里,方便查阅。引用链接:

阴影锥(shadow volume)原理与展望—真实的游戏效果的实现

作者:王浩

前言:真实的游戏效果

shadow volume 这个术语几乎是随着 DOOM3 的发布而成为FPS 玩家和图形学爱好者谈论的对象的。虽然这个游戏还没有上市,但是凭借 John Carmack 的传奇经历以及 DOOM3发布的一些让人惊讶的预览图片,我们仍然有理由认为它将会是 2004 年最热门的 FPS 游戏之一。 id software向来都不吝惜为了达到最好的图像效果而使用最先进的渲染技术 ,这曾经使得玩家为了玩它开发的游戏而不得不掏光口袋里面的钱来升级电脑,不知道这次我们可以幸免吗?

自 DX9 发布以来,大家的注意力似乎都被 shader 吸引住了, BBS里面谈论的话题也总是离不开 shader based rendering ,前一段时间关于 GPU内部精度的讨论大有遮天蔽日之感,但其实和闪闪发光的金属小球以及波光鳞鳞的水面比较,几个简简单单的影子常常能带给场景更多的真实感。也许这就是为什么DOOM3 能够在多如牛毛的 FPS 游戏中脱颖而出的原因之一。

阴影的实现方法有很多种,现在比较流行的主要是 shadow mapping 和shadow volume. 前者实现起来相对简单,可以发挥现在 GPU 可编程流水线的能力,但是由于先天不足,shadow mapping在处理动态光源/物体的时候开销过大,经常作为一种静态场景中的廉价替代物。而 Shadow volume 的强项恰恰是 shadowmapping 的短处,像 DOOM3 这种大量运用动态光源,并且要对时刻都在运动中的物体投射阴影,shadow volume是现阶段唯一的选择。

Shadow mapping 的原理:

一个物体之所以会处在阴影当中,是由于在它和光源之间存在着遮蔽物,或者说遮蔽物离光源的距离比物体要近,这就是 shadow mapping 算法的基本原理。

Pass1: 以光源为视点,或者说在光源坐标系下面对整个场景进行渲染,目的是要得到一副所有物体相对于光源的 depth map (也就是我们所说的shadow map ) , 也就是这副图像中每个象素的值代表着场景里面离光源最近的 fragment 的深度值。由于这个 pass中我们感兴趣的只是象素的深度值,所以可以把所有的光照计算关掉,打开 z-test 和 z-write 的 render state 。

Pass2: 将视点恢复到原来的正常位置,渲染整个场景,对每个象素计算它和光源的距离,然后将这个值和 depth map中相应的值比较,以确定这个象素点是否处在阴影当中。然后根据比较的结果,对 shadowed fragment 和 lightedfragment 分别进行不同的光照计算,这样就可以得到阴影的效果了。

从上面的分析可以看出来,depth map的渲染只和光源的位置以及场景中物体的位置有关,无论视点怎么运动,只要光源和物体的相互位置关系不变,shadow map就可以被重复使用,因此对于没有动态光源的场景, shadow mapping 是很明智的一种选择。

除了上面提到的不能很好应付动态光源场景的限制之外,shadow mapping 还存在着所有使用 texture的场景面临的共同问题-锯齿。根据采样定理,只有纹理分辨率小于或者等于物体的实际分辨率时才不会失真,而当一副很大的纹理被贴到尺寸比它小的物体上时,会出现一个 fragment 覆盖多个 texel 的情况,这时要准确的再现这个 fragment 的颜色信息,就要综合考虑所有被它覆盖的texel 产生的影响,这就是各种纹理滤波方法最基本的原理。但是由于 depth map 是在不断的变化当中,所以不能像一般的纹理那样把各个mip -map 事先计算好放到显存里面。有一种利用 pixel shader 的方法对 depth map 做 bilinearfiltering, 但是开销很大,在现阶段不具备实用意义。同样的问题在纹理分辨率小于屏幕分辨率的时候仍然存在,这时多个 fragment会被投射到同一个 texel 上面,虽然从再现纹理的角度来说并不存在失真,但是由于多个 fragment共用同一个纹理值,锯齿问题还是存在。更糟糕的是,没有一种滤波技术可以从根本上解决这样的锯齿,因为从数学上讲,人们不可能通过运算来创造出比原始量更多 的信息。近年来,为了解决 shadow mapping 的锯齿问题,人们做了很多努力,比较有前景的是 adaptive shadowmap(ASM) 和 perspective shadow map(PSM) 。两者的基本原理都是在可能产生锯齿的地方人为增加采样率,使得一个fragment 至少对应一个 texel , 区别是 ASM 增加采样率的地方是在 shadow 边缘,而 PSM是在靠近视点的地方。修补一个本身存在缺陷的方法从数学上来说是缺乏美感的,正像 John Carmack 在 2002年8月的一封 email中所说:

“ Shadow buffers makegood looking demos with controlled circumstances, but when you startusing them for a “real” application, you find that you need absolutelymassive resolution to get acceptable results for omni - directionallights, and a lot of the artifacts need to be tweaked on a per-lightbasis. While it is possible to do shadow buffers on GF1/radeon classhardware, without percentage closer filtering they look wretched. If wewere targeting only the newest hardware, shadow buffers would have abetter shot, but even then, they have more drawbacks than are commonlyappreciated. ”

看起来似乎 John Carmack 找到了实现阴影更好的方法?让我们来看看它究竟是什么。

Shadow volume 的原理:

Shadow volume 这种算法第一次被提出是在Franklin C. Crow 在 1977 年写的一篇论文 “SHADOW ALGORITHMS FOR COMPUTERGRAPHICS ”里。其基本原理是根据光源和遮蔽物的位置关系计算出场景中会产生阴影的区域( shadow volume),然后对所有物体进行检测,以确定其会不会受阴影的影响。

图中的绿色物体就是所谓的遮蔽物,而灰色的区域就是 shadow volume。

只有处于 shadow volume 里面的物体才会受阴影的影响。

shadow volume的算法

现在清楚了 shadow volume 的基本原理,那么如何确定一个物体或者一个物体的某一部分处于 shadow volume 中呢?这就要用到 stencil buffer 的帮助了。

z-pass 算法:

z-pass 是 shadow volume 一开始的标准算法,用来确定某一个象素是否处于阴影当中。其原理是:

自己打败自己是最可悲的失败,

【转】阴影锥(shadow volume)原理与展望

相关文章:

你感兴趣的文章:

标签云: