Shadow Map 和 Shadow Volume

Shadow Map和Shadow Volume 可以说是最常见的阴影计算方法,二者各有千秋。个人认为,理解这两种阴影算法的重要前提是 理解 ZTest,ZWrite,Stencil Test的作用。

ShadowMap适用于静态的光源和静态的物体,好处是开销不算大,需要2个pass。而且对于静态的光源和物体,大多数情况下,生成的Depth Map可以进行复用(此时,为啥不选择光照贴图)。而当物体或光源运动时,则每帧需要重新渲染到纹理,生成新的Depth Map,此时开销较大。而且ShadowMap产生的阴影会有锯齿。

ShadowMap算法: 

Pass1:以光源位置为视点,对整个场景进行渲染。说白了就是假设相机在视点处, 进行常规的相机渲染。当然,这一步我们只需要生成Depth Map,所以只需打开ZTest,ZWrite,而不用进行其他任何的计算。将顶点的z和w值进行保存到Depth Map。 最后的结果是在Depth Map中保存了每个像素中离光源最近的深度值。

Pass2:相机正常渲染整个场景,将此时每个像素的深度值(假设为Z2)与Depth Map中对应像素的深度值(假设为Z1)进行比较,如果Z2 > Z1,则该像素处于阴影中。 需要注意的是在这个pass中,比较深度值的时候需要把当前顶点的位置变换到pass1中的空间(因为你不能在2个不同视角所产生的不同空间进行深度值比较,这样没有意义)。


Shadow Volume  ZPass算法:
Pass1: 也是得到一张Depth Map,但要注意和ShadowMap不同的是,整个DepthMap是正常相机渲染整个场景得到(而不是ShadowMap中在光源位置渲染得到)。

Pass2: ZWrite关闭,Stencil  write开启。渲染所有生成的Shadow Volume。
对于Shadow Volume面向相机的一面,如果ZTest通过(意味着Shadow Volume在这个像素的深度值比深度缓冲区小,即进入了Shadow Volume中),Stencil值加1,如果ZTest失败(意味着Shadow Volume上这个像素的深度值比深度缓冲区大,即没有进入Shadow Volume),stencil值不变。
对于Shadow Volume远离相机的一面,如果ZTest失败,stencil减1,否则保持不变。

Pass3:根据stencil buffer中的值来判断该像素是否应该绘制阴影,即如果stencil值大于0,表示像素在Shadow Volume中,需要绘制阴影。

ZPass算法的缺陷是,如果相机(视点)处于Shadow Volume之中,会产生错误。改进算法为ZFail算法。

ZFail算法:
Pass1:与ZPass算法Pass1一样

Pass2:ZWrite关闭,Stencil  write开启。渲染所有生成的Shadow Volume。
对于Shadow Volume远离相机的一面,如果ZTest失败,stencil加1,如果ZTest通过,stencil不变。
对于Shadow Volume面向相机的一面,如果ZTest失败,stencil减1,如果ZTest通过,stencil不变。

Pass3:与ZPass算法Pass3一样

总结,可以看到ZPass和ZFail算法的区别仅仅是第二个Pass的渲染 Font Face和Back Face的顺序 以及对模版值的操作情况不同

你可能感兴趣的:(Shadow Map 和 Shadow Volume)