过滤对象

PCSS 要先寻找遮挡物,再按半影宽度执行 PCF。两个阶段都在区域内查深度,软阴影越宽,逐纹素访问的开销越值得关注。能否先保存一份区域统计量,之后用较少查询回答这些问题?

先明确要加速的运算。当前接收点为 p\mathbf p,阴影坐标为 u\mathbf u,比较深度为 tt,则

V(p)=∑jwj1[D(u+δj)≥t],wj≥0,∑jwj=1.V(\mathbf p)=\sum_jw_j\mathbf1[D(\mathbf u+\boldsymbol\delta_j)\ge t], \qquad w_j\ge0,\quad \sum_jw_j=1.

这里过滤的是同一接收深度下的多次比较。它与下面两种运算均不同:

1[∑jwjD(u+δj)≥t],\mathbf1\left[\sum_jw_jD(\mathbf u+\boldsymbol\delta_j)\ge t\right],

∑jwjV(pj).\sum_jw_jV(\mathbf p_j).

第一种先平均深度,最后仍只有一个二值判断;第二种混合了不同接收点的可见性,它们可能有不同深度甚至属于不同物体。统计阴影仍然要估计第一式的比例,不能把这三种运算交换顺序。

深度分布

把窗口中的深度值看成随机变量 Random Variable ZZ。按过滤权重随机选一个纹素,得到的深度就是一次样本。PCF 可见率于是等于该窗口中深度不小于接收深度的比例:

V(t)=P(Z≥t).V(t)=P(Z\ge t).

这与一个熟悉的统计问题相同:已知一组学生分数,怎样求超过某个分数的人数比例?拥有全部分数或直方图时可以直接数;只知道均值、方差时,则需要额外的分布模型或概率界。

累积分布函数 Cumulative Distribution Function,CDF 为 F(t)=P(Z≤t)F(t)=P(Z\le t)。连续分布中 P(Z≥t)=1−F(t)P(Z\ge t)=1-F(t);离散深度可能有相等值,应按深度比较约定处理,若相等视为可见,则使用 1−F(t−)1-F(t^-),也就是扣除严格小于 tt 的样本比例。

概率密度曲线的累计面积与累积分布曲线

左图在概率密度 Probability Density Function,PDF 下累计面积,右图将这种累计量画成随阈值单调增加的 CDF。左侧灰区截止在 x=1x=1,右侧虚线在 x=0x=0,两者不是同一阈值的数值标注。钟形分布只用于展示密度与累计概率的关系,真实深度未必服从正态分布。

均值与方差

均值 Mean μ=E[Z]\mu=\mathbb E[Z] 表示区域深度的平均位置,方差 Variance 表示深度围绕均值的分散程度:

σ2=E[(Z−μ)2]=E[Z2]−μ2.\sigma^2=\mathbb E[(Z-\mu)^2] =\mathbb E[Z^2]-\mu^2.

展开平方并用 E[Z]=μ\mathbb E[Z]=\mu 就得到第二个表达式。它的重要之处在于:不必每次查询都知道区域内所有深度,只要能取得深度平均与深度平方平均,便能计算方差。

方差阴影贴图 Variance Shadow Map,VSM 因此在建图时保存 zz 和 z2z^2,例如放在纹理两个通道中。对相同区域、相同权重过滤后,读回

m1=∑jwjzj,m2=∑jwjzj2,σ2=m2−m12.m_1=\sum_jw_jz_j,\qquad m_2=\sum_jw_jz_j^2, \qquad \sigma^2=m_2-m_1^2.

先平方再平均与先平均再平方不同,这个差恰好记录了深度的变化。常见实现将方差限制为非负,并设置适当的小下限,以处理浮点误差;过大的方差下限也会使阴影过亮,不能无条件增大。

概率上界

均值和方差并不足以恢复全部分布。VSM 使用单侧切比雪夫不等式 One-sided Chebyshev Inequality,也称 Cantelli 不等式,给出 t>μt>\mu 时的尾部概率上界:

P(Z≥t)≤σ2σ2+(t−μ)2.P(Z\ge t)\le \frac{\sigma^2}{\sigma^2+(t-\mu)^2}.

可以从一个非负平方量看出这个界的来由。令 Y=Z−μY=Z-\mu,a=t−μ>0a=t-\mu>0,对任意 s≥0s\ge0,在事件 Y≥aY\ge a 上有 (Y+s)2≥(a+s)2(Y+s)^2\ge(a+s)^2,因此

σ2+s2=E[(Y+s)2]≥P(Y≥a)(a+s)2.\sigma^2+s^2 =\mathbb E[(Y+s)^2] \ge P(Y\ge a)(a+s)^2.

将右侧概率解出,再选择使界最紧的 s=σ2/as=\sigma^2/a,就得到上面的分式。推导没有假设正态分布,所以无需计算正态 CDF 或 erf。

实时实现把这个上界作为可见率近似:

V^(t)={1,t≤μ,σ2σ2+(t−μ)2,t>μ.\widehat V(t)= \begin{cases} 1,&t\le\mu,\\[4pt] \dfrac{\sigma^2}{\sigma^2+(t-\mu)^2},&t>\mu. \end{cases}

t≤μt\le\mu 时返回 11 是常见处理,不意味着所有纹素都在接收点之后。t>μt>\mu 时公式也只是上界;真实可见率可能小得多。这些差异会导致后面的漏光问题。

遮挡均值

Variance Soft Shadow Mapping,VSSM 将方差统计进一步用于 PCSS。最终的 PCF 可见率已有近似,第一步还需要遮挡物的平均深度;它不是整个窗口的平均值。

例如接收深度 t=7t=7,窗口中深度小于 77 的样本才是遮挡物,深度 8,98,9 的样本不应加入遮挡均值。令 p=P(Z≥t)p=P(Z\ge t) 为非遮挡比例,遮挡与非遮挡的条件均值分别为 zb,zuz_b,z_u,窗口均值满足

μ=(1−p)zb+pzu.\mu=(1-p)z_b+pz_u.

这是按两类样本数量展开平均值的恒等式。VSSM 用概率界近似 pp,并在接收面近似平面的条件下取 zu≈tz_u\approx t,于是

z^b≈μ−pt1−p.\widehat z_b\approx\frac{\mu-pt}{1-p}.

这样就能用窗口统计量估计遮挡均值,再按 PCSS 的半影公式决定最终过滤范围。两个近似都需要条件:非遮挡表面不一定恰在深度 tt,概率界也不一定准确;当 p≈1p\approx1 时,分母很小,须回退到无有效遮挡或其他安全处理,不能直接产生很大的非法深度。

所有统计应采用一致深度定义。尤其在透视投影下,对投影深度求平均后再线性化,一般不等于平均真实线性深度;用于半影几何的平均距离需有相应的数据或明确的额外近似。

范围查询

现在的任务变成查询某区域的 m1,m2m_1,m_2。Mipmap 通过逐级平均,预先保存不同尺度的近似统计;运行时选择相近层级并插值,就能用少量访问读取大范围均值。

纹理从128×128逐级平均到一个颜色值

图中瓢虫和其他花纹逐步变成较粗色块,最后的 1×11\times1 保存整体平均。用于统计阴影时,平均的数据换成 z,z2z,z^2。Mipmap 对位置和窗口覆盖的近似仍然存在,三线性插值不能使任意矩形查询变为精确值。

求和面积表 Summed-Area Table,SAT 则保存二维前缀和。先看一维:输入 1,3,5,3,7,1,3,8,6,41,3,5,3,7,1,3,8,6,4,累计和为 1,4,9,12,19,20,23,31,37,411,4,9,12,19,20,23,31,37,41。要查询第 4–6 项的和,取 20−9=1120-9=11,不用再次遍历 3,7,13,7,1。

二维采用半开区间约定,令

S(x,y)=∑0≤i<x, 0≤j<yD(i,j).S(x,y)=\sum_{0\le i<x,\,0\le j<y}D(i,j).

轴对齐矩形 [x0,x1)×[y0,y1)[x_0,x_1)\times[y_0,y_1) 的和为

Q=S(x1,y1)−S(x0,y1)−S(x1,y0)+S(x0,y0).\begin{aligned} Q={}&S(x_1,y_1)-S(x_0,y_1)\\ &-S(x_1,y_0)+S(x_0,y_0). \end{aligned}

二维矩形和由四个前缀区域容斥得到

蓝色是目标矩形。先取包含它的大前缀区域,再减掉左侧和上侧多余部分,最后加回被减去两次的左上交叠区。四次表查询得到总和,除以矩形纹素数得到平均值;深度平方另建同样的表。

SAT 构建和存储为 O(WH)O(WH),矩形查询为 O(1)O(1)。它只直接处理轴对齐矩形,有限精度下大前缀和相减还可能损失有效数字。动态场景需要重建派生统计,GPU 并行扫描、带宽和精度都是成本;“查询常数时间”不等于全部算法没有预处理。

漏光问题

同一个均值与方差可以对应很多分布。如果窗口同时包含前方遮挡物、背景和接收面,深度经常是多峰的。一个概率上界或简单单峰模型可能把遮挡比例估小,使本应挡住的光被保留下来,这称为漏光 Light Leaking。

多峰深度分布与简化分布的尾部差异

蓝线表示多峰分布,红线用单峰形状说明简化后的差异;虚线右侧的累计面积不同,估出的非遮挡比例也不同。这里的红线是直观示意,VSM 实际使用 Cantelli 界,并未真的拟合一条高斯曲线。

一个简单反例是深度值 1,91,9 各占一半,接收深度 t=5t=5。均值也是 55,常见分支返回完全可见,但真实比较只有一半通过。误差来自分布信息不足,而非滤波数据一定算错。

非平面和重叠接收面使软阴影估计产生异常

图中红框标出阶梯与重叠面附近的异常。即便区域矩查询准确,zu≈tz_u\approx t 的接收平面假设也可能不成立。提高分布表达能力不能自动修复非平面、缺失几何或错误的搜索范围。

高阶矩

矩 Moment 是分布的积分统计。这里采用原始矩 mk=E[Zk]m_k=\mathbb E[Z^k];VSM 保存前两阶,高阶矩可以进一步约束分布形状。

矩阴影贴图 Moment Shadow Map,MSM 常存 z,z2,z3,z4z,z^2,z^3,z^4。平均后得到四个矩,再由这些统计估计阈值两侧的概率。因为矩仍能线性过滤,所以可以继续使用 Mipmap、模糊或其他适当的加权查询。

二、三、四阶矩对深度CDF的近似

蓝色阶梯是逐样本 PCF 对应的基准累计比例,红、青、绿依次使用二、三、四阶矩。绿色在这组分布中更接近阶梯,尤其能保留两个明显跳变之间的平台。它不意味着四个矩能够精确恢复任意连续或多峰分布。

有限个矩留下的是一组可能分布。常见 MSM 从这些分布中求遮挡比例的紧下界,用它近似阴影;对应可见率仍偏向上界。某些只有少量离散深度的情形可由四矩确定,而一般情形仍有不确定性。四通道存储、重建运算和数值稳定性是额外代价。

矩的求解

可以用 Hamburger 四矩 MSM 的构造理解“从矩得到比例”具体在做什么。将 m0=1m_0=1,构造

B=(1m1m2m1m2m3m2m3m4).B=\begin{pmatrix} 1&m_1&m_2\\m_1&m_2&m_3\\m_2&m_3&m_4 \end{pmatrix}.

这个矩阵记录二次多项式的平方平均:任意系数 a\mathbf a 都有

aTBa=E[(a0+a1Z+a2Z2)2]≥0.\mathbf a^TB\mathbf a =\mathbb E[(a_0+a_1Z+a_2Z^2)^2]\ge0.

因而合法矩对应对称半正定矩阵。对于正定且不退化的情形,给定查询深度 tt,先解

Bc=(1tt2),B\mathbf c=\begin{pmatrix}1\\t\\t^2\end{pmatrix},

再求二次多项式 c0+c1z+c2z2=0c_0+c_1z+c_2z^2=0 的两根 a,ba,b。构造在 t,a,bt,a,b 三个深度上有质量的候选分布,权重由

(111tabt2a2b2)(wtwawb)=(1m1m2)\begin{pmatrix} 1&1&1\\t&a&b\\t^2&a^2&b^2 \end{pmatrix} \begin{pmatrix}w_t\\w_a\\w_b\end{pmatrix} =\begin{pmatrix}1\\m_1\\m_2\end{pmatrix}

确定。特定多项式根的构造使该候选也符合高阶矩约束;把严格位于 tt 之前的权重相加,得到这一矩问题的遮挡下界。

1
2
3
4
5
6
7
8
查询并解码过滤后的四阶矩
对量化后的矩进行适当正则化
构造3×3矩阵 B,检查退化与数值条件
求解 B * c = (1, t, t²)
求二次多项式的两个实根 a、b
求三个候选深度的权重
累加小于接收深度 t 的权重作为阴影估计
处理异常值并将最终阴影限制到合法区间

若矩阵奇异,会存在非零二次多项式 qq 使 E[q(Z)2]=0\mathbb E[q(Z)^2]=0;非负平方的平均为零,意味着分布只能落在 qq 的零点上,最多对应两个离散深度。这解释了四矩为何能够充分表达某些只有两层深度的情况,也说明不能在该特例里继续直接求矩阵逆。

实际实现可用 Cholesky 分解,将对称正定矩阵分成三角因子的乘积,再顺序求解;并按 tt 与两根的位置直接计算分支,减少通用求逆。矩阵近奇异、二次系数接近零或量化使矩失去合法性时,需正则化与回退。这一形式允许候选深度位于实数轴上;限制到 [0,1][0,1] 的 Hausdorff 版本有不同分支,不能随意把根裁到区间后继续套同一推导。

四矩可使用专门的线性或仿射变换改善量化分布,因为仿射变换在归一权重下可以与平均交换。把两个 FP16 的原始位直接塞成一个 FP32,再按普通浮点数过滤,却不保留这个性质。存储格式和统计语义必须一起设计。

距离场

除了把深度统计存成二维贴图,也可以直接保存空间中到几何的距离。有符号距离场 Signed Distance Field,SDF 在物体外为正、内部为负、表面为零,绝对值表示到最近边界的距离。

例如半径为 RR、中心为 c\mathbf c 的球有

d(p)=∥p−c∥−R.d(\mathbf p)=\|\mathbf p-\mathbf c\|-R.

它比单张阴影图保留更多空间关系,可以从不同位置查询,但三维数据的存储和构建通常更贵。

直接混合边界图与混合距离场的区别

上排 A、B 的边界位置不同,直接混合黑白图会在中间产生灰色区域;下排先转换到连续距离值,再插值,两侧正负范围的零分界便移动到新位置。最右图将这个零分界重新显示为形状,所以得到的是移动的边界,而不只是两个形状的半透明叠加。

若 ds=(1−s)dA+sdBd_s=(1-s)d_A+sd_B,需要取 ds=0d_s=0 的等值面恢复形状。图中的 SDF−1\mathrm{SDF}^{-1} 表示这种几何提取,不是普通的可逆函数。插值后的场未必仍是严格的最近距离场;若要拿来步进,需要额外确认它不会高估安全距离,或采用保守界。

球体追踪

在物体外的点 p\mathbf p,若真实距离为 d(p)>0d(\mathbf p)>0,以它为半径的开球内没有表面。射线从该点出发,走不超过这个距离便不会穿过最近表面;这就是球体追踪 Sphere Tracing 的基础。

沿射线使用逐渐变化的安全球推进

远离树木时,安全球大,一步能走得较远;接近树冠后,球变小,步长随之缩短。算法查询的是当前位置到任意几何的最近距离,不能预先认为最近表面一定就在射线方向上。

射线方向 r\mathbf r 需归一化,令 p(t)=o+tr\mathbf p(t)=\mathbf o+t\mathbf r,则

tj+1=tj+d(p(tj)).t_{j+1}=t_j+d(\mathbf p(t_j)).

1
2
3
4
5
6
7
从表面偏移后的起点开始,令 t 为小的正值
重复有限次数:
查询当前位置的距离 d
若 d 不大于命中阈值,报告遮挡
若 t 已超过光源或追踪范围,报告未发现遮挡
t = t + 保守安全距离
达到迭代上限时,按实现策略处理未完成查询

近切线、细小几何和粗网格距离场可能需要很多步。起点自交、负距离、纹理插值误差和非均匀缩放也需处理;增加最小步长虽然能避免停滞,却可能跳过薄物体,不能将任意正步长都称为安全。

安全角

同一个空球还给出方向信息。观察点为 o\mathbf o,射线上的点为 p\mathbf p,空球半径是 d(p)d(\mathbf p),中心距离为 t=∥p−o∥t=\|\mathbf p-\mathbf o\|。从观察点向球作切线,形成半角 θ\theta:

sin⁡θ=d(p)t,θ=arcsin⁡d(p)t.\sin\theta=\frac{d(\mathbf p)}t, \qquad \theta=\arcsin\frac{d(\mathbf p)}t.

这是直角三角形中的半径除以斜边。要求 t>0t>0,比例在合法范围内;很小的角度下 sin⁡θ≈θ\sin\theta\approx\theta,便能直接用 d/td/t 估计角尺度。

不同安全球给出不同角度,沿路保留最小角

蓝、红、橙三个球分别对应 p1,p2,p3p_1,p_2,p_3。同样一个球半径,离观察点越远,张开的角也会越小;需要沿追踪路径比较半径与距离的比值,而非只比较绝对距离。最小安全角意味着附近遮挡物最接近所查询的方向束。

软影估计

一个常见的距离场软阴影启发式,将沿路的最小比例转换成可见率:

V^=min⁡j{1, kd(pj)tj}.\widehat V=\min_j\left\{1,\,k\frac{d(\mathbf p_j)}{t_j}\right\}.

真正命中遮挡物时取 00;没有命中时,这个量根据离障碍物的角度间隙减弱直接光。它利用了安全角与光源角范围的关系,但并没有精确积分一个面光源所有可见方向。

由上到下k为2、8、32时的距离场软影

上图 k=2k=2,过渡较宽;中图 k=8k=8;下图 k=32k=32,阴影更接近硬边。kk 越大,较小的角间隙就能让结果达到 11,因此半影越早结束。它控制角尺度,不能简单当作物体的材料粗糙度。

沿球体追踪同时维护最小 kd/tkd/t,就能得到硬遮挡与近似半影,额外工作相对较少。完整面光源的大小、方向、多个遮挡物以及采样步长仍会影响精度,不能把这个比例解释成严格的未遮挡面积百分比。

存储与误差

场景几何的网格距离场可视化

建筑、树木、车辆不再显示真实材质颜色,而是用于观察距离场所表达的几何及查询行为。轮廓、薄片和复杂区域能帮助检查体素分辨率与追踪开销;具体可视化的灰度取决于实现,不能直接当作物体反射率或一个统一线性距离值。

距离场阴影依赖几何预处理与额外存储。刚体变换可以复用物体局部场,形变或拓扑变化则可能要求更新。粗采样会漏掉薄几何,三线性插值也不保证恢复精确距离;若距离被高估,步进可能穿透表面。

非均匀缩放改变不同方向的距离,不能只乘任意一个缩放因子继续宣称安全。实现需要相应的保守缩放、距离下界或更准确构建。速度、质量与内存取决于几何、分辨率、步数及数据组织,距离场并非对所有场景都比阴影贴图便宜。

字体应用

同一类表示也能用于文字。二维 SDF 保存到字形轮廓的有符号距离,绘制时依据零分界确定内外,并用像素足迹决定过渡宽度。

放大字形仍可依据距离阈值重建连续边缘

图中的文字是被研究的渲染对象:细笔画、衬线和曲线边缘在放大后仍按距离场重建,不是把普通正文截图用来替代 Markdown。若内部距离为负,可用

α=1−smoothstep⁡(−w,w,d)\alpha=1-\operatorname{smoothstep}(-w,w,d)

计算覆盖过渡,ww 按屏幕空间导数或相应像素尺度选择。缩放时重新判断边缘,比直接放大已光栅化颜色图更容易保持平滑;原距离纹理仍有有限分辨率,过尖角、细笔画和极端缩放不保证无误差,因此“无限分辨率”是效果描述,不能理解为有限数据包含任意几何细节。