滤波阴影贴图
Filtered Shadow Maps
普通阴影贴图的深度不能直接过滤。滤波阴影贴图存的是深度的某种统计量(矩、指数),可以像普通纹理一样模糊、做 mipmap、用求和面积表,只取一个样本就能得到平滑的半影。代表方法有方差阴影贴图 (VSM)、卷积阴影贴图、指数阴影贴图 (ESM/EVSM) 和矩阴影贴图;共同难点是漏光。
方差阴影贴图 (VSM)
- 一张图存深度,另一张存深度平方;生成时可用 MSAA 等抗锯齿,之后可模糊、mipmap、放进求和面积表,所有纹理采样过滤手段都能用。
- 在接收体位置采样一次得到平均遮挡深度 (一阶矩)。 大于接收体深度 时完全受光;否则: 为二阶矩。 是受光百分比的上界(来自单侧切比雪夫不等式)。对固定深度的平面遮挡体和平面接收体,,所以它是许多实际情况的好近似。
- 直观理解:阴影边缘处方差增大;在半影受光边,平均遮挡深度只比接收体略近, 接近 1;进入半影后 变大、 下降,同时方差从边缘近 0 变到遮挡体深度不同且平分面积处最大,两者平衡得到线性变化的阴影。
- 优点:能用表面斜率修改二阶矩,优雅地处理几何偏移问题。数值上 是两个相近大数相减,会放大精度不足,应使用浮点纹理。
- 性价比高:PCF 要更多样本才能在软阴影中避免噪声,VSM 一个高质量样本就能得到平滑半影,在算法限度内阴影可以任意软而不增加开销。
- 与 PCF 一样,过滤核宽度决定半影宽度;求出接收体到最近遮挡体的距离即可改变核宽。mipmap 对缓慢增宽的半影估计很差,会出现方块伪影;求和面积表效果好得多。
漏光 (light bleeding)
- 两个及以上遮挡体覆盖接收体且其中一个离接收体很近时,切比雪夫不等式给出的最大值与真实受光比例无关,完全遮挡的区域仍有光。用更多更小区域的样本可以解决,但 VSM 就变成了一种 PCF。
- Lauritzen 的美术可控方法:把低百分比视为全阴影,其余重映射到 0%–100%,以变窄半影为代价压暗漏光。
- 阴影深度复杂度低的场景 VSM 效果好;地形阴影很少有多重遮挡,很适合 VSM。
卷积阴影贴图
把阴影深度编码为傅里叶展开,可过滤且收敛到正确答案,漏光较少;但要计算和访问多项,执行和存储开销都显著增加;还存在振铃:在原遮挡体深度稍后的特定深度出现轻微漏光。
指数阴影贴图 (ESM / EVSM)
- Salvi 与 Annen 等独立提出用指数函数的单项:把深度的指数及其二阶矩存入两个缓冲。指数函数更接近阴影测试的阶跃函数,显著减少漏光,也避免振铃。
- 局限:指数值的二阶矩可能极大,超出浮点范围;生成线性 z 深度可提高精度,并让指数衰减更陡。
- 质量好于 VSM,存储和性能优于卷积阴影贴图,是三者中最受关注的。还可用 MSAA 改善结果、得到有限的透明效果,用计算着色器提升过滤性能。
- 级联 ESM 相比标准级联贴图,所有级联可用一个偏移因子;但也有各种漏光等伪影需要处理。
矩阴影贴图
Peters 和 Klein 提出,用四个或更多矩,质量更好但存储更大,可用 16 位整数存储降低开销。其扩展还能提供光散射和透明效果。
定位
滤波阴影贴图可以看作样本很少的廉价 PCF,同样半影宽度恒定;都可与 PCSS 结合实现可变宽度半影。书中总结:滤波阴影贴图提供快速软阴影计算,在遮挡体远离接收体时(如地形)尤其好用。
| 方法 | 存储 | 优点 | 缺点 |
|---|---|---|---|
| VSM | 深度 + 深度² | 可任意过滤,单样本软阴影 | 多遮挡体漏光,精度问题 |
| 卷积 | 多个傅里叶项 | 收敛到正确答案 | 开销大,振铃 |
| ESM/EVSM | 指数深度 + 二阶矩 | 漏光少,性价比最好 | 数值溢出,需线性深度 |
| 矩阴影 | ≥4 个矩 | 质量更好 | 存储更大 |
GPU Gems 的视角:求和面积方差阴影贴图 SAVSM(GPU Gems 3 第 8 章)
来源:Andrew Lauritzen《Summed-Area Variance Shadow Maps》;摘录 Chapter 8. Summed-Area Variance Shadow Maps — Andrew Lauritzen。与上文 RTR4 的 VSM/ESM/MSM 并列:本章给出 VSM 落地细节、漏光压制与按像素可变核宽。
VSM 把深度当成可线性滤波的分布:阴影图写深度与深度平方,过滤后恢复一阶、二阶矩,再用单侧切比雪夫不等式给出受光概率上界 。对「单一平面遮挡体 + 单一平面接收体」该上界等于真实 PCF 结果,因此在许多游戏场景中可直接当可见性用。最小方差要夹到极小正数,既防数值炸掉,也常能顺手消掉粉刺。
偏置方面,Lauritzen 用片元深度的 把每个纹素建成局部平面分布,把斜率写进二阶矩,而不是靠恒定深度偏置——多边形几乎平行于光线时也不必把彼得潘拉得很大。漏光(半影同时出现在本该全暗的第二接收面上)无法在任意遮挡分布下彻底消除,但可用 linstep(Amount, 1, p_max)(或 smoothstep)砍掉低强度假半影再重映射,Amount 与场景尺度无关,调到刚好去掉最刺眼漏光即可。
深度度量强烈建议用到光源的线性距离(方向光则用到光平面的距离),而不是透视除法后的 ;否则方差是两个大数相减,精度一丢画面就花。实现上还可对阴影图开 MSAA、可分离盒模糊当最小核宽、再生成 mip,着色时一次各向异性采样即可。注意:接收体必须写进方差图,否则半影尺度会错;「只画投射体 / second-depth」那套传统偏置技巧与 VSM 不兼容。
当半影宽度要随遮挡距离逐像素变化(与 软阴影 PCF 与 PCSS 的 PCSS 同路)时,固定模糊不够。本章把 VSM 放进求和面积表 (SAT):任意矩形区域的矩平均 可取,核宽可动态。代价是 SAT 吃掉约 位精度,需用均值偏置、把矩拆到四通道、原点居中 SAT、或已知最大核时用整数环绕累加等手段保住有效位数。经验上最小核宽至少约 4 才能压住最扎眼的阴影锯齿;固定核宽时「模糊 VSM + 漏光压制」通常比 SAVSM 更便宜,动态核宽才轮到 SAVSM。