转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=2387

上一篇提到了PSSM的方法,及其它的两个缺点。I3D2011上的Sample Distribution Shadow Maps可以用很低的代价同时解决掉那些缺点,在最大程度上优化shadow map上sample的分布。

SDSM

PSSM的那两个缺点实际上都来自于同一个根源:光锥区域是根据视锥的大小,而不是可见pixel的范围来调整。这里所说的pixel范围涉及到两个方面。第一是pixel在view space的深度范围,这会影响区域的划分。另一个是pixel投影到light space的坐标范围,这影响到scale和bias的计算。很显然最佳情况是,shadow map的sample分布在所有可见pixel上,其他地方不浪费。而这两个方面都可以很简单地通过场景的depth texture得到。

原论文提到了多种sample distribution的统计方法。在实践中,log partition速度最快,效果和其他更复杂方法的差距非常小,所以这里就讨论这一种方法,其他可以依此类推。这种SDSM的算法可以归纳成:

  1. 渲染一遍场景,得到depth texture。
  2. 统计depth texture,得到最大和最小的depth。
  3. 把depth的范围根据log的距离分布平行切成几个区域。
  4. 从pixel的depth求出view space position,投影到light space,得到该区域的scale和bias,组成crop matrix乘到projection matrix之后。
  5. 对每一区域都生成一张shadow map。
  6. 在使用的时候,根据像素在视空间的位置确定自己是在哪个区域,以选择shadow map。

SDSM仍然是一种CSM,原理和框架并没有改变。所以总体上看,SDSM仍然类似于PSSM,只是不是通过光锥,而是通过可见pixel来划分区域和计算crop,这就解决了PSSM的第一个缺点。另外,由于深度是自动划分的,也就不会存在远近不能两全的缺点,也不需要一个额外参数来手工调整了。所以PSSM的两个大缺点在SDSM里都不存在了。

从这里也可以看出,整体程序只要做很小的修改就能升级到SDSM。由于depth texture在deferred框架里是必然存在的,所以步骤1可以认为是free的。对于forward框架来说,pre-depth也是常用的策略,所以基本也可以忽略1的影响。目前步骤2、4是通过compute shader 5.0来计算的,可以在一个pass内完成。以后会实现一个pixel shader的版本,用多pass做到同样的事情。

结果

从结果可以看出,SDSM的阴影质量比PSSM精细。

SDSM 4-level

放大看个局部比较。上图为PSSM的,细线的影子有断裂和连在一起的状况。下图为SDSM的,细线清晰得多。

PSSM crop
SDSM crop

在区域个数较少的时候,差异更明显。

SDSM 1-level

未来

CSM无法避免的缺点就是需要分多个区域,生成多张shadow map。这使得存储和计算都增加了多倍的负担。I3D2012的Rectilinear Texture Warping for Fast Adaptive Shadow Mapping通过类似于dual paraboloid的非线性形变,把视锥的不同地方用不同的分布存到一张shadow map里。但也是需要对场景的所有物体都做tessellation才能保证结果正确,这个开销仍然不可忽略。目前这方面还没有看到其他进展。