约 40 分钟技术学习游戏引擎

Games104学习笔记(29)

GAMES104:动态全局光照和 Lumen(下)

课程:GAMES104《现代游戏引擎:从入门到实践》
第 21 讲(下):动态全局光照和 Lumen(Part 2)
本地视频:21.动态全局光照和Lumen (Part 2) _ GAMES104-现代游戏引擎:从入门到实践-p01-80.mp4
本地视频时长:约 1 小时 34 分钟 38 秒
版本说明:以课程演示的实现为主,课件中的预算、距离、纹理尺寸及耗时不代表所有 UE 版本的默认值。

一、知识主线:从“找到表面”到“取得光照”

上半讲解决了 GI 的基本问题,以及用 Mesh SDF、Global SDF 查询几何与可见性的办法。本讲继续回答:

  • 光线命中一个表面后,从哪里取得它向外反射的光?
  • 如何让间接光经过多次反弹,而不在一个像素中递归追踪完整路径?
  • 如何在极低的光线预算下,让全分辨率画面获得平滑、可信的照明?

可以把整套系统理解为以下知识链:

Mesh Cards 捕获表面 → Surface Cache 缓存材质与光照 → Voxel Lighting 支持粗几何命中的光照查询 → Screen Probes 收集当前视图需要的方向光照 → World Radiance Cache 复用远场结果 → 重要性采样与滤波 → 全分辨率像素积分。

其中存在两种不同的复用:

  1. 表面光照的跨帧反馈,使多次反弹逐渐传播。
  2. 探针光照的空间、方向与时间复用,使少量新光线服务于大量像素。

Lumen 不是单一的“光追算法”,而是一套围绕不同查询需求设计的几何表示、缓存、采样和重建系统。

二、先区分几类数据:不要把所有 Cache 当成同一种东西

数据或表示 主要保存什么 主要解决什么问题
Mesh SDF 单个网格的距离场;查询时保留对象身份 较精细的近距离几何命中、遮挡
Global SDF 合成后的世界距离场 大范围、低成本几何追踪
Mesh Cards 多方向表面捕获的投影与参数化 把三维表面组织成可缓存的二维区域
Surface Cache 表面材质属性,以及直接、间接和合成光照 已知具体表面后,快速取得它的光照
World Space Voxel Lighting 世界空间体素中的粗光照表示 Global SDF 命中后取得近似表面光照
Screen Probes 当前视图表面位置附近的方向辐亮度和命中距离 以稀疏探针支撑可见像素的最终收集
World Space Radiance Cache 世界空间探针的远场方向辐亮度 避免相邻屏幕探针重复执行昂贵的远距离追踪

最容易混淆的是最后三项:

  • Voxel Lighting 是面向粗几何命中的光照查询表示。
  • Screen Probes 是面向当前视图的最终收集表示。
  • World Radiance Cache 是为远场光照建立的共享探针缓存。

它们可以配合使用,但不是三个不同名字指向同一张纹理。

三、Mesh Cards:给三维表面建立一组二维“快照”

3.1 为什么需要 Cards

如果每次 GI 光线命中时都重新运行完整材质着色、计算所有灯光和阴影,成本会很高。

一个替代方案是提前或按需捕获表面属性,把光照结果存放在二维纹理里。命中时只需定位到对应区域并采样。

Mesh Card 可以理解为:

用正交相机从某个方向观察网格,将这个方向可见的表面投影成二维纹理。

课件展示了六个轴向方向上的捕获。每张 Card 具有局部和世界空间包围盒,以及轴向方向索引。

3.2 六个方向不等于“每个模型永远只有六张卡”

六个轴向方向说明捕获方向的组织方式,不意味着任意复杂网格都能用固定六张卡获得完整覆盖。

凹陷、内部结构、遮挡和复杂形状会造成覆盖困难。理解 Cards 时应关注:

  • 哪些表面实际被捕获到了?
  • 对应区域是否具有足够分辨率?
  • 运行时命中位置能否映射到有效的缓存区域?

没有覆盖的表面,不会因为有 SDF 就自动获得正确材质和光照。

3.3 它不是传统 Lightmap

传统 Lightmap 往往主要保存离线烘焙的静态照明结果。

本讲的 Surface Cache 则把表面参数化与动态光照更新结合起来:材质捕获和光照更新是分开的工作,可以按预算刷新。

所以:

二维存储不等于静态烘焙;关键在于存了什么、如何生成、何时更新。

四、Surface Cache 的生成:捕获、拷贝与压缩

4.1 第一遍:Card Capture

课件展示的捕获数据包括:

  • Albedo:漫反射颜色。
  • Normal:表面法线。
  • Depth:捕获方向下的深度。
  • Emissive:自发光。

后续 Surface Cache 层还包括 Opacity。捕获并不是把最终游戏画面截下来,而是保存能够支持后续光照计算的表面属性。

更新策略考虑:

  1. 固定的每帧 texel 预算。
  2. 到相机的距离。
  3. GPU 使用反馈。
  4. Card 在屏幕上的投影大小。

课件给出的捕获预算示例为 $512\times512$ texel。它是当时的工程配置,不是算法必须满足的数学常数。

4.2 第二遍:写入 Atlas 并压缩

捕获结果被拷贝到较大的 Surface Cache Atlas 中,再对适合的层做压缩。

课件示例使用 $4096\times4096$ Atlas,并展示总体存储从约 320 MB 降到约 88 MB。

这里值得记住的是工程思路:

  • 集中存储,方便 GPU 统一访问。
  • 对不同物理量采用合适的精度与压缩方式。
  • 深度、颜色、法线和 HDR 自发光不能简单套用同一种编码。
  • 捕获预算与缓存容量是两件事:一帧只更新部分 texel,不意味着 Atlas 只有这么大。

五、表面缓存中的直接光照

5.1 从逐 texel 遍历所有灯,变成按 Tile 分配工作

课件中的做法包括:

  • 将 $128\times128$ page 划分成 $8\times8$ texel 的 tiles。
  • 以 tile 为单位裁剪不相关灯光。
  • 在课件配置中,每个 tile 选择前 8 个灯光。
  • 使用 1-bit 阴影掩码表达课件中的二值可见性,再累加有效灯光贡献;它不是完整的连续透射率模型。

核心是先减少“表面区域 × 灯光”的无效组合,再计算照明。

灯光数量上限是预算限制,不表示物理世界中一个表面最多只能被八盏灯照亮。

5.2 阴影贴图与 SDF 配合

课件的流程是:

选择待更新 tile → 采样 Shadow Map → 用 SDF 补充屏幕外相关阴影查询 → 应用灯光。

这说明直接光照缓存本身也依赖混合可见性方案。不能把 Lumen 理解成所有可见性都只由一种光追方法负责。

5.3 直接光照与间接光照是相对于接收表面分类的

光源直接照到表面 $x$,属于 $x$ 的直接光照;先照到其他表面,再反射到 $x$,属于 $x$ 的间接光照。

一个自发光面直接照亮接收面时,这段传输仍是直接照明。它经其他表面反弹后才成为更高阶间接光。

本讲后面会把自发光加入表面出射辐亮度,以供其他位置查询。

六、为什么 Global SDF 命中后不能直接采样 Surface Cache

6.1 几何命中信息不等于表面地址

Mesh SDF 查询可以保留:

  • 命中的 Mesh ID。
  • 世界空间命中位置。
  • 表面法线。

已知网格身份,才能进一步定位它的 Cards 和 Surface Cache 区域。

而课件所示的 Global SDF 合成表示只提供粗略的命中位置与法线,没有足够的 per-mesh 信息。

所以,问题不是“Global SDF 不知道在哪里命中”,而是:

它缺少从命中点寻址到某个具体网格表面缓存的身份信息。

6.2 用 Voxel Lighting 建立另一条查询路径

解决办法是把 Surface Cache 中的合成光照注入世界空间体素表示。

Global SDF 命中后,依据世界位置及方向相关信息查询 Voxel Lighting,而不必反查具体 Card。

这用较低精度换取了低成本和大范围覆盖。细节较粗,不等于它完全没有方向相关的光照信息。

七、Voxel Lighting:先建立表面关联,再注入光照

7.1 六方向短光线查询

课件展示了对每个体素沿六个轴向方向执行短距离 Mesh Distance Field 追踪。

为理解课件中的端点写法,设体素中心为 $\mathbf{c}$,轴向单位向量为 $\mathbf{a}$,半径参数为 $r$,则一条短线段为:

$$ \mathbf{x}{\mathrm{start}}=\mathbf{c}-r\mathbf{a}, \qquad \mathbf{x}{\mathrm{end}}=\mathbf{c}+r\mathbf{a}. $$

这里 $r$ 是课件对应的体素半径参数,不应在没有实现上下文时擅自解释成体素对角线长度。

查询记录:

  • Hit Object ID。
  • Hit Distance。

二者打包进 Visibility Buffer,建立体素查询位置与附近真实表面之间的关联。

7.2 用 Tile 筛选候选对象

课件展示了 $4\times4\times4$ voxel tile 的候选对象过滤,以及用 InterlockedMin 保留较近命中结果。

工程重点是:

先按空间局部性缩小候选集合,再做短线段查询,避免每个体素扫描场景中的全部对象。

7.3 光照注入

课件给出的步骤包括:

  1. 清理对应 Clipmap 中的 Voxel Lighting。
  2. 压紧有效 Visibility Buffer 条目,减少无效工作。
  3. 依据命中对象和距离,找到相关表面。
  4. 采样 Surface Cache 的 Final Lighting。
  5. 将结果注入世界空间体素光照。

注意:清理光照数据不等于必须把整个场景距离场与所有几何关联每帧完全重建。几何表示更新、关联更新、光照刷新应分别理解。

八、表面间接光照:稀疏探针代替逐 texel 追踪

8.1 探针布置在 Surface Cache 的 Tile 上

课件中:

  • 每个 $8\times8$ texel tile 放置 $2\times2$ probes。
  • 每个 probe 服务于约 $4\times4$ texels。
  • 每个 probe 从半球追踪 16 条光线。
  • 对探针位置和光线方向做抖动。

这是用于更新表面缓存间接光的探针,不要与后面服务当前视图的 Screen Probes 混为一谈。

8.2 四邻探针插值

完成稀疏采样后,表面 texel 从附近四个探针取得间接光照。

用简化的标量或 RGB 光照量 $I_j$ 表示探针结果:

$$ I(x)\approx\sum_{j=1}^{4}w_j(x)I_j, \qquad w_j\ge0,\quad \sum_{j=1}^{4}w_j=1. $$

上式只是插值的概念表达。真实实现还需考虑有效性、几何关系以及缓存中的方向表示。

它降低了追踪次数,但也引入了重建误差:如果跨越遮挡边界无条件插值,就可能漏光。

九、跨帧反馈:多次反弹不是在每个像素里递归完成的

9.1 课件中的依赖关系

设第 $n$ 帧:

  • $D_n$:表面直接光照。
  • $I_n$:表面间接光照。
  • $F_n$:表面合成出射光照。
  • $V_n$:世界空间 Voxel Lighting。

逻辑依赖为:

$$ V_{n-1} \longrightarrow I_n, \qquad (D_n,I_n,L_e)\longrightarrow F_n, \qquad F_n\longrightarrow V_n. $$

这里的箭头表示数据依赖,不是所有 GPU pass 的精确调度顺序。

表面间接光使用已有世界光照信息,合成后的表面光照再反馈到世界表示,为后续更新提供输入。

9.2 用一个简化迭代式理解

对近似 Lambert 漫反射表面,若 $D_n$、$I_n$ 都按辐照度定义,逐颜色通道有:

$$ F_n(x)=L_e(x)+\frac{\rho(x)}{\pi}\left[D_n(x)+I_n(x)\right]. $$

其中 $\rho$ 是漫反射反照率,$L_e$ 为自发光辐亮度,$F_n$ 为近似漫反射出射辐亮度。

可进一步写成教学用迭代模型:

$$ I_n=\mathcal{G}(V_{n-1}), \qquad V_n=\mathcal{P}(F_n). $$

$\mathcal{G}$ 代表追踪、采样和间接光收集,$\mathcal{P}$ 代表向世界光照表示的投影或注入。它们不是课程代码中的某两个同名函数。

注意不要重复乘 Albedo:如果某个缓存量已经是出射辐亮度,就不能把它当成尚未乘材质的辐照度再次使用。

9.3 反弹为什么能继续传播

从尚无间接光的初始状态开始,第一轮把直接照亮的表面作为后续照明来源;之后的更新会读到其他表面已经反射过的光,从而逐渐包含更高阶反弹。

但“第 $n$ 帧严格等于第 $n$ 次反弹”只是理解反馈机制的理想化说法。实际系统有:

  • 分批 page 更新。
  • 不同缓存的更新频率。
  • 历史复用。
  • 空间滤波。
  • 已有高阶光照状态。

因此,一帧不是一个可精确计数的物理反弹阶段。

9.4 反馈复用的代价

好处是把昂贵的光传输拆成可控的持续更新任务。

代价是变化不会总在同一帧传遍所有缓存:开灯、关灯、物体移动后,间接光可能短暂滞后。

另外,漏光、低分辨率误差和错误历史也可能被反馈继续传播。因此缓存有效性与稳定更新是算法的一部分,不只是附加优化。

十、固定预算下的光照更新优先级

课件给出的示例预算:

  • 直接光照:$1024\times1024$ texels。
  • 间接光照:$512\times512$ texels。

Page 更新优先级写为:

$$ \mathrm{Priority}=\mathrm{LastUsed}-\mathrm{LastUpdated}. $$

这里两项是使用和更新的时间或帧序号。最近被使用、但已经较久未更新的区域,应得到较高优先级。

课件采用 bucket sort 管理优先队列,示例为 128 个 buckets,按优先级选取工作直到耗尽本帧预算。

这体现了实时系统的设计目标:

不是让所有缓存每帧都最新,而是在稳定的帧成本内,让当前需要的区域尽可能可靠。

十一、Screen Probes:把大量像素的方向采样合并起来

11.1 为什么不让每个像素独立追踪大量光线

漫反射照明需要对半球方向积分。在室内,小窗、灯具等高亮区域只占很小的方向范围,少量均匀光线很容易错过。

逐像素只追踪一两条光线,不能自动获得高质量 GI;如果没有足够复用和重建,会出现严重噪声。

Screen Probe 的做法是:

  • 在当前可见表面上布置稀疏采样位置。
  • 每个位置存储多个方向的入射辐亮度。
  • 让附近像素共享这些方向数据。
  • 像素最终按自身法线和材质进行积分。

共享的是照明信息,不是强迫整个屏幕块使用同一个法线。

11.2 Screen-space 布局,World-space 采样位置

Screen Probes 在屏幕上分布,但通过深度还原到三维表面位置。

因此它既不是只记录一个二维像素颜色,也不是固定覆盖整个世界的均匀探针网格。

相机移动会改变哪些表面需要探针,这也是它必须配合历史复用与世界空间缓存的原因。

十二、Octahedral Atlas:把球面方向放进二维纹理

课件中的探针使用带边界的八面体映射,通常每个 probe 存储 $8\times8$ 的方向纹理。

一个二维 texel 对应一个世界空间方向,Atlas 保存:

  • Radiance。
  • Hit Distance。

八面体映射的价值包括:

  1. 用紧凑二维布局表示球面方向。
  2. 相邻探针采用一致的方向索引。
  3. 易于按方向读取、滤波和复用。
  4. 边界处理避免纹理滤波在映射接缝处产生明显不连续。

注意两点:

  • $8\times8$ 是方向维度的存储规模,不是这个探针覆盖的屏幕像素块大小。
  • 不能仅凭“二维网格均匀”就认定球面上每个 texel 的立体角严格相等;积分权重仍需匹配实际方向采样方案。

十三、自适应布置:在无法插值的地方补探针

13.1 规则布局为何会失败

一个规则屏幕网格单元可能同时包含:

  • 前景人物和远处墙面。
  • 门框和门后的房间。
  • 细栏杆和背景。
  • 深度急变的轮廓边缘。

二维距离很近,不代表这些像素处于相同的三维照明环境。

13.2 Hierarchical Refinement

课件展示从 $16\times16$ 到 $8\times8$、再到 $4\times4$ 屏幕像素间距的逐层细化。

核心流程:

  1. 建立较稀疏的基础探针。
  2. 检查周围探针能否有效插值到目标像素。
  3. 在失败位置追加探针。
  4. 继续细化,直到有效或达到预算上限。

额外探针存放在 Atlas 的附加区域。Atlas 有容量上限,自适应并不意味着无限增加采样点。

13.3 用局部表面平面检查几何一致性

设目标像素的世界位置为 $\mathbf{x}$,单位法线为 $\mathbf{n}$,邻近探针位置为 $\mathbf{p}_j$,则到目标切平面的距离为:

$$ d_j=\left|\mathbf{n}\cdot(\mathbf{p}_j-\mathbf{x})\right|. $$

课件用相对深度差构造快速衰减的权重。概念上可写为:

$$ w_j^{\mathrm{depth}} =2^{-k(d_j/z)^2}, \qquad z>0,\quad k>0. $$

$z$ 是用于归一化的有效场景深度。实际代码必须拒绝无效深度,并避免除零。

再将该权重与双线性权重相乘:

$$ \widetilde{w}_j=w_j^{\mathrm{bilinear}}w_j^{\mathrm{depth}}. $$

若总权重足够,再归一化;如果所有候选几乎无效,则需要补探针或采用回退,不能仅靠除以一个很小的数就宣称插值有效。

十四、探针抖动与时间累积

课件将探针直接放在有效像素上,并跨帧抖动:

  • 探针位置。
  • 采样方向。

还展示了 Hammersley 序列。它是用于较均匀覆盖采样域的低差异序列,不是简单的独立白噪声。

抖动的意义是让不同帧观察不同采样位置与方向,配合时间复用减少固定采样图案和噪声。

可用教学用混合式理解时间滤波:

$$ \overline{L}n =(1-\alpha)\overline{L}{n-1}^{\mathrm{reprojected}} +\alpha\widehat{L}_n, \qquad 0<\alpha\le1. $$

其中 $\widehat{L}_n$ 是当前估计,历史量需要重投影并经过有效性检查。上式不是本讲展示的完整历史滤波实现。

不能把相机移动、遮挡变化或灯光变化后的旧数据无条件平均进来,否则会出现拖影和延迟响应。

十五、重要性采样:让有限光线指向更有贡献的方向

15.1 积分中有两种重要性

对反射项,可写成:

$$ L_r(x,\omega_o) =\int_{\Omega^+} L_i(x,\omega), f_r(x,\omega,\omega_o), \max(\mathbf{n}\cdot\omega,0), \mathrm{d}\omega. $$

蒙特卡洛估计为:

$$ \widehat{L}r =\frac{1}{N}\sum{k=1}^{N} \frac{ L_i(x,\omega_k), f_r(x,\omega_k,\omega_o), \max(\mathbf{n}\cdot\omega_k,0) }{ p(\omega_k) }. $$

$p$ 是相对于立体角的实际采样 PDF,不是随意选取的亮度或权重。

被积函数中有两种互补信息:

  • Lighting importance:哪些方向可能有强入射光?
  • BRDF importance:哪些方向对接收材质贡献大?

只按 BRDF 采样,可能遗漏小窗;只按亮度采样,可能把光线浪费在表面背面或材质响应很弱的方向。

15.2 从上一帧探针估计 Lighting importance

课件的步骤是:

  1. 重投影到上一帧。
  2. 从四个邻近 Screen Probes 的方向辐亮度取得估计。
  3. 利用 Octahedral Atlas 中已有的方向索引,避免昂贵搜索。
  4. 屏幕邻居被遮挡或不适用时,回退到世界空间探针辐亮度。

这是用历史照明指导新采样,并不是把上一帧画面直接当作最终正确结果。

新出现的灯光、突然变化的遮挡会降低该预测的可靠性,因此不能把“历史很暗”绝对等同于“当前贡献为零”。

15.3 BRDF importance 不应只看探针中心的法线

一个 Screen Probe 会服务多个像素,周围像素的法线可能不同。

课件做法是收集附近像素的漫反射方向响应:

  • 在约 $32\times32$ 屏幕范围采集 64 个邻近像素。
  • 按几何深度权重筛选,课件展示的接受阈值为 0.1。
  • 将相关像素的法线所对应的漫反射传输分布累积到 SH。

这不是只计算“平均法线”再采样一个半球,而是近似描述多个接收像素共同需要的方向。

课件代码还对特殊材质作保守处理,避免错误裁剪那些材质可能需要的方向。

十六、固定 64 条光线:通过重分配提高采样效率

课件展示的 Screen Probe 追踪预算为每个 probe 64 条光线。

策略为:

  1. 从较均匀的方向布局开始。
  2. 为方向 texel 计算 BRDF importance 与 Lighting importance 的乘积。
  3. 按重要性排序。
  4. 对低于裁剪阈值的低重要性方向减少采样。
  5. 将释放的预算用于高重要性方向的细分采样。

课件举例:每裁剪三个低重要性方向,就可以把某个高重要性方向的一份样本扩展成四份,保持总光线数量不变。

关键不是“更多追踪”,而是“相同预算里更多有效追踪”。

16.1 乘积权重不是自动成立的 PDF

若把两个近似方向分布的乘积当作采样依据,还必须归一化:

$$ q(\omega)= \frac{ \widetilde{p}{\mathrm{light}}(\omega), \widetilde{p}{\mathrm{BRDF}}(\omega) }{ Z }. $$

$\widetilde{p}$ 表示构造重要性时使用的近似非负权重,归一化常数为:

$$ Z=\int \widetilde{p}{\mathrm{light}}(\omega’), \widetilde{p}{\mathrm{BRDF}}(\omega’) \mathrm{d}\omega’, \qquad 0<Z<\infty. $$

场景全暗或两个权重的有效方向没有交集时,可能有 $Z=0$;此时不能做上述归一化,需要改用有效的基础采样或其他回退分布。

这里有两个不同的分母:$Z$ 只用于把重要性权重归一化为提议分布;第 15.1 节蒙特卡洛估计的每个样本,则必须除以实际产生该样本的立体角 PDF $p(\omega_k)$。

离散方向格子还要匹配各自的立体角与子格子采样规则。若真实采样还包含基础分布混合或方向细分,不能直接拿尚未体现这些操作的 $q$ 当作实际 PDF。

16.2 实时方向裁剪可能带来偏差

只要被积函数非零的方向被赋予严格零概率,通常就不能保证无偏估计。

所以本讲的阈值裁剪与方向重分配,应理解为实时性能、噪声和偏差之间的工程取舍,不应据此宣称“重要性采样完全没有误差”。

作为通用数学解释,若想避免提议分布遗漏有效方向,可保留一部分具有完整支持的基础采样;这不是声称课件一定采用了某个具体混合比例。

十七、探针空间滤波:共享方向,不急着混合最终像素颜色

17.1 为什么探针空间滤波划算

课件示例中,一个 Screen Probe 覆盖 $16\times16$ 屏幕像素。

在探针空间做 $3\times3$ 邻域滤波,覆盖的屏幕尺度约为 $48\times48$ 像素,但不需要逐像素执行同样大的滤波核。

17.2 同方向数据便于复用

相邻探针的 Octahedral texel 对应相同世界方向,因此可以直接访问匹配方向的辐亮度。

课件说明此阶段可不以法线差异作为主要限制,而是重点使用深度权重。

原因是还在过滤方向入射辐亮度;每个像素之后仍按自己的法线进行漫反射积分。

这不表示几何边界可以忽略。空间位置改变会改变遮挡和入射光,因此还需要深度与命中几何相关的判断。

17.3 不同位置看同一个命中点,会产生角度误差

设邻近探针的某条光线命中世界位置 $\mathbf{y}$,当前探针为 $\mathbf{p}$。从当前探针指向该点的方向为:

$$ \omega’=\frac{\mathbf{y}-\mathbf{p}}{|\mathbf{y}-\mathbf{p}|}. $$

若准备复用的方向为 $\omega$,可以用:

$$ \theta_{\mathrm{error}} =\arccos\left(\operatorname{clamp}(\omega\cdot\omega’,-1,1)\right) $$

衡量方向不匹配。方向均需归一化,重合位置等退化情况需排除。

课件展示了小于约 $10^\circ$ 的角误差条件。

远处命中点从相邻位置看过去,方向差通常较小,适合共享;近处遮挡变化大,复用容易抹掉局部阴影,应更谨慎。

这就是“滤远场噪声,同时尽量保留局部遮挡”的直观原因。

十八、World Space Radiance Cache:把远场追踪变成共享工作

18.1 远场为什么特别难

课件指出:

  • 小而亮的特征越远,张开的角度越小,采样噪声更突出。
  • 长距离、非相干光线追踪较慢。
  • 相邻 Screen Probes 会重复查询相似远场光照。
  • 远场光照随空间位置通常变化较慢,具有缓存机会。

这里“变化较慢”是相对于邻近位置的空间变化,并不是说远方灯光永远不会随时间变化。

18.2 分开处理近场与远场

Screen Probes 保留局部遮挡与近场细节,世界探针共享更远处的方向辐亮度。

课件演示以约 2 米作为近场与远场的划分尺度。这是该配置的工作范围,不是由物理定律推导出的普适距离。

同时要区分:

  • 近远场 Radiance Cache 的划分。
  • Mesh SDF 与 Global SDF 的追踪范围划分。

二者目的相关,但属于不同层次的预算分配,不能仅因距离接近就当成同一件事。

18.3 世界空间缓存有更稳定的误差

缓存位置锚定在世界空间,误差不容易完全跟着屏幕采样网格跳动。

这有利于稳定画面,但不保证自动正确。几何变化、缓存分辨率和更新延迟仍会造成失真。

十九、连接 Screen Probe 与 World Probe 的光线

19.1 起点不同,不能直接复制同一方向

Screen Probe 和 World Probe 位于不同位置。

即使两个探针查询同一个方向,它们看到的几何也可能不同。若直接采样同一方向,容易出现视差错误和错误遮挡。

19.2 世界探针跳过插值影响范围

课件强调 World Probe ray 应跳过 interpolation footprint。

直观上:

  • 插值单元内部的近处遮挡由局部追踪负责。
  • 世界探针主要描述单元外较远的照明。
  • 如果世界探针把单元内部遮挡也强行混入共享结果,附近不同位置插值时就容易互相污染。

这不是随意忽略近处物体,而是把近处与远处的责任拆开。

19.3 用球面视差近似修正方向

课件使用 simple sphere parallax:

  1. 把屏幕探针射线与世界探针的近似球面相交。
  2. 得到球面上的连接位置。
  3. 从世界探针中心指向这个连接位置。
  4. 按修正后的方向读取世界探针辐亮度。

若屏幕探针位置为 $\mathbf{x}$,方向为单位向量 $\omega$,世界探针中心为 $\mathbf{c}$,近似球半径为 $R$,则求正向交点:

$$ |\mathbf{x}+t\omega-\mathbf{c}|^2=R^2, \qquad t>0. $$

令交点为 $\mathbf{q}$,修正方向为:

$$ \omega_{\mathrm{corrected}} =\frac{\mathbf{q}-\mathbf{c}}{|\mathbf{q}-\mathbf{c}|}. $$

这是课件图示的几何解释;适用时必须选择有效正向交点,无交点或退化情况需要回退。

球面只是视差近似,不代表场景真实几何是一面球,也不能精确恢复复杂遮挡。

二十、世界探针的放置、复用与刷新

课件展示的流程:

  1. 标记之后会进行插值的位置。
  2. 在 Clipmap indirection 中找到对应世界探针。
  3. 已有探针复用上一帧追踪结果;缺失位置分配新 probe index。
  4. 对部分缓存条目重新追踪,传播光照变化。
  5. 生成光线、追踪,再做探针空间滤波。

这里的 indirection 将“世界网格位置”与“实际存储索引”分开,使有限缓存可以服务不断变化的查询范围。

这是一种需求驱动的资源分配:优先维护当前真正会用到的探针,而不是无限铺满整个世界。

世界缓存和 Surface Cache 的共同点,是把昂贵更新限制在固定预算内;不同点是它们缓存的物理量、空间布局与消费者不同。

二十一、从探针辐亮度到全分辨率像素:SH 积分

21.1 为什么漫反射适合 SH

漫反射对整个半球方向进行加权积分,会平滑高频方向变化。

因此低阶球谐 SH 能较紧凑地表示与漫反射积分相关的方向光照,避免每个像素重新读取、积分全部方向 texels。

课件采用 Three-band SH,并使用“3rd order”这一叫法。为避免不同文献的 order 约定混淆,这里明确指:

包含 $l=0,1,2$ 三个频带,每个颜色通道共 9 个系数。

不是包含到 $l=3$ 的 16 个系数。

21.2 先投影 Radiance,再进行漫反射卷积

采用实正交归一球谐基,对颜色通道 $a$:

$$ c_{lm}^{a} =\int_{S^2}L_i^{a}(\omega)Y_{lm}(\omega),\mathrm{d}\omega, \qquad l=0,1,2,\quad -l\le m\le l. $$

若探针覆盖完整球面,余弦截断核的卷积可写为:

$$ E^{a}(\mathbf{n}) \approx\sum_{l=0}^{2}A_l\sum_{m=-l}^{l} c_{lm}^{a}Y_{lm}(\mathbf{n}), $$

其中:

$$ A_0=\pi,\qquad A_1=\frac{2\pi}{3},\qquad A_2=\frac{\pi}{4}. $$

再对 Lambert 漫反射应用:

$$ L_{\mathrm{diffuse}}^{a} \approx \frac{\rho^{a}}{\pi}E^{a}(\mathbf{n}). $$

这组公式是便于复习的标准数学展开,不是课件给出的完整 Shader。若某实现已把卷积系数或 $1/\pi$ 吸收到存储系数中,就不能重复应用。

21.3 像素仍使用自身的法线与材质

全分辨率像素插值或读取邻近探针的系数,再按自身法线执行积分。

因此附近像素可以共享同一组方向照明,却表现出不同的受光结果。

21.4 SH 不适合无条件承担尖锐镜面反射

低阶 SH 擅长低频方向分布,无法精确表示窄高光或清晰镜像。

课件还展示了按 BRDF 重要性采样方向、再查询 Radiance Cache 的积分思路。不能把漫反射 SH 分支直接视为所有粗糙度与所有反射类型的唯一解法。

二十二、分层追踪:命中信息决定光照查询路径

课件展示了先屏幕空间、再 Mesh SDF、再 Global SDF,最后环境回退的流程。

路径 课件中得到的命中信息 光照读取 主要边界
Screen Space Trace 屏幕 UV 上一帧 Scene Color 只能利用屏幕可表示的信息;要处理历史有效性
Mesh SDF Trace Mesh ID、世界位置、法线 Surface Cache Final Lighting 网格距离场精度、对象范围和追踪预算有限
Global SDF Trace 世界位置、法线 Voxel Lighting 几何与光照更粗,缺少直接表面缓存寻址信息
环境回退 没有场景表面命中 Sky Cubemap 只能表示环境照明,不能恢复漏掉的室内遮挡

课件中的参数示例包括:

  • 屏幕空间 HZB:最多 50 步。
  • Mesh SDF:最大追踪距离约 1.8 米,候选对象位于相机周围约 40 米范围。
  • Global SDF:最大追踪距离约 200 米。

这些距离表达不同限制:“对象相对相机的选择范围”不等于“从当前射线起点可追踪的长度”。

另外,未命中可能是场景确实开放,也可能是步数耗尽、表示缺失或追踪精度不足。工程上不能把所有失败都解释成物理上无遮挡的天空方向。

硬件光追是另一种几何查询路径,也可以结合 Surface Cache 或命中点光照。它不会自动消除采样噪声、材质查询和缓存更新的成本。

二十三、性能:低光线数量是整套复用共同产生的结果

课件给出了一个 PS5 性能示例:

  • 1080p 内部渲染分辨率。
  • 用 Temporal Super Resolution 输出到 4K。
  • 平均约半条光线/像素。
  • 示例流程总耗时约 3.74 ms。

同时另一幅示例标注约八分之一条光线/像素、2.15 ms Final Gather。

必须保留测试边界:

  1. 这是课件示例,不是当前所有场景的性能承诺。
  2. Final Gather 时间不等于整帧时间。
  3. 该流程耗时不能直接当成 Surface Cache 更新、全部反射和整个 Lumen 系统的总耗时。
  4. “半条光线/像素”是分摊后的平均工作量,不表示每个像素都发射半条物理光线。
  5. TSR 输出 4K 不等于所有 GI 查询都在原生 4K 分辨率执行。

性能来源不只是 SDF 追踪快,还包括:

  • 表面材质和光照缓存。
  • 局部候选裁剪。
  • 稀疏探针。
  • 同方向空间滤波。
  • 近远场分工。
  • 时间复用。
  • 重要性采样。
  • 按需更新和固定预算。
  • 较低内部采样分辨率与重建。

二十四、系统性局限:找到误差来自哪一层

24.1 几何表示误差

薄物体、复杂内部结构、距离场分辨率不足,可能产生漏光或错误遮挡。

更精确的追踪表示能改善几何查询,但不一定修复缺失的表面缓存。

24.2 缓存覆盖与分辨率误差

Cards 未覆盖、Atlas 分辨率不足或体素光照过粗,都可能使真实表面与缓存表示不一致。

24.3 采样误差

小面积高亮源、强方向性照明、历史重要性预测失效,会增加噪声或遗漏贡献。

24.4 重建误差

探针插值跨越几何边界、视差修正不充分、滤波过强,会出现漏光或局部细节变软。

24.5 时间误差

固定更新预算与历史复用带来延迟;无效历史没有及时拒绝,会出现拖影。

24.6 物理模型的覆盖边界

课件末尾用真实场景展示直接光、间接光、光泽反射、散射和焦散等现象。

它提醒我们:渲染方程描述的传输很复杂。本讲详细展开的缓存和漫反射最终收集方案,不等于已经以相同精度解决了透明折射、焦散或所有介质散射。

二十五、常见混淆

25.1 “Lumen 是完全不需要预处理的动态 GI”

动态光照更新不等于没有资产预处理。距离场、Cards 等表示可以包含离线构建工作,运行时再更新其可见性或光照状态。

25.2 “SDF 里面就有颜色和材质”

SDF 主要回答几何距离与命中。材质、表面光照及远场入射辐亮度分别由其他表示提供。

25.3 “Surface Cache 就是最终屏幕画面”

Surface Cache 存的是场景表面表示及其光照,不是视图中的最终像素缓冲。Screen Probe 与全分辨率像素积分是后续工作。

25.4 “Radiance Cache 可以替代所有近场追踪”

近场遮挡对位置敏感,远场共享缓存不能无条件替代局部追踪。

25.5 “多次反弹是每条射线递归很多次”

本讲通过缓存反馈逐步更新多反弹照明,不要求每个最终像素在同一帧追踪完整多反弹路径。

25.6 “重要性权重越大,直接乘出的结果就越亮”

重要性主要决定采样预算。估计照明仍需按实际采样概率校正,否则会把采样偏好错误地当成物理能量。

25.7 “滤波不看法线,所以不同表面可以随意平均”

探针阶段共享的是方向辐亮度;深度、位置、命中距离和可见性仍然重要,像素阶段也仍使用自身法线。

25.8 “硬件光追更精确,所以缓存可以全部删掉”

硬件光追提高的是某些几何查询的能力,并不免费提供足够采样、材质着色、降噪或多次反弹。

二十六、复习要点

  1. Cards 把三维表面组织成二维可寻址区域,Surface Cache 进一步保存表面属性与光照。
  2. 材质捕获、直接光更新、间接光更新具有不同预算和刷新需求。
  3. Mesh SDF 保留对象身份,Global SDF 的合成表示不直接提供同等的 Surface Cache 地址。
  4. Voxel Lighting 为粗世界几何命中建立低成本光照查询路径。
  5. Surface Cache 与世界光照的跨帧反馈,使高阶反弹逐渐进入缓存状态。
  6. 更新预算决定响应速度;多反弹复用不等于瞬时达到无误差平衡。
  7. Screen Probes 以稀疏位置存储方向辐亮度,服务大量全分辨率像素。
  8. 八面体映射统一方向寻址,自适应布置修复规则探针无法有效插值的位置。
  9. 历史辐亮度和附近像素的方向响应共同指导重要性采样。
  10. 固定光线预算通过方向重分配提高效率;阈值裁剪仍有偏差风险。
  11. 命中距离帮助筛选空间复用,避免把近处遮挡过度平滑。
  12. 世界空间辐亮度缓存承担远场共享,球面视差修正帮助连接不同起点的光线。
  13. 三频带 SH 将漫反射方向积分压缩为少量系数运算,不能精确表示尖锐镜面。
  14. 分层追踪的命中信息不同,因此对应不同光照读取路径。
  15. Lumen 的实时能力来自表示、预算、复用与重建的协作,不来自某个单独的“万能算法”。

参考资料

来源边界:本文主要根据本地视频课件整理;带有“概念表达”“教学用”“数学展开”的公式和解释属于辅助推导。课件末尾的问答只核对到了提问画面,未把未转录的口头回答写成讲者原话。