【Siggraph 2025】MegaLights - Stochastic Direct Lighting in Unreal Engine 5
来源:D:\迅雷下载\Graphics Materials\Siggraph 2025 - MegaLights - Stochastic Direct Lighting in Unreal Engine 5.pdf 提取时间:2026-05-15 16:17:59
Slide 1

SIGGRAPH 2025 游戏实时渲染的进展课程
大家好,我的名字是克日什托夫,我们想与蒂亚戈·科斯塔一起展示我们的新作品 虚幻引擎 5 中的随机直接光照技术。
Slide 2

📌 要点汇总
- 光照质量需求:游戏追求动态灯光、阴影及逼真柔和区域光,需复杂BRDF与分层材料模拟。
- 工作流程瓶颈:图形质量受限于复杂流程,艺术家需更高效工具(如程序化灯光)以减少限制。
- 基线技术要求:照明方案必须为艺术家提供核心视觉目标,且需兼容游戏机与PC GPU性能。
游戏不断地提高质量标准,想要使用更多的灯光,他们想要每个灯光 具有动态性并投射阴影并希望拥有具有逼真柔和的区域光 阴影。他们还想使用复杂的 BRDF、光源或分层材料 需要多次 BRDF 评估来模拟穿过材料的光 层。通常情况下,仅进行无阴影光评估就变得太过分了 昂贵。
与此同时,游戏变得越来越复杂,我认为我们现在正处于关键时刻 其中工作流程实际上是游戏图形质量的主要限制因素。理想情况下 艺术家应该能够轻松地工作,没有太多限制,就像这样 截图在这里。这可能有点过分,但是,这就是发生的事情 当艺术家弄清楚如何按程序放置灯光时。
另一个关键点是这必须是基线照明技术。某事某事 艺术家可以在制作过程中将其作为主要视觉目标。它不可能是额外的 技术,这需要艺术家进行额外的重新照明,并且会使事情变得复杂 工作流程。它至少必须能够在游戏机和相应的 PC GPU 上运行。
Slide 3

📌 要点汇总
- 前向/延迟照明:适用于小规模灯光,但灯光数量增加时计算成本剧增
- BRDF光线追踪:离线渲染常用,固定光线追踪数量使性能与照明复杂度无关
- 阴影处理差异:前向方法依赖阴影贴图或光线追踪阴影,需预计算遮罩
-
辐照度整合:通过预积分辐照度结合阴影项实现灯光逐屏应用
我们可以通过多种方式实现直接照明。
游戏中通常的方法是我们进行前向或延迟照明,其中 对于屏幕上可见的每个光,我们首先使用阴影贴图预先计算阴影项 或者可能是光线追踪阴影,对其进行去噪并预先计算阴影遮罩。并且 然后在一个单独的通道中,我们将灯光在屏幕上一一应用,并结合它们 带有计算阴影项的预积分辐照度。这对于小规模的人来说非常有效 灯的数量,但随着灯数量的增加,每个灯做功可以得到 昂贵得令人望而却步。
另一种进行直接照明的方法(在离线渲染中更常见)是 基于 BRDF 或朝向随机子集追踪固定数量的光线 光,如果我们击中光,我们就会积累它的能量。这里的主要好处是 现在性能与照明复杂性无关。我们只追踪一个固定的 每个像素的光线数量,而不是为每个光线做工作。
Slide 4

📌 要点汇总
- 延迟光照挑战:光线追踪阴影与去噪成本高,大量灯光导致冗余计算
- 缓存阴影限制:动态灯光与内存不足导致缓存失效,VSM方案仍无法满足需求
- 光源能量分布:80%光照来自单一光源,建议
1 最重要的光
鉴于延迟光照在游戏中的流行程度,这是我们首先要考虑的地方 开始了我们的调查。我们研究了如何加速光线追踪阴影的方法, 光评估等等,但事情并没有真正适应我们想要的照明 复杂性。
当我们仔细查看内容时,很明显为什么我们无法点击 我们的目标。例如,该像素处于 50 个灯的衰减范围内,并且对于每个灯 我们需要计算阴影贴图或者光线追踪和去噪阴影, 但只有 15 个灯光会影响该像素,所以我们在这里做了很多无用的工作。
部分成本可以通过缓存阴影贴图来隐藏,但事实并非如此 改变缩放那么多。在影子之前我们只能缓存这么多东西 由光线、相机或物体移动引起的缓存失效会影响性能。 例如,在 MegaLights 演示中,我们让机器人在场景中飞行,创建 数百个移动灯,完全打破了任何缓存方案。此外 即使一切都是静态的,缓存阴影贴图页面也需要 不合理的内存量。在我们的 MegaLights 演示中启用 VSM(虚拟 Shadow Maps) 填充阴影贴图虚拟页的最大分配大小 4GB 缓存,但仍然无法容纳所有必需的灯光,从而导致各种伪影。
光线追踪阴影可以使用自适应追踪(调整 每个像素或每个图块的迹线数量)并使用稀疏阴影掩模来保存 内存,但这并不会改变整体缩放比例。追踪光线和 去噪是相当昂贵的,并且每个灯都进行去噪会造成困难且相对较小
限制灯的数量。
即使我们能以某种方式免费处理阴影,仍然存在一个问题 评估每个像素的大量灯光。理论上只有 15 个灯,但这些很复杂 轻型类型和复杂的材料,这使得它们在控制台上太昂贵 即使他们不会受到阴影。
如果我们观察这 15 种可见光,就会发现 80% 的能量来自单一光,所以 为什么我们要尝试暴力破解这 50 个灯?为什么不只计算单个光 以高质量并近似其余?
Slide 5

另一种方法是使用 BRDF 采样或基本上使其成为一个 GI 问题。
这是 UE5 中的常见解决方法。艺术家在其中放置了某种发射网格 场景中,将它们从主视图中隐藏起来,并将它们用作柔和的区域光源 分析灯。
这本质上是免费的,因为我们无论如何都必须计算 GI,但附带了一堆 质量问题。小发射面或较远的发射面 即使通过流明(我们的 GI/反射系统)光线引导技术。
另一个问题是实时 GI 通常需要直接光照的帮助。甚至 在离线渲染中,艺术家经常使用一些技巧,例如按顺序将区域光放置在窗口中 加速GI收敛。这里我们在控制台上做实时GI,60hz, 我们不是帮助 GI 进行分析光,而是要求它进行计算 直接照明。
Slide 6

📌 要点汇总
- 第三种方法:通过固定光子集跟踪光线,累积光能后降噪,实现扩展性。
- 光线选择关键:需避免被遮挡光线,最大化每条射线的利用效率。
- 灯光层次结构局限:预构建结构忽略可见性,导致照明错误和泄漏问题。
- ReSTIR潜力:在高端PC表现优异,但需适配控制台
第三种方法是构建一个新系统,我们随机选择一个固定的 每个像素的光子集并跟踪朝向它们的光线。如果光线射到灯上,那么我们 撞击并将光能累积到单个渲染目标中的阴影。最后我们是 完成所有跟踪后,将对该渲染目标进行降噪。这可以更好地扩展, 因为无论场景中有多少个光源,我们总是这样做 每个像素的固定工作量。
当然实际操作起来没那么简单。在控制台上,我们可以每次做 1 条光线 像素,在这种情况下,光的选择变得非常重要,正如我们想要的那样 最大限度地利用每条射线。例如,在右侧的图表中,我们描绘了 两束光线射向两盏灯,它们非常接近我们的着色点,并且似乎 确实很重要,但是它们都被遮挡了,所以我们浪费了整个 预算,无需计算任何内容。
光线选择的方法有很多。
最流行的之一是不同类型的轻型层次结构,我们首先 围绕灯光建立一些层次结构,然后尝试选择最重要的集群。 预构建的层次结构可以加速光采样,但它没有考虑可见性和 正如我们在该图中看到的,可见性是灯光选择的关键部分。光 层次结构还可以实现某种光合并(层次 LOD),但在 在实践中我们遇到了太多问题(照明不正确、泄漏等)。最后 构建每个帧的灯光层次结构可能非常昂贵,因为此操作 不能很好地转化为 GPU。
另一种非常流行的方法是 ReSTIR。它可以运送一些令人惊奇的东西 在高端 PC 上的结果,但我们能否将其缩小到控制台,以便它 成为我们的基准照明方法?
Slide 7

📌 要点汇总
- ReSTIR机制:通过重用历史样本与邻近像素的可见性信息,结合新候选样本提升渲染质量
- 性能瓶颈:样本重用与光线追踪可见性检查显著增加
为了回答这个问题,我们首先需要看看 ReSTIR 实际上是什么 确实如此。
ReSTIR 将这几个橙色块添加到随机直接照明中,它将查找 历史上的一些样本和一些邻居,通过追踪来检查他们的可见性 射线,最后将这些重复使用的样本与新的候选样本结合起来 随机选择这一帧。
这里的主要思想是,如果我们不能随机选择一个好的候选样本,如 例如,我们选择的所有样本都被遮挡,可能我们有 历史上更好的东西,或者也许我们邻近的像素更幸运 灯光选择。
ReSTIR 极大地提高了质量,但缺点是这种重用增加了高 恒定成本。不仅重用操作本身成本高昂,而且最重要的是 我们必须通过追踪光线来检查每个重复使用的样本的可见性。
为了达到合理的质量,我们希望至少有 1 个 SPP,这 每个像素需要 2-3 条迹线。在高端 PC 上这可能不是什么大问题,但在 在控制台中,我们实际上无法追踪每个像素超过 1 条光线。
Slide 8

📌 要点汇总
- 候选抽样:需精确选择灯光以保证质量,而非完全随机
- BRDF加权:灯光需按BRDF加权,确保像素覆盖20%灯光列表
- 硬件成本差异:游戏机因灯光评估成本高,需优化无阴影采样
- 阴影处理缺陷:BRDF不考虑阴影,遮挡光易导致样本冗余
- 成本与效率平衡:高恒定成本下需调整采样策略,使用新常数优化
另一个问题是候选抽样。
理论上我们可以为每个像素选择一些完全随机的灯光,但实际上 为了达到可运输的质量,我们需要非常仔细地选择这些灯。 我们需要通过 BRDF 对每个光进行加权,并且我们需要能够在 每个像素至少 20% 的灯光列表。这对于高端产品来说可能也不是什么大问题 PC,但在游戏机上,这些成本积累得非常快,就像我们基本上所做的那样 对场景中 20% 的灯光进行无阴影灯光评估。
最重要的是,BRDF 不考虑阴影,并且强烈的遮挡光会 收到大量样本使得发现良好的可见光变得更加困难。
总而言之,我们的恒定成本很高,我们已经无法承受,但我们仍然 需要解决与以前类似的光采样问题,只是使用不同的常数。
Slide 9

📌 要点汇总
- ReSTIR样本重复问题:初始样本重复率高导致噪声减少但降噪器效果下降
- 时空过滤机制差异:ReSTIR使用更长历史记录但可能破坏采样模式
- 优化设计目标:
AABBCC 的时间累积 ABCABC 的时间累积
这是一个很好的问题 - 有什么事情我们可以比 ReSTIR 做得更好吗?
在玩随机光采样时,我们注意到有时只是 简单采样比 ReSTIR 效果更好。对此的解释非常简单。 初始样本有更高的重复机会,因为每一帧都有 将这些初始样本连接到当前帧样本的路径呈指数级增长。 这就是为什么在实践中 ReSTIR 实现钳制 M(数量 帧以将样本保留在历史中),但即使使用钳位,这种聚集效应仍然存在 突出。为了解决这个问题,我们需要将 M 限制为 1,这将有效地 禁用任何重用,我们将回退到简单的随机采样。那些团块 重复样本的数量使得 ReSTIR 输出的噪声更少,但也大大降低了 降噪器的有效性。为了让降噪器发挥最佳效果,我们希望 光的不相关和交替图案。
从另一个角度来看,ReSTIR 和降噪器的屏幕效果非常相似 空间、空间和时间过滤。区别在于 ReSTIR 重新着色 重用样本而不是重用已经着色的样本,具有更长的时间 历史记录(通常是 2 倍长)并且这些样本不必经历历史记录 整改。这通常允许 ReSTIR 积累更多时间帧并 更积极地重用邻居,但它也会打乱采样模式,这在 有些情况实际上可能会导致整体质量下降。
那么为什么不跳过时空重用,而是设计我们的采样 降噪器,这样我们就可以更便宜地实现类似的质量,并且能够适应
我们的目标预算有限?
Slide 10

对所有灯光进行采样 仅对可见光进行采样
理想情况下,我们只对每个像素的可见光列表进行采样。
拥有这样的列表将允许我们在每帧中随机选择不同的灯光 为降噪器生成漂亮的模式。
仅对可见光进行采样可以防止我们浪费工作来追踪 隐藏的灯光,对最终像素没有贡献,只会浪费我们的资源 样本预算并增加噪音。
Slide 11

📌 要点汇总
- 8x8图块共享:通过8x8屏幕空间图块共享光能见度,减少内存开销并提高采样效率。
- 随机双线性查找:采用随机双线性插值技术,平滑图块间光列表过渡并加速可见光传播。
- 显式列表替代布隆过滤器:显式列表支持额外有效负载和直接采样,优于布隆过滤器的二进制可见性方案。
- 样本深度引导限制:8x8
随机双线性可见光列表查找 最近的可见光列表查找
历史可能是此类可见光列表的重要来源,例如 可见的最后一帧可能也将在下一帧可见。
由于内存开销,我们实际上无法为每个像素提供一个灯光列表,但我们可以 将其用于 8x8 屏幕空间图块。相邻像素有很高的共享概率 光能见度。为了创建这样的列表,在跟踪过程之后,我们收集所有可见的 灯光样本并使用 WaveActiveMin 输出每个 8x8 图块的排序灯光列表。在接下来的 我们可以在采样过程中重新投影我们的像素,查找适当的图块并 从可见光列表中选择一种光。
我们还尝试使用各种降权方案而不是二进制 可见性,其中每个光线将根据光线命中/未命中的调整后的比率进行加权, 但事实证明在实践中效果较差,因为此类方案追踪的光线较少 半影中的样本。通常我们实际上想要相反的东西,就像半影一样 有很多噪音,我们不想对它们进行欠采样。
8x8 的图块相当大,有时会产生一些明显的不连续性。 本质上,我们是在图块边框上从一个灯光列表切换到另一个灯光列表。在 为了解决这个问题,我们使用随机双线性查找,这将平滑地插值 4 个最接近的列表之间。不仅隐藏这些转变,而且还加速新的转变 可见光在屏幕上的传播。
8x8 屏幕空间图块确实会降低样本深度引导的有效性 不连续性,但实际上它并没有那么糟糕,因为我们累积了每个光可见度
像素。
最初我们使用布隆过滤器,我们发现这很有趣,因为布隆过滤器既是 巧妙的数据结构,在实时渲染中也相当罕见。后来我们 切换到显式列表,因为这些列表允许每个灯有额外的有效负载并允许 对这样的列表进行采样,而无需迭代光栅单元内的所有灯光。
这些列表也可以有一个小的硬编码大小,因为从根本上来说它们的长度是 受每个 8x8 图块可见样本数量的限制。另一种看待它的方式是 如果我们对 1SPP 进行着色,那么即使在降噪器中进行时间累积,我们也无法 确实积累了太多的灯光(无论我们如何挑选灯光),这意味着 每个图块的最大可见光数量受到着色样本数量的限制 每个像素。
Slide 12

📌 要点汇总
- 动态采样策略:同时
我们不能只对可见光列表进行采样。场景是动态的,隐藏的灯光可能 变得可见。我们需要花费样本预算的一部分来发现 新的可见光。
我们在这里所做的是从可见光和隐藏光列表中进行采样,然后我们 将隐藏灯列表权重总和限制为总权重总和的 20%。这样我们 能够为隐藏的灯光分配固定数量的样本。
这可以很容易地通过将可见光采样到一个隐藏的水库中来完成 灯进入第二个,并在之前夹紧隐藏的光储器重量 将它们合并在一起。两个水库都使用单独的随机变量,因此它们 不相关。我们还根据可见光列表添加隐藏光库 随机变量,它允许我们维护可见光列表随机变量噪声 属性。
20% 当然只是一个任意可调整的数字,它控制着之间的权衡 收敛后的质量和遮挡期间的质量/技术反应的速度 到场景变化。
有时可见光可能非常暗淡,或者我们可能没有任何本地灯光 所有。在这种情况下,我们放松 20% 的钳位,以便可以追踪更多光线 隐藏的灯光可以加快场景变化或遮挡的收敛速度。
隐藏灯光预算比降低隐藏灯光的权重效果更好,因为强隐藏灯光
灯光永远不能主导采样(超过 20% 的采样预算)。我们的方法是 非常擅长处理硬案例,例如强完全遮挡的灯光,这 通常会主导采样并导致大量噪声。
有时,历史重新投影会由于对象移动或屏幕外而失败 抽样。在这种情况下,我们仍然重复使用最近的图块,因为它可能有一些有用的灯光,但是 我们还增加了隐藏光样本的比例,以加速新的可见光 发现。
Slide 13

📌 要点汇总
- 新管道结构:引入橙色模块构建可见光列表,优化采样流程
- 成本效益:通过可见光列表采样降低计算开销,提升效率
- 隐藏光处理:少量痕迹检查隐藏光,不影响主流程性能
- 降噪应用:最终灯光列表用于生成高质量降噪图案
现在,当我们有了这个可见光列表时,我们可以查看我们的新管道。很漂亮 与我们之前看到的类似,但我们添加了一个橙色块来负责 用于构建可见光列表。下一帧此列表用于采样灯光 使我们能够以相当小的成本构建此列表来指导样本。
我们确实分配了一些痕迹来检查隐藏的灯光,但它相对较小 开销。大部分光线被发送到可见光并贡献 朝向最终像素。
最后我们有一个灯光列表,这将使我们能够为灯光生成漂亮的图案 降噪器。
Slide 14

📌 要点汇总
- 加权水库抽样:通过循环灯光列表并按权重随机选择样本,实现高效采样。
- 感知加权优化:利用对数调整灯光亮度权重,缓解强光对最终像素的过度影响。
- STBN纹理应用:时空蓝色噪声纹理提供优化后的随机模式,支持引擎内多种屏幕空间操作。
- 预计算限制:STBN纹理需按像素顺序单次采样,无法直接重复使用以生成独立随机变量。
现在让我们充分利用我们的灯光列表。
为了选择我们的样本,我们使用加权水库抽样,您可以 请参阅底部,这是一种非常简单的方法,可以循环所有灯光一次并 根据体重随机选择一个。
我们使用对数进行感知加权,根据 BRDF 的亮度对每个灯进行加权。 感知加权是一种总体质量改进,但最重要的是它允许 我们减轻非常强的灯光的重量,在色调映射后不会有那么大的灯光 对最终像素的影响,有助于解决强烈的遮挡光问题。
时空蓝色噪声提供具有噪声模式的查找纹理,这些噪声模式是 针对去噪进行了优化。这些模式真的很好(而且便宜),我们使用它们 整个引擎在屏幕空间中进行不同类型的随机操作。
这里只有一个小问题。这个查找纹理给了我们一个随机的 每个像素都有一个变量,但正如我们在这里看到的,我们需要为每个像素一个随机变量 我们的样本选择循环的迭代。我们不能只对 STBN 纹理进行多次采样 次,因为它是专门预先计算的,按顺序对每个像素采样一次 保持那些良好的 STBN 模式属性。
Slide 15

📌 要点汇总
- 重用随机变量:通过重新映射保留原始噪声特性,实现样本选择范围的复用
- 抖动采样:将随机变量映射到多段,支持单像素多光线追踪的高效处理
- 双变量分配:使用两个独立随机变量分别管理可见光与隐藏灯光列表,缓解比特损失问题
-
性能限制:灯光数量受硬件性能约束,需平衡采样精度与计算开销
值得庆幸的是,有一些技巧可以让我们重用随机变量倍数 倍,同时仍保留原始噪声特性。
对于单个样本选择,我们可以在每次之后将所选范围重新映射回 0-1 光选择步骤。
如果我们想跟踪每个像素的多条光线,那么我们可以使用抖动采样,这 会将我们的随机变量重新映射到多个段。
任何类型的重新映射都将使用随机变量的一位精度,但实际上 这不是问题。我们使用两个随机变量进行采样,其中一个用于可见光列表 一个用于隐藏灯光列表,它允许将这一比特损失重新分配到两个 随机变量。另外,无论如何我们不能在每个列表上循环太多的灯光,因为 到性能限制。
Slide 16

📌 要点汇总
- 单个纹理查找:提升采样速度,优化性能。
- 保留STBN特性:维持原有质量优势,无需额外调整。
- **
所有这些不仅使我们能够仅使用单个纹理查找来更快地采样,而且 最重要的是它保留了那些良好的 STBN 特性。这是一个相当大的 质量改进并且完全免费 - 不需要任何额外 计算或跟踪。
Slide 17

📌 要点汇总
- 灯光优化:通过随机子集评估与动态调整光栅单元灯光数量,平衡连贯性与效率
- 双列表迭代算法:交替处理不同排序的灯光列表,聚焦最小光指数提升计算效率
- **
现在我们知道如何选择灯光,但在大场景中循环灯光中的所有灯光 网格单元可能会变得相当昂贵。这些光栅单元可能包含数百个灯。
我们在这里所做的是评估可见光列表上的所有灯光,然后我们 评估光栅中的一些灯光,跳过已经评估过的灯光 从可见光列表中。每个像素评估不同的随机子集,其中 使其变得非常不连贯,但在快速捕捉光线变化方面也非常有效。 如果我们检测到历史遗漏,我们会增加光栅中评估的灯光数量 细胞。
整个算法归结为迭代两个具有不同排序的灯光列表 步幅并评估两个列表的最小光指数。
我们可以在这里做的另一项简单优化是我们只需要 双向反射分布函数。我们发现全灰度 BRDF 计算(将所有输入转换为 灰度)增加了太多噪音,但我们能够更改一些代码,例如 将光分量累加器转换为灰度,减少 VGPR 使用。
我们还丢弃低于特定暴露相关阈值的样本。这个门槛 设置得相当低,因此几乎不会造成任何偏差(能量损失)。这不是一个 性能优化,但确实有助于质量。基本上如果光线不强 足以影响最终像素,而不是浪费光线来检查其可见性,我们 可以将该光线分配给更重要的事情。这也删除了一些萤火虫 来自非常不可能和昏暗的灯光,这些灯光的权重非常高
一些帧。
Slide 18

📌 要点汇总
- 采样策略:通过降低分辨率采样(如每4像素取4样本)并重用BRDF计算,提升效率。
- 采样模式优化:采用棋盘或四车模式并结合空间/时间抖动,提高像素重建成功率。
- 上采样技术:基于深度和法线进行随机双线性上采样,确保结果收敛至正确值。
- 特殊情况处理:无有效像素
每个像素 1 次采样 每 1/4 像素 4 个样本
如果像素的法线和深度相同,则像素之间的光权重通常非常相似 类似。我们可以使用它以较低的分辨率进行采样。例如代替 每个像素选取 1 个样本,我们可以重用 BRDF 每 4 个像素选取 4 个样本 计算。
这里重要的部分是我们需要使用良好的采样模式,例如 棋盘或四车。我们还在空间上抖动这些采样模式 暂时的。所有这些都极大地增加了我们重建最终像素的机会。
采样后,我们将根据深度和法线进行随机双线性上采样 权重,最终应该收敛到正确的结果。
在极少数情况下,我们可能没有任何有效像素可供上采样 - 所有权重 由于大深度或正常不连续性,可能为零。例如,可能有一个 细线,我们可能不会采样属于它的任何像素。在这种情况下我们重用 历史没有像邻里钳制那样进行任何类型的历史纠正。
由于历史修正和上采样器,这不会收敛到与 全屏采样,可以使阴影变得更柔和(在全分辨率和 半分辨率)。另一方面,它使采样速度几乎提高了四倍,因此它可以是 实践中相当不错的权衡。
目前我们正在努力将其更改为自适应采样方案,以便 保持全分辨率采样的质量和较低分辨率的更好性能
抽样。
Slide 19

📌 要点汇总
- 定向光问题:高权重导致采样偏差,影响局部光可见性
- 通道分离方案:独立计算定向光可提升质量但成本高昂
- 软预算控制:动态限制定向光样本比例,依赖局部光权重阈值
- 扩展性方案:20%隐藏预算可优化强光源(如聚光灯)处理
- 采样策略:根据局部光强度动态调整定向光追踪光线数量
定向光可能会给随机光采样带来很多问题。
定向光通常是非常强的光源,通常强数千倍 比场景中的其他任何东西都重要。当基于 BRDF 进行采样时,此类灯将 具有非常高的权重,这意味着在轻选择期间我们将发送 几乎所有光线都朝向它,并且几乎没有光线将用于局部光 当试图在室内发现新的可见光时,这可能是一个问题。
一个常见的解决方案是在单独的通道中计算定向光,例如 例如,为定向光运行专用的光线追踪阴影通道。这个 单独的通道也可以提高质量,因为现在我们可以运行单独的着色 并且仅针对定向光进行去噪。缺点是这可以 非常昂贵,因为我们现在必须跟踪每个像素的额外光线并运行另一个 着色和降噪通过,并且可能并不总是适合有限的游戏预算。
相反,我们所做的是限制可使用的样本预算的一小部分 对于定向光。这与我们夹住的隐藏灯非常相似 定向光源重量占局部光源重量总和的百分比。我们只有在以下情况时才这样做 本地光的权重总和高于某个阈值。这样如果没有本地 灯光或局部灯光非常昏暗,我们可以向 定向光比固定预算少 50%。
该方案本质上是一种软光线预算,有时我们会追踪更多 或更少的光线朝向定向光,具体取决于影响给定的局部光
像素。
其他光类型也可能存在与定向光相同的问题。例如, 有人可以使用非常强的聚光灯来模拟太阳。实际上我们没有运行 成这样的问题。比太阳弱的光通常只需通过以下方式即可很好地处理: 感知权重。 20% 的隐藏灯光预算也改善了此类灯光的处理, 因为我们可以保证他们最多会收到 20% 的射线。理论上还是这样 可以扩展该方案以选择此类非常强的光的列表并创建一个 为他们单独制定预算。
Slide 20

📌 要点汇总
- 区域灯可见性优化:使用2x2位掩码标记可见部分,减少被遮挡区域的样本浪费
- 2x2位掩码作用:细分二维随机变量抽样,提升区域光采样质量并适配多种光源形状
- 自适应细分需求:硬编码2x2细分无法满足所有
我们需要看的另一件事是区域灯。
正如您在此屏幕截图中所看到的,这些可能非常大并且只是二进制文件 光能见度还不够。此类光线的很大一部分可能被遮挡,我们 会浪费对其进行追踪的样本。
为了改进这一点,我们保留了一个额外的 2x2 位掩码,它标记了可见部分 每盏灯。该位掩码只是我们可见光列表中的有效负载,并且是一起构建的 与可见光列表。
更具体地说,2x2 位掩码细分用于区域光的 2d 随机变量 抽样。区域光采样函数旨在重新映射二维随机 变量从 [0;1] 平方到光源区域,同时保留区域,以便它们 最大限度地提高生成样本的质量。这样它在任何光线下都能很好地工作 来源(胶囊、球体等)。
硬编码 2x2 细分并不适合所有情况。有时我们会想要 有更多的细分,因为有些灯可能非常大。在其他情况下,例如线 对于灯光,我们可能希望有不同的细分比例,例如 4x1。我们目前 致力于将其变成一个自适应的分层方案。
Slide 21

在采样过程中,我们首先为每个像素选择 N 个灯光,然后对于每个选定的灯光,我们 需要在灯光表面选择一个点。
这个点选择将减轻隐藏区域的权重,这使我们能够追踪更多 光线射向光的可见部分,减少噪音。
每个区域光均使用 2d STBN 噪声和 2d 样本扭曲进行采样,以便 在降低隐藏区域的权重后保留良好的 STBN 属性。这些有点 STBN 和扭曲的风格与我们之前看到的不同,因为我们现在正在工作 与 2d 点。
Slide 22

📌 要点汇总
- 光线重复优化:通过复用相同像素光线的可见性结果,减少重复计算提升性能
- 半影大小调整:全局半影乘数可缩小光源尺寸,加速光线追踪但可能影响照明外观
- 适用场景扩展:优化方案适用于Steam平台、高端移动设备等性能受限但需保持画面质量的
由于采样的随机性,一些光线可能会重复。
例如,我们可能在表面附近有一个强点光源,并且迹线 4 相同 来自同一像素的光线射向该一点。我们真的不需要追踪所有 4条相同的射线。我们可以只跟踪 1 个并将其可见性重新用于其他 3 个。
对于距离很远的非常小的区域灯也可能发生这种情况,其中 半影太小了。
这在内容中并不常见,因为艺术家喜欢使用大面积灯光, 但它确实提高了性能一点,而且没有任何缺点。
它还允许调整全局半影大小乘数以进一步缩小。这个 性能可扩展性乘数将改变照明外观,因为它会减少 区域光源大小,但随着更多光线最终到达,它也会加速跟踪速度 重复并且将被跳过。对于 Steam 等平台来说,这可能是一个很好的权衡 甲板或高端移动设备,比当前一代游戏机慢得多, 但我们仍然希望运行相同的内容,而无需艺术家手动重新调整场景。
Slide 23

📌 要点汇总
- 重复使用射线:通过重复利用邻近像素的射线,减少光线追踪次数以优化性能。
- 屏幕空间内核:基于像素距离与射线命中距离动态调整内核大小,提升效率。
- 深度差异启发式:结合像素间深度差异等启发式方法优化射线重复使用逻辑。
- 概率重加权:因邻近像素概率分布不同,需对最终结果进行重新加权处理。
- 模糊接触阴影:在降低光线数量的同时保持阴影稳定性与锐利度,平衡视觉质量与性能。
自动缩小到当前一代控制台以下的另一种方法是重复使用射线 像素之间。
我们不只是对中心样本进行阴影处理,我们可以查找一些邻居,看看是否 他们的光线可以重复使用。
我们使用屏幕空间内核,其大小基于到该像素的距离,并且 射线命中距离。我们还检查了一些启发式方法,例如像素之间的深度差异。
最终结果也必须重新加权,因为我们在邻近的 像素的概率与中心像素中发生的概率不同。
它会模糊接触阴影,但它允许使用每个像素追踪更少的光线,同时 同时保持光线稳定和锐利。
Slide 24

📌 要点汇总
- 预积分辐照度:通过预计算光照明减少噪音并加速渲染,但假设阴影可分离(存在误差)。
- 向后兼容性:确保随机与非随机灯光在视觉上一致,支持高端PC ReSTIR实现。
- 阴影分离问题:近似方法可能引发误差(如Heitz等2018研究所述),需未来改进。
- 非游戏需求:当前方法在非游戏场景中存在局限,需针对性优化以满足更高要求。
最后,我们准备好对可见样本进行着色。
首先,我们累积影响给定像素的可见样本权重。然后我们乘以这个 通过预先积分的光辐照度累积重量(分析/预先计算的光 照明)。
使用预积分辐照度意味着我们假设我们可以分离 来自阴影的阴影,这是不正确的([Heitz et al. 2018] 中的介绍有一个 很好地描述了这个近似值以及它可能导致的问题),但它使得 有些事情会更快一点,噪音也更少。
最重要的是,它能够向后兼容,就像我们的随机灯看起来一样 与非随机的完全一样。这也是背后的原因 使用此近似值进行高端 PC ReSTIR 实现。
尽管如此,这绝对是我们想要在某个时候解决的问题,因为这是一个常见的问题 非游戏用例的请求。
Slide 25

📌 要点汇总
- 时间方差过滤:通过跟踪信号时间方差度量噪声,实现精准空间滤波
- 信号解调处理:消除非随机信号成分,避免材质数据模糊(如反照率)
- **分通道降噪
时间过滤器 空间过滤器 基于 Shading 过滤噪声像素 评估灯光的累积漫反射 和镜面信号时间方差可见样本
历史
着色后我们运行去噪。
仅使用 TSR,我们就已经获得了一些相当不错的结果,但有些地方 绝对需要专用的降噪器。
我们对所有灯光运行一次去噪通道(所有灯光都累积到 2 个渲染中) 目标),我们分别对漫反射和镜面信号进行降噪。
在去噪之前,我们对信号进行解调,这会消除非随机信号 它的物质部分。我们不想像反照率这样模糊材质数据。
整个降噪器基于SVGF引入的时间方差思想。我们 跟踪信号的时间方差,我们稍后使用它来度量噪声的大小 给定像素,以便我们知道该像素所需的强大空间过滤。这样我们 仅模糊图像的噪点部分。
Slide 26

📌 要点汇总
- 光照存储:使用两个32位渲染目标分别存储漫反射和镜面反射信号,避免色移伪影。
- 历史纠正:通过5x5邻域夹和YCoCg方差裁剪减少颜色偏移,
颞叶+TSR
在时间过滤器方面,这是我们重新投影历史并积累光照的地方 和照明时刻。
光照存储在两个 32 个渲染目标中。一种用于漫反射信号,一种用于镜面反射信号。 由于随机浮点量化,我们只能使用 32 位精度,这 防止各种条带或色移伪影。它似乎工作得很好 实践中,与 64 位参考相比,我们没有发现任何问题。
我们还存储照明亮度的第一和第二时刻,也是一组时刻 一种用于漫反射,另一种用于镜面反射。
Float11 和 Float16 的范围相当宽(-2^16 到 2^16),但仍然在一些范围内 极端情况下可以超过。为了防止夹紧时出现任何问题,我们 将所有照明值存储在预曝光空间中。
我们使用 5x5 邻域夹来进行历史纠正。这是一个相当大的区域,所以 首先,我们加载所有内容并将其打包到组共享中。
我们在 YCoCg 空间中运行方差裁剪,这减少了历史过程中的颜色偏移 整改。
一个有趣的技巧是,当新数据超出邻域边界时 我们根据与这些边界的距离来加速历史记录,这大大减少了 重影。这里的想法是,如果新数据确实与历史相差甚远,那么
我们很可能应该很快抛弃这段历史,而不是试图纠正它 并重复使用。我们的计算方法如下:
float3 ClampedHistoryDiffuseLighting = 钳位(HistoryDiffuseLighting,DiffuseNeighborhood.Center - DiffuseNeighborhood.Extent、DiffuseNeighborhood.Center + DiffuseNeighborhood.Extent); 浮动归一化距离到邻域 = 长度(abs(ClampedHistoryDiffuseLighting - HistoryDiffuseLighting) / max(DiffuseNeighborhood.Extent, 0.1f)); 浮动扩散置信度 = 饱和(1.0f - 归一化距离到邻域);
稍后使用 DiffuseConfidence 来减少累积帧的最大数量 历史(减少历史权重)。我们不允许它下降到 0,因为我们想要融入 至少有一些历史框架,以防止出现剧烈的过渡。
另一种是当我们使用下采样时,一些像素被重建 而且不太可靠,所以我们放松了对他们的邻里限制。这修复了一些 高度不连续特征(微小金属光栅等)的不稳定性,其中每个 由于几何形状和子像素抖动,帧输入可能看起来完全不同。
Slide 27

📌 要点汇总
- 稀疏内核优化:采用单个稀疏内核旋转替代多通道A-Trous,结合TSR技术消除过滤孔
- 动态应用策略:仅处理高时间方差像素,提升速度与锐度,依赖TSR降噪
- 绝对方差校正:针对强镜面照明的数值误差,避免误判无噪像素的绝对时间方差
- 遮挡处理机制:通过固定时间方差假设+空间采样累积消除萤火
空间过滤器与标准过滤器有点不同。而不是多个昂贵的 A-Trous 通道,我们使用单个稀疏内核,该内核按像素旋转。这有效 感谢 TSR(我们的时间 AA + 放大器),它可以清理任何过滤孔。
我们仅将其应用于相对时间方差较高的像素,这使得 事情变得更快更锐利。我们不需要在这里输出完美的图像,因为 TSR 可以处理一些噪音。
使用绝对方差有助于解决诸如强镜面照明之类的情况,其中微小的误差 由于数值精度问题,可能会导致较大的绝对时间方差,即使 这些像素没有噪音。
为了处理去遮挡,我们假设输入像素具有恒定的时间 方差(我们没有发现估计方差值得额外开销),增加 空间样本的数量并在色调映射空间中累积,从而消除了 萤火虫。当我们积累更多的帧时,我们就会淡出所有这些假设。之后 累积 4 帧历史数据后,我们完全禁用所有遮挡处理。
Slide 28

📌 要点汇总
- 分辨率差异问题:降噪器在低分辨率处理导致上采样后模糊或噪声残留,需权衡
去噪还有一个问题,我们需要在这里讨论。即 去噪以比上采样更低的分辨率进行累积和过滤。
这意味着降噪器历史记录中的单个像素对应于降噪器之后的多个像素 上采样。所以去噪时我们要么必须积累那些不相关的像素 导致模糊的照明,或者我们需要丢弃导致噪声的每一帧的历史记录。
对于逐光降噪器来说,这个问题并不那么突出。它们仅对阴影进行降噪 使用阴影掩模或比率估计器的术语,而灯光则在 非随机方式每帧每像素。在这种情况下,这个问题最明显 仅在半影周围。当对多个光源的合并辐照度进行去噪时, 问题更大,因为现在它模糊了所有可以非常明显的照明, 尤其是在人眼可以快速发现缺乏镜面细节的面部。我们 确实尝试做一些类似于每光比估计器降噪器的事情,方法是找到 每个像素最重要的光 (BRDF) 并将其分解出来。这在以下情况下效果不佳 由于光选择本身是随机的,所以现在光选择噪声将是 在更复杂的照明场景中在屏幕上可见。分解 BRDF 本身并不是 也很棒,因为现在所有时间和空间过滤器都将在错误的值上运行。 每个像素都可以被不同的重要光线分开,这可能会导致一些奇怪的现象 在最重要的光选择不连续的地方出现伪影,我们尝试 融合这些价值观。
理想情况下,我们的降噪器的历史记录也应该是显示分辨率,这样我们就可以 避免这个问题,但实际上这在控制台上可能会非常昂贵。它是
通常以 1080p 渲染,然后上采样到 4k,这现在需要 降噪器以 4k 速度运行时间滤波,使整个过程变慢约 4 倍。仍然 我们想要进一步研究的东西,至少作为扩展到高端的一种方式 个人电脑 GPU。
Slide 29

📌 要点汇总
- 关键词:采样80%像素能量可减少降噪
- 关键词:启发式方法依赖时间稳定性提升效果
- 关键词:优化镜面高光处理减少非平坦表面模糊
- 关键词:直接传递信号至TSR提升图像清晰度
- 关键词:裁剪图像锐度增强依赖采样稳定性
正如我们之前所看到的,每个像素通常只有几个重要的灯光。如果我们是 如果能够对一个像素的 80% 的能量进行采样,那么我们就可以减少 降噪或者甚至可能只是将信号直接传递到 TSR。
我们对此有一个很好的启发法。可见光列表给出了总量 可能影响给定像素的能量。我们还知道我们成功采样了什么 这个框架。例如,如果有一盏灯具有强烈的镜面高光 对于 80% 的能量,我们在这一帧中对其进行了采样,那么我们实际上不需要这样做 此处的任何去噪都可以将该信号直接传递到 TSR。
这种启发式方法需要一定的时间稳定性(时间积累),如 采样的灯光设置可能会因帧而异,但总体效果很好 在实践中。它不仅有助于提高输出图像的清晰度,而且还有助于提高输出图像的清晰度。 去噪问题,例如镜面高光重影或模糊,这些问题很难解决 正确重新投影,尤其是在非平坦表面上。
这里可能很难看到,但它确实使右边的裁剪图像变得更加明显 更锐利。
现在我要把它交给蒂亚戈。
Slide 30

📌 要点汇总
- **硬件
实例重叠
我们用来计算光样本可见性的主要方法是硬件射线 跟踪,这使我们能够避免渲染和维护多个的开销 每帧阴影贴图,这在处理大型图像时尤其成问题 动态灯光的数量。
虽然阴影质量极其重要,但我们无法表示 BVH 中的所有对象 用于渲染主视图的细节量。首先,有一个 每个顶点的内存开销较高,使用 Nanite 的 UE 项目往往使用高度 详细的网格。这也意味着 BVH 构建和跟踪可能会变得过于昂贵 最重要的是,kitbashed 环境会导致大量实例重叠,这 进一步增加了追踪成本。
因此,我们需要使用简化的代理网格以及激进的实例 剔除和聚合表示以降低射线中级别的复杂性 追踪。
Slide 31

📌 要点汇总
- 近场表示:使用代理网格平衡性能与精度,覆盖玩家150米范围
- 远场优化:通过合并实例、减少三角形计数降低光线遍历成本,存储于TLAS中
- 内联光线追踪:默认采用以提升控制台一代性能表现
- 层级简化:近场未命中时切换至更简化的关卡表示,优化远距离追踪效率
光线追踪代理
我们使用 2 种光线追踪表示级别: ● 近场,覆盖玩家周围 150 米的区域 相机,我们使用代理网格。 ○ 这些是原始几何图形的较低多边形表示,即 在性能和精度之间提供良好的平衡,非常适合 近距离追踪。 ● 如果光线没有击中任何近场网格并延伸到其半径之外,我们也会 跟踪更积极简化的关卡表示。 ○ 在此表示中,我们合并实例并显着减少 三角形计数以降低光线遍历成本。 ○ 远场表示存储在单独的 TLAS 中,这使得 由于 BVH 复杂性较低,这些跟踪速度更快。
我们默认使用内联光线追踪,因为我们在当前的情况下可以获得更好的性能 控制台的一代。
Slide 32

📌 要点汇总
- 代理网格光线追踪缺点:主要问题是代理与栅格化几何之间存在不匹配
- 代理与栅格化几何不匹配:导致光线追踪过程中的精度和效率问题
- 影响光线追踪精度和效率:不匹配可能引发计算误差与性能瓶颈
使用代理网格进行光线追踪有一个主要缺点,那就是不匹配 代理和栅格化几何之间。
Slide 33

这些不匹配会导致不正确的自阴影,因为光线是从 栅格化几何表面,它们可能会立即与代理网格相交 三角形。
在这些屏幕截图中,我们可以看到前面的墙上有不正确的阴影 玩家,因为该网格使用了我们无法在光线中有效表示的曲面细分 追踪。同样,在地板上,不匹配也会导致更多的自我阴影。 即使在玩家角色上,模拟的布料网格也不太好 在光线追踪中表示并导致不正确的阴影。
Slide 34

动画和 alpha 蒙版几何体还存在常见问题,即 准确地表示和追踪光线尤其昂贵。
Slide 35

📌 要点汇总
- 正面/背面剔除局限性:无法完全避免光线击中物体正面导致的遮挡问题(如右图示例)。
- 性能开销增加:使用剔除机制会增加约10%的光线追踪开销,因阻止了部分早期存在检测。
- 依赖代理网格不足:需引入后备机制解决剔除无法覆盖的不匹配问题,而非仅依赖代理网格。
不幸的是,这些不匹配问题不能通过简单地使用正面或背面来避免 光线上的面部剔除。 在左图中,我们可以看到背面剔除足以防止 不正确的咬合。然而在右边,我们可以看到光线也击中了一个物体的情况 代理的正面,导致不正确的遮挡。
最重要的是,使用正面或背面剔除会增加大约 10% 的开销 追踪,因为它可以防止光线遍历过程中的一些早期存在。
所有这些意味着我们不能仅仅依赖代理网格,而是需要后备 解决这些问题的机制。
Slide 36

📌 要点汇总
- 屏幕空间光线追踪:通过深度缓冲区追踪光线,避免自阴影错误,偏移世界轨迹原点。
- 接触阴影细节:屏幕轨迹可获取高精度接触阴影,但需像素精确以防止遮挡跳过。
- 光线长度定义:世界空间光线长度可能导致屏幕全范围追踪,增加计算成本。
- 代理网格优化:屏幕轨迹减少光线与代理几何的错误交互,提升阴影准确性。
- 固定步进限制:屏幕全范围追踪对固定步进方法成本过高,需优化算法。
代理网格
屏幕跟踪 世界轨迹与屏幕轨迹
因此,我们避免不正确的自阴影的主要方法是屏幕空间光线追踪。 由于屏幕光线是根据光栅化几何深度缓冲区进行追踪的,因此我们可以 依靠它们离开曲面而不会错误地与代理相交 几何。然后我们可以根据距离有多远来偏移世界轨迹的原点 屏幕跟踪得到,类似于此图所示,这避免了大部分自我 阴影问题。
另一个好处是我们可以获得接触阴影的细节,而这些细节在 BVH。然而,与典型的接触阴影不同,我们通常可以逃脱 由于点击次数较少且光线长度较短,我们需要屏幕轨迹 像素精确,否则我们可能会跳过遮挡物,并且光线长度定义为 世界空间,这意味着在某些情况下我们需要一路追踪 屏幕,这对于固定步进来说太昂贵了。
Slide 37

分层跟踪(最大值 = 50
我们依靠 HZB 追踪能够快速而准确地跳过空白区域,而无需 针对光线上的每个像素进行测试。
我们希望尽可能避免典型的屏幕空间伪影: ● 因此,我们默认假设非常保守的低表面厚度,这意味着 在大多数情况下,当光线落后时我们会回退到硬件光线追踪 表面而不是假设存在交叉点。 ● 另一个问题是,长屏幕走线可能会导致明显的伪影,因为 深度缓冲区别名,因此在实践中我们限制长度以避免这些问题。 ● 针对深度缓冲区进行跟踪也会导致其自身的自阴影 我们通过结合点和双线性采样深度来避免这些问题。
我们还使用模板位跟踪实例是否在光线追踪中表示,以及 如果光线穿过这些像素之一,我们会增加估计的厚度以获得 来自这些实例的更多接触阴影。
Slide 38

📌 要点汇总
- 内联跟踪与AHS跟踪:用于处理GI/反射,但现有方法在直接阴影中效果不佳。
- 完整命中评估:高精度但牺牲内联光线追踪性能,增加控制台开销。
- 分阶段跟踪策略:先轻量级内联跟踪,遇材质评估时启用连续射线,平衡精度与性能。
- 材质图alpha遮罩限制:艺术家定义的alpha遮罩不适用于固定功能实现,需其他方案。
- alpha mask近似方法:基于alpha mask的三角形构建BVH,廉价但非直接
内联跟踪 AHS 跟踪
而对于 GI 或反射,我们通常可以使用缩小或剔除等技巧 BVH 构建过程中的三角形基于 alpha mask,以廉价地近似遮挡, 这些方法对于直接阴影效果不佳。
理想情况下,我们会支持某种“固定功能”alpha 屏蔽,我们可以 使用内联光线追踪时直接评估,但由于艺术家能够定义 使用材质图的 alpha 遮罩对我们来说不太实用,所以我们只剩下 其他一些选项: ● 我们可以使用完整的任何命中评估来追踪所有光线,这为我们提供了准确的 结果,但另一方面我们无法从内联光线追踪中受益,所以它 增加了控制台的大量开销。 ● 第二种方法是首先执行通常的轻量级内联跟踪,如果我们 遇到需要材质评估的实例,我们追踪“连续”射线 启用任何命中评估。这种方法为我们提供了准确度 需要但不会失去所有光线的内联光线追踪优势。
Slide 39

📌 要点汇总
- 硬件光线追踪限制:处理茂密树叶和大量实例化网格时,AHS开销过高,BVH构建成本高。
- 虚拟阴影贴图(VSM)优势:支持柔和阴影,避免重复渲染,与光线追踪阴影兼容。
- 混合方案灵活性:艺术家可手动选择实例使用VSM或HWRT,非二元替代关系。
- VSM资源消耗问题:每盏灯需额外开销生成
仍有一些情况和内容使得使用硬件光线追踪变得简单 在当前硬件上不实用: ● 运行 AHS 的开销可能太高,特别是因为它 通常用于具有大量重叠三角形的茂密树叶。 ● 或者可能存在大量实例化的动画网格,需要大量 构建 BVH 所花费的内存和时间。
为了解决这个问题,我们还支持回退到虚拟阴影贴图,而不是 对特定灯光使用硬件光线追踪。
虚拟阴影贴图支持对我们的目的有用的功能: ● 它们能够产生合理的柔和阴影,因此它们与 来自其他光源的光线追踪阴影。 ● 在光采样过程中,我们还可以标记采样到哪些页面 避免不必要的工作将网格渲染到阴影贴图中。
这种后备方法不需要是二元选择。艺术家可以手动标记 哪些实例应渲染为阴影贴图,并依赖 HWRT 在光线追踪中得到很好体现的实例。
但是,需要注意的是,此后备选项并不解决阴影贴图问题 缩放问题。我们必须支付一次 BVH 成本(无论如何它都是必需的) 流明),但头顶上几乎没有每盏灯。有了 VSM,情况就不同了,因为现在每个 光需要额外的开销来准备每个光的阴影贴图,甚至
复杂的缓存 VSM 方案,这可以快速积累,推动整个 合理的 60hz 预算之外的技术。所以在实践中这仅用于 定向光,因为表示不匹配在那里往往更明显 扩展 BVH 以覆盖整个场景视图范围将是相当昂贵的。
Slide 40

📌 要点汇总
- 跟踪管道分层处理:屏幕跟踪优先处理自阴影,近场跟踪处理主要光线路径
- 材质评估支持光线回溯:alpha遮罩材质触发材质评估回溯机制
- 远场表示处理超范围光线:光线超出近场半径时启用远场表示回溯
- 阴影贴图采样与块压缩优化:VSM灯光采样阴影贴图,16x16块压缩保持一致性
- 多阶段压缩保障连贯性:各处理阶段间运行压缩算法提升数据一致性
将此图放在一起: ● 我们的跟踪管道的核心由屏幕跟踪组成,它们总是 首先进行追踪以避免不正确的自阴影,然后进行近场追踪, 处理大部分光线。 ● 如果光线击中使用 alpha 遮罩材质的物体,我们有 通过材质评估来回溯光线的选项。 ● 类似地,如果光线延伸超过近场半径,我们可以回溯 电平的远场表示。 ● 最后,对于使用 VSM 的灯光,我们还对阴影贴图进行采样。
我们还在每个步骤之间运行压缩以保持一致性。这个 压缩步骤每组处理 16x16 跟踪图块,以便最大化 连贯性。
Slide 41

📌 要点汇总
- 灯光性能优化需求:多数游戏灯光数量有限,但成熟引擎仍需压缩性能以处理大量灯光。
- 光计数热图应用:通过可视化配置(如8灯阈值)监控灯光使用情况,辅助优化实施。
- 复杂灯光类型挑战:艺术家广泛使用矩形光、纹理光等复杂类型,
光计数热图
大多数游戏实际上并没有附带数千个灯光,因此即使在成熟的游戏中 像 UE 这样的引擎,当我们开始时还有相当多的性能需要压缩 推动大量的灯。 例如,我们的光计数热图可视化配置为 8 个灯 默认情况下的最大阈值,显示了当时的要求 已实施。 艺术家也开始大量使用复杂的灯光类型(例如矩形光和纹理光) 更多,所以我们需要确保这些在整个引擎中得到有效处理。
Slide 42

📌 要点汇总
- 性能优化:通过改进构建逻辑,将网格构建时间从0.6毫秒缩短至0.2毫秒。
- **分阶段光
当扩展到数千个时,我们的光栅实施开始感到压力 灯光,因此我们必须改进构建逻辑以更好地处理大量灯光。
我们更新的实现如下所述,这减少了花费的时间 在 MegaLights 演示中将网格构建时间从超过 0.6 毫秒缩短到低于 0.2 毫秒。有 在过去的十年里,关于这个主题的大量研究和出版物都得到了高度评价 有效的方法,因此可能可以进一步优化。
保留现有的基于 froxel 的结构,但光注入被分成 2 个 通过。首先,我们使用每个单元 1 个线程组将灯光剔除到粗网格中,因为它是 使用单个线程循环所有灯光非常慢。然后我们使用结果 粗网格将灯光剔除到我们在渲染过程中使用的主网格中。在这个 第二遍,每个单元需要检查的灯数量显着增加 较低,因此每个单元使用一个线程通常就足够了。每个单元的完整线程组可以 导致利用率不高,所以是使用一个线程还是一个线程组来处理 可以根据灯的数量动态决定一个单元。 32条泳道的波浪 可以在支持它的平台上提供一个很好的中间群体。
我们需要打包每个单元的光列表,因为为每个网格单元分配内存 最坏的情况会导致大量内存浪费。这需要数数 每个单元的相关灯光,在缓冲区中分配空间,然后写入列表索引。 为了避免必须循环全局列表列表两次(一次用于计数和 一次用于写入),我们首先将相关的灯光列表写入LDS(溢出到 链表存储在全局内存的共享缓冲区中),在实际网格中分配空间
缓冲区,然后将 LDS + 溢出链表中的列表复制到该缓冲区中。
通常大多数光栅单元都被遮挡,HZB 剔除使我们能够极大地 减少光栅建筑开销。由于 froxel 网格的非线性特性,单元格 尺寸随着深度的增加而增加,因此那些远处的细胞通常更昂贵,因为它们 受许多灯光和线程的影响,写入所有这些可能会成为带宽限制 光指数。
Slide 43

📌 要点汇总
- 严格剔除范围:对性能优化至关重要,需精准控制剔除范围以提升效率。
- 矩形光忽视:矩形光因游戏应用较少常
没有谷仓门 带谷仓门
严格的剔除范围对于最大限度地提高性能非常重要。类似于光 网格建设,这是许多人广泛研究的事情 出版物涵盖了它的不同方面,但一种类型的光似乎是 在剔除方面经常被忽视的是矩形光(可能是因为它们没有被 到目前为止在游戏中使用较多)。我们发现通过考虑谷仓门 为了加强剔除,我们可以显着减少它们影响的细胞数量。
Slide 44

📌 要点汇总
- 套准压力:需在设计中平衡材质类型与灯光特征的处理需求
- 瓷砖分类:按材料和灯光类型划分图块,优化VGPR资源分配
- 特定着色器:针对矩形光/纹理光设计专用逻辑,降低开销
- 入住率提升:灯光类型分类使MegaLights演示入住率提高约20%
- **
套准压力和占用率也是我们在设计过程中需要考虑的问题 着色器,因为它们需要处理一堆材质类型和灯光特征。 为了解决这个问题,我们根据材料类型和类型进行瓷砖分类 影响每个图块的灯光,这样我们只需为最坏情况 VGPR 付费 在需要的地方使用。 特别是,支持矩形光和纹理光的逻辑增加了相当多的开销, 所以我们有针对这些的特定着色器排列。在 MegaLights 演示中,执行以下操作 这种基于灯光类型的额外分类将入住率提高了约 20% 开销很小,因为我们跟踪哪些类型的灯光影响每个光栅单元,而 构建光栅。
这包裹了我们的不透明管道,所以让我们继续讨论半透明和体积 雾。
Slide 45

📌 要点汇总
- 体积光照结构:UE使用froxel网格(体积雾)和世界空间网格(粒子效果)分别存储体积光照数据
- 球谐函数存储:粒子效果网格中每个体素存储2波段球谐函数以表示光照信息
- 阴影贴图依赖:传统结构依赖
世界空间体素网格 Froxel 网格
在 UE 中,我们以 2 种结构计算和存储体积光照: ● 对于体积雾,我们使用相机对齐的 froxel 网格。 ● 对于粒子效果,我们在相机周围有一个世界空间网格, 我们在其中存储每个体素的 2 波段球谐函数。
这些结构通过向其中注入灯光和阴影而在每一帧进行更新 通常使用阴影贴图来计算。然而当主要依靠射线时 追踪阴影我们没有阴影贴图,注入这么多灯光也很 昂贵,因此这些结构已升级以与新系统集成。
Slide 46

📌 要点汇总
- 体积采样方法:半分辨率采样为每个体素选择N个光样本
- 阴影追踪与照明:追踪阴影光线并用相位函数评估可见样本照明
- 可见光列表构建:为下一帧生成可见光列表以优化渲染流程
- 双阶段处理:需对每卷数据执行两次操作以确保准确性
- 半透明体积处理:结合体积雾与漫反射BRDF实现复杂光照效果
用于不透明像素的一般方法也可以应用于体积: ● 我们可以以半分辨率运行采样并为每个体素选取 N 个光样本 ● 追踪阴影光线 ● 并使用相位函数评估可见样本的照明 半透明体积的体积雾和漫反射 BRDF ● 最后我们为下一帧构建可见光列表
我们必须这样做两次,每卷一次。
Slide 47

世界网格 福罗克塞尔网格
然而,这种简单的方法存在一些问题: ● 首先,探测器相当稀疏,特别是对于世界空间网格来说,所以 从附近体素收集可见性会导致在具有以下特征的区域中进行无效引导 高频阴影 ● 其次,两卷之间有很多重复的工作○ 我们正在挑选重要的灯光并从一堆光线中追踪阴影光线 世界上的探测器数量 ○ 但正如您在这些屏幕截图中看到的,探测器的覆盖范围 这两卷有很大重叠。
Slide 48

📌 要点汇总
- 扩展froxel网格:用于存储SH以计算光照,避免重复工作并提升半透明物体渲染效率
- 视觉伪影问题:相机移动时froxel网格结构明显,影响视觉效果
- 时间过滤缺陷:重投影导致无法完全避免的错误,需额外处理
- 世界空间网格对比:虽存在类似问题但更稳定,因不依赖相机位置
一种想法是简单地扩展 froxel 网格结构来存储 SH 并使用它来 计算粒子效果和半透明物体的光照。这似乎是一个 避免两卷之间重复工作并改进指导的有效方法 由于 froxels 更密集,因此对半透明度的影响更大。然而,在实践中这 导致一些明显的视觉伪影: ● 首先,froxel 网格的底层结构非常引人注目, 特别是当相机移动时。 ○ 世界空间网格也可能发生此类问题,但至少它是 稳定,因为它不依赖于相机,所以不会分散注意力。 ● 我们还需要使用时间过滤,但重投影会引起明显的影响 我们无法完全避免的错误。
Slide 49

另一种选择是使用混合解决方案,其中仅共享采样和跟踪 两卷之间。 我们根据 froxel 位置运行探针的采样逻辑,因为它们更密集, 这意味着我们可以在邻居探测器之间共享可见性数据而不会造成伤害 指导有效性。 然后跟踪这些样本的光线,最后运行 2 个着色通道,每个通道一个 卷,其中每个卷随机收集最近采样的样本 探针。
这种方法节省了大约 25% 的构建卷时间,因为我们 不需要运行两次采样和跟踪。
Slide 50

📌 要点汇总
- 不透明表面优势:利用法线与材料属性提升采样效率,减少像素样本数量
- 半透明采样挑战:需更多样本应对未知表面着色需求与光线分布不均问题
- 冷冻像素影响:大尺寸像素导致随机上采样不稳定,需更广泛过滤处理
- 相位函数作用:半透明BRDF优化光线分布,降低采样复杂度
- **样本数量
早些时候,在讨论不透明管道时,我们提到了这样的假设: 通常 80% 的能量来自一束光。 对于不透明表面,我们可以访问法线和材料属性 用于采样过程中的着色,这样我们就可以避免每个像素的样本数量很少, 选择半透明体积的样本更具挑战性。
首先,我们将光注入球谐函数,并且不知道哪个 表面将提前使用每个体素进行着色。 冷冻像素相对于像素大小相当大,因此随机上采样 相邻体素可能会导致不稳定或需要更广泛的过滤。 由于采样是在统一的体积中完成的,因此我们考虑了相位函数 半透明的 BRDF 使得轻量更加均匀。
这些因素的结合意味着我们最终必须对更多样本进行着色 每个体素的数量比不透明表面通常所需的数量多。
Slide 51

📌 要点汇总
- 增加样本数量:提升采样精度但显著增加计算成本,影响整体效率。
- 扩展随机上采样:通过聚合多邻居样本减少开销,但可能模糊照明细节。
- 时空滤波应用:结合时间与空间滤波技术,优化可见性稳定性与细节保留。
- 采样/可见度探头 - 采样/可见度探头 - 遮光探头
一种简单的方法是增加每个体素的样本数量,但是这 使得管道的所有阶段都更加昂贵。
或者,我们可以扩展我们在着色过程中已经进行的随机上采样, 但我们可以收集并着色,而不是对单个邻居的样本进行着色 来自多个邻居的样本。这避免了额外的采样和跟踪开销, 但也会导致一些照明细节的损失,因为它最终会模糊可见性 术语。
最后,我们还应用时间和空间滤波来进一步提高稳定性 卷。
Slide 52

SH 光近似
某些半透明物体(例如玻璃)需要更高质量的照明(包括镜面反射)。
一个简单的方法是认为前层是最重要的并对其进行遮蔽 再次运行整个 MegaLights 管道,以便获得准确的照明。然而 这在实践中通常太昂贵,因为我们很容易最终将成本加倍 如果玩家靠近这些表面,则照明的总成本。
但我们还需要支持多层着色,因此我们需要在一个 更具可扩展性的方式。一种廉价的选择是使用半透明来照亮这些表面 体积。我们可以使用已有的球谐函数,并提取 近似镜面照明的主导方向。这可以在简单的情况下很好地工作 情况下,但正如您在屏幕截图中看到的,它只能支持一种镜面反射 高光,并且要求SH中的光照稳定,否则镜面反射会 即使灯光是静态的,也会出现明显的抖动。
目前我们正在使用这种方法,但这是一个正在进行的工作领域,因为我们想要 以支持此类半透明表面上更好的照明质量。
Slide 53

📌 要点汇总
- 薄表面处理:优化树叶照明效果,提升传输质量
- 背面追踪调整:禁用屏幕空间跟踪,调整光线偏移方向避免
我们还处理传输,但目前仅适用于薄表面,这极大地 改善树叶照明。
传输有时需要从网格的背面进行追踪,我们 在这种情况下必须进行一些调整。我们禁用屏幕空间跟踪,如下所示 那些无法追踪几何图形的背后。我们还需要稍微改变一下我们的偏见和偏见 向着光。这样光线就可以跳过树叶几何体的后面,而不是 立即与其自相交。
从树叶背面到射线击中点的距离给出了距离 估计,然后可以将其插入到我们的传输项中。
Slide 54

📌 要点汇总
- 运行环境:Play
现在让我们看看这一切在运行时性能方面是如何结合在一起的。
这些数字来自在 PlayStation 5 上以 1080p 运行的 MegaLights 演示 渲染分辨率,每像素 1 个样本,并且禁用异步计算。 屏幕上有超过 900 个灯光,这导致每个像素大约有 20 到 80 个灯光。
总成本约为 5.5ms,涵盖所有阴影和直接着色成本 照明。
Slide 55

值得注意的一件有趣的事情是,对不透明表面进行采样需要更多时间 尽管以一半分辨率运行,但比着色效果更好。 这是因为采样成本与灯的数量成正比,而灯的数量非常高。 这个场景,很多灯光都是矩形灯光,采样和采样成本很高 压低入住率。 另一方面,着色具有更固定的成本,因为它有一个硬上限 每个像素有多少个样本着色,使其相对稳定,因为成本为 仅受瓷砖类型影响。
Slide 56

另一件需要注意的事情是半透明着色几乎和 不透明,尽管探针数量明显少于像素上的数量 屏幕。 这是因为,正如我们之前讨论的,半透明需要我们遮蔽更多 每个体素的样本,以提高稳定性并减少噪声。
Slide 57

📌 要点汇总
- 艺术家体验提升:使用MegaLights后,艺术家迅速感受到创作乐趣和参与感。
- 心态转变与进展:进入新心态后,艺术家在演示中逐步实现灯光布局的突破性进展。
- 灯光应用扩展:初期灯光布置零散,后期逐渐形成关卡中密集且协调的灯光效果。
总的来说,一旦艺术家开始使用 MegaLights,很快就会清楚有多少 他们玩得很开心。
当他们进入新的心态时,看到进展真的很有趣 致力于 MegaLights 演示。他们慢慢地开始,到处放灯, 但这种情况很快就发生了变化,我们开始在关卡中看到更多的灯光。
Slide 58

然后,正如您在此屏幕截图中看到的,我们也开始看到矩形灯的使用 加速。
Slide 59

📌 要点汇总
- 阴影丢失原因:剔除灯具导致阴影丢失,艺术家使用网格塑造光线增加采样难度
- 光函数建议:理想方案为光函数塑造光形,结合射线端偏置跳过夹具几何
- 手动标记方案:实际采用网格固定装置,要求艺术家手动标记BVH避免错误剔除
- 自动剔除问题:自动剔除远处灯具引发光线泄漏与整体照明显著变化
由于从光线追踪中剔除灯具而导致阴影丢失
我们开始发现很多内容,艺术家使用网格来塑造光线, 这使得正确采样和解析这些灯光变得非常困难。
理想情况下,应该使用光函数来塑造光的形状(可以廉价地评估 在采样过程中)并且使用射线端偏置跳过夹具几何形状 每个灯指定。
在实践中,这并不是什么大问题,所以我们用这些网格来发送我们的演示 为基础的固定装置。我们只需要要求艺术家在 BVH 中手动标记他们,这样我们 最终不会自动剔除远处的那些,这会导致光线 泄漏并显着改变整体照明。
Slide 60

📌 要点汇总
- 程序光生成器:艺术家常用工具,用于创建复杂灯光效果
- 样条线自动布光:沿样条线路径智能分布灯光,提升布光效率
- 工具提升效率:自动化功能减少手动调整,优化创作流程
在某些时候,艺术家使用诸如程序光生成器之类的工具变得非常舒服 沿着样条线自动放置灯光。
Slide 61

📌 要点汇总
- 系统扩展性:系统扩展性提升,更宽容地处理复杂光源配置。
- 光源设计优化:采用多光源组合替代单一IES配置文件,适应随机纹理需求。
- 采样性能限制:随机光采样可能降低性能或增加噪声,需通过衰减范围等参数优化。
整个系统的扩展性更好,也更宽容,通常会达到这样的程度: 我们发现墙壁内有随机纹理的区域灯或由多个灯制成的灯 光源,而不是使用具有 IES 配置文件的一盏灯。
随机光采样仍然不是灵丹妙药,光源也会减少 采样传递性能或增加场景中的噪音,以及内容优化 例如减小衰减范围,锥角或谷仓门都是相关的。
Slide 62

📌 要点汇总
- 新方法应用:光线追踪新方法解决控制台等资源受限平台的直接照明问题
- 质量限制:网格表示效果、单像素采样限制及去噪需求影响最终质量
- 性能权衡:灯光数量与场景复杂性直接影响性能,但灵活性优于传统手动调节
- 混合技术方案:结合BVH与VSM处理定向光阴影,平衡性能与质量
总结一下:
光线追踪可以采用新方法来解决直接照明问题,甚至更多 资源受限的平台,如控制台。
当然,仍然存在质量限制,例如: ● 光线追踪中网格的表示效果如何 ● 在大多数情况下,我们仅限于每个像素 1 个样本,因此请小心采样 和去噪至关重要。
该技术的性能与每个像素采样的灯光数量成正比 和光线追踪场景的复杂性。
我们这里有可怕的限制,显然灯数仍然有限,但总的来说 实践证明这是一个非常好的权衡。艺术家可以更多地放置灯光 在系统崩溃之前自由。此外,随机方法擅长 能够在性能和质量之间自由调整,这给了我们更大的灵活性 无需采用劳动密集型的手动灯光调节或维护 针对不同可扩展级别的多种灯光设置。
虽然 BVH 的限制令人恐惧,但实际上艺术家喜欢放置区域光,这 通常只需要接触点附近有详细的阴影投射器。这第一 屏幕空间轨迹很好地处理了光线的一部分,使其成为 局部灯光的合理解决方案。定向光可能具有挑战性,因为它可能
需要在大绘制距离处出现锐利的阴影,这对于 BVH。在这种情况下,我们可以回退到 VSM。要么完全依赖 VSM,要么 使用结合了光线追踪和 VSM 追踪的混合方法。
时间伪像在快速运动期间可能是一个问题,因为所有随机光 抽样方法依赖于能够积累和重复使用多个数据 帧。对于小灯数和小光源来说,这些并不是一个突出的问题 大小,因为通常我们可以只对每个像素采样一个最重要的光,并得到几乎 瞬时响应。具有大光源或每个像素有大量重要灯光 事情确实会有些崩溃,因为现在我们必须依赖多个 数据帧,但我们没有。大多数游戏似乎仍在实践中 如果工作得足够好,时间伪影通常会被降噪器隐藏。 在我们负担得起的高端 GPU 上,这些问题也不那么成问题 每个像素追踪更多光线。
Slide 63

📌 要点汇总
- BRDF与显式采样结合:混合采样策略优化大灯与反射BRDF,复用BRDF射线提升直接照明
就未来的工作而言,我们仍在努力制作MegaLights 准备好了。我们仍然需要大量的优化、修复和缺失的功能 来改进和实施。
例如,我们希望将 BRDF 采样与显式采样混合。显式的 采样非常适合对较小或距表面较远的灯光进行采样。 BRDF 采样非常适合大灯和反射 BRDF。我们已经有了我们的 BRDF 射线(流明迹线),因此我们可以廉价地重复使用这些射线,以改善直接 照明质量。
我们正在努力改进,以更好地支持前向着色,使用 GPU 驱动反馈机制,根据渲染的前向驱动样本引导 阴影表面。我们还收集使用此功能的被许可人的反馈 生产技术,这将使我们能够准备有用的调试工具 并优化 MegaLights。
低端(移动)的可扩展性仍然是一个悬而未决的问题。一些游戏想要发货 他们的内容涵盖非常广泛的硬件 - 从廉价手机到 高端 PC GPU。一旦使用 MegaLights 创作内容,它就会变成 在不需要灯光艺术家做大量工作的情况下减少灯光数量具有挑战性,并且 我们不想最终陷入艺术家必须维护多个照明的情况 手动设置。
另一个重要领域是去噪和上采样。目前 MegaLights 正在运行
它自己进行降噪,然后输出最终由 TSR 进一步处理, 这导致了各种挑战。我们想研究制作这两个 更加统一。通过从内部降噪器传递一些额外信息或 将所有降噪移至 TSR。当然有大量使用机器学习的新研究 在这一领域显示出非常有希望的成果。
Slide 64

📌 要点汇总
- 网格表示挑战:硬件光线追踪中,网格优化问题因阴影暴露底层结构而难以解决。
- 动态几何瓶颈:大量动画实例导致内存与性能预算崩溃,无法准确表示复杂动态几何。
- 巨大网格性能问题:空洞结构(如洞穴)在光线追踪中引发性能瓶颈,BVH重编成本高且内存消耗大。
- Nanite优化限制
未来的主要挑战是硬件光线追踪中的网格表示。
虽然到目前为止我们(在某种程度上)已经能够摆脱低多边形代理和 其他捷径,因为漫反射 GI 和粗糙反射是相当宽容的。阴影为 直接照明可以轻松暴露网格的底层光线追踪表示。
动态几何仍然是一个未解决的问题,而且很容易崩溃 内存和性能预算,使得目前无法准确 代表大量的动画实例。
大量的 kitbashing 或巨大的网格,内部有很多空白区域(例如 天空盒网格或从单个网格建模的洞穴)可能会导致光线追踪 即使在高端 PC GPU 上也会出现性能问题。理论上这可能是 通过 BVH 重新编织来解决,但重新编织是一项成本相当高的操作,并且需要 更多的内存,这并不理想,因为 BVH 构建时间已经很具有挑战性并且 BVH表示本身有很大的内存开销。
使用 Nanite(我们的虚拟几何管道),我们能够隐藏大部分网格 光栅化的优化问题,但光线追踪约束将这些问题带回来 要求艺术家仔细优化他们的 BVH 表现。
虽然我们开始看到光线追踪 API 的新扩展,这将使更多 Nanite 网格的有效表示,几何复杂性不断增长。 有些新类型的内容在 ray 中呈现更具挑战性
追踪,在我们能够依赖纯光线之前需要解决这个问题 追踪阴影。
Slide 65

📌 要点汇总
- (无内容):此幻灯片无演讲内容
Slide 66

📌 要点汇总
- (无内容):此幻灯片无演讲内容
Slide 67

📌 要点汇总
- (无内容):此幻灯片无演讲内容
Slide 68

📌 要点汇总
- (无内容):此幻灯片无演讲内容
SIGGRAPH 2025 游戏实时渲染的进展课程