(论文)[EG-2007] Bitmask Soft Shadows
Bitmask Soft Shadows
- 改进了 micropatch 逆向投影估计软阴影的算法
- micropatch 通过将当前着色点对应遮挡的 shadow map 中的 texel 逆向投影到光源上,计算覆盖面积从而实现软阴影的估计
- 论文贡献如下
- 提出了 bitmask 算法,通过 bit-or 替代了求面积,能够处理 overlap 的情况
- 提出了 microquad 替代 micropatch,能够更加好的近似遮挡物
- 实现上,会有一些其他近似
- 提出了 MSSM 层次阴影结构,能够进一步减小需要投影的 microquad 数量【精细提出无用 quad】
相关工作
- Soft shadows via micropatch backprojection
- 光源中心发射的 shadow map,里面的阴影当作潜在遮挡体,称为 micropatch
- 估计着色点 p 可见性的时候,将 micropatch 逆向投影回世界空间,然后再从 p 投影回光源,估计可见的比例

- scatter 类方法:从 micropatch 开始,投影到影响像素
- gather 类方法:从着色像素开始,从 depth map 中获取 micropatch
- 问题
- 光源中心看不到的遮挡物被完全忽略了
- micropatch 投影到光源上有 overlap 的时候,会出问题【偏黑】
- 相邻的 micropatch 投影到光源上可能出现 gap【空洞】,因为 micropatch 不连续
- 实时性能考虑,只有有限的 micropatch 会被逆向投影
- hierarchicalshadow map(HSM) 试图解决,类似 mipmap
Bitmask soft shadows
- BMSS
- 矩形光源软阴影
- 思路类似
- 先在光源采样点做 shadow map(通常在中心),depth map 上的区域就是 micropatches,逆投影回光源表面
- 在光源上撒点,用一个 bit 表示可见性
- micropatch 本身是轴对齐的,因此更新很方便
- micropatch 逆向投影到光源上的时候,使用 bit-or
操作,这样就不会重复计算了
- 投影区域覆盖的点,将对应的 bit 设置为被遮挡
- 均匀划分,放在正中间【8x8、16x16、32x32】
- 16x16 效果不错,但是放在正中间会有 pattern
- jitter,性能原因,还是使用规则 jitter
- 下列分布能够让规则的横竖锯齿得到缓解

Post filtering of the visibility buffer
- 量化导致的跳变,尤其是出现在有一个边和光源边对齐的时候【量化误差】
- 下图边上的点向外移动一个像素,导致跳变
- 那么角上的点恰好满足两条边的跳变,沿着角的方向降低更多
- 下图边上的点向外移动一个像素,导致跳变
- 论文一种启发式的平滑后处理
- 论文保存两个结果
- B:按照 bitmask 计算得到的 visibility 值【准确,但是存在量化误差】
- A:按照重投影面积累加计算的 visibility
值【可能重复计算,结果相对平滑】
- 使用 unclamped 的结果引导插值
- 使用 A 引导 B 的插值
- 一次 filter pass 如下
- 先计算 A、B 的中心差分是否一致,一致才进行下面计算
- 变化一致说明 B 的误差是来自于量化;不一致的话可能是其他原因,不好引导
- \(x\) 轴插值如下,\(y\) 轴类似;选择变化小的作为新的 \(B_0\)
- 先计算 A、B 的中心差分是否一致,一致才进行下面计算
\[ B_0^x = \frac{A_0-A_{-1}}{A_1-A_{-1}} \left(B_1-B_{-1}\right) + B_{-1} \]
Multiple depth map
- 光源中心看不到的遮挡物可能被忽略了,因此可以使用多个 depth map
缓解这一点
- 传统方法不好做,因为无法解决重复计算问题
- 本文可以,bit-or 操作不会重复计算
- 两种方式
- 从光源上多个点渲染 shadow map,然后做逆向投影
- 简单方式:单个着色点做 depth peeling
- 例如下图中,depth map 只有绿色部分
- 但是实际上对于蓝色着色点来说;橙色部分也是遮挡物,但是他没有在 depth map 中体现出来
- depth peeling 能够解决这个问题【论文说这种情况带来的 artifact 很多】

- 此外新的策略
- 动态物体、静态物体生成各自的 shadow map
- 每帧只需要更新动态物体
Multi-colored light sources
- 少量颜色的光源【论文给了一个 3 种颜色的光源】
- 每一个颜色维护一个 bitmask
- bitmask 和 阴影做 bit and 的结果除以 bitmask 里面对应的 1 的数量,就是这个颜色的可见性
- 相对于之前的 4D texture / summed area table,开销更小
- 对于任意颜色纹理的话,使用如下查找表更快
- 光源上的 8 个 patch 话分为一组,预计算所有情况下【\(2^8=256\)】的可见性求和结果,然后运行的时候走查找表
- 对于 32x32 的光源:最多需要查询 \(32\times32/8=128\) 次
- 注意查询次数和 micropatch 数量无关,只在最终进行查询
Backprojecting microquads
- micropatch 的表示是和光源平行的 quad
- 左图的 overestimation:depth map 中的像素块,投影到像素中心的深度对应的 micropatch
- 上面图中的 gap 问题【不连续区域被忽视了】

- 本文引入:microquads
- 相邻 4 个点的深度样本,连接起来构成一个 microquad
- 在计算的时候,之后 4 个顶点深度都比着色点小时,才进行逆向投影【保守策略】
- 上图表示,这样的近似更好
- 原生就没有 gaps 问题
- 可能导致 underestimation:图中矩形右上角的点被忽略了【2D 示例】
- 相邻 4 个点的深度样本,连接起来构成一个 microquad
- 有点像双线性插值
- 更少出现自遮挡问题【surface acne,sell-shadowing】
- 光源可见的,不平行于光源的表面
- micropatch 重建结果是很多分离的水平面片,扩展出来的区域会形成自遮挡【下图蓝色点】
- microquad 则可以正确近似表面

- 任意 quad 投影到光源是容易的,但是精确 clamp
开销高【可能在光源范围外】
- 使用简单的近似:将所有逆向投影的顶点 clamp 到光源的边内部
- 边界可能会有小误差,但是可以接受
- 不会存在 gaps 或者 overlaps
- 使用简单的近似:将所有逆向投影的顶点 clamp 到光源的边内部

- 进一步近似:使用每条边的中心,构造轴平齐的矩形,方便计算
- 比直接使用 bounding box 更好,但是带来了 gaps 和 overlaps

- 即使如此近似,microquad 的处理还是比 micropatch 开销更高
- 因为边是重合的,因此每个 microquad 纹理读取此时平均为 2
Improved search area refinement
- 有额外开销,因此希望不处理一些没有贡献的 microquad
- HSM 能够处理,但是还是太保守了
- 新数据结构,称为 MSSM(multi-scale shadow map)
- level \(i\) 的 texel
保存一这个像素为中心的 \(2^i\times2^i\)
区域内的最小、最大深度值
- 每层分辨率都是一样的
- 每层计算可以通过 \(i-1\) 层的 4 个纹理读取实现
- 范围示意图【看蓝色的】:clamp to edge
- level \(i\) 的 texel
保存一这个像素为中心的 \(2^i\times2^i\)
区域内的最小、最大深度值

- N-Buffer 的变形
- 它是将邻域范围保存到左下角
- MSSM 信息更多
- 高分辨率下 MSSM 构建开销比 HSM 高很多
算法
- 初始搜索范围
- 光源中心生成 shadow map 的时候有一个 near plane
- 着色点 p 和光源构成的四棱锥和 near plane 交集 \(A_0\)
- 首次查询:选择层级使其覆盖 \(A_0\),得到初始范围 \([z_{\min},z_{\max}]\)
- 做出判断,落在范围内则继续;否则已经得出结果
- 使用 \(z_{\min}\) 替代 near plane,和四棱锥求交,得到新的交集 \(A_1\)【更小】
- 然后使用合适层级的 4 个样本覆盖搜索区域,然后更新范围
- 在更新一次,得到 \(A_2\),作为最终的范围