# 光追噪点与降噪的取舍：颗粒、拖影、糊掉细节是怎么来的

从蒙特卡洛采样为什么必然有噪声讲起，看清空间滤波与时间累积在补什么，以及拖影、细节丢失、慢半拍这三种代价

> 降噪 · 实时光线追踪 · 渲染原理 · 路径追踪 · 约 5 分钟 · 10 月 17 日

## 本篇要点

1. 像素要的是一个点在所有方向上的平均光照，光线追踪只能随机抽几条方向来估计这个平均值，样本少就估不准，偏差表现为画面上的一层颗粒。
2. 估计误差大致按 $1/\sqrt{N}$ 下降，要多干净就得成平方地加光线，所以实时渲染不可能靠增加采样消掉噪声，只能靠降噪重建。
3. 噪声大小取决于被估分布有多“尖”：面向大光源的直接光很干净，多次弹射的间接光和小而亮的区域会频繁出现“多数样本是 0、偶尔样本极大”的情况，这就是颗粒和火萤的来源。
4. 降噪器不推测画面内容，它的全部本钱是用空间冗余（邻域滤波）和时间冗余（用运动矢量取回上一帧并按比例混合，历史常占 80%–90%）替代没发出来的光线，把每像素 1 条的等效样本数抬到几十条。
5. 降噪出错有三类：阴影和反射不跟随接收面的运动矢量，导致拖影；方差无法区分“噪声”和“真实细节”，导致高频细节被一起抹掉；历史占比高导致画面慢半拍。
6. 邻域钳制可以压拖影，但钳得越狠越会丢掉有效历史、让噪声和闪烁回来，因此稳定与鬼影在实践上是一对必须取舍的目标。
7. 降噪后的图像是有偏估计，它用偏差换方差；这正是降噪器需要按场景手调的原因。

---

上一篇讲到，效果类查询可以每像素只发 1/4 条光线，再靠时空滤波重建回全屏。这就带出一个开光追的玩家都见过的现象：静止看水面还好，一转视角，粗糙反射和间接光那里就浮出一层颗粒；快速转身时，物体边缘还会拖出一条半透明的尾巴。这篇回答：这些颗粒是什么，降噪器凭什么把它抹掉，代价又是什么。

## 噪点的根源：一个像素要的是一个平均值

先纠正一个很自然的误解：像素的颜色不是“某一条光线的颜色”。真实世界里，一个点的亮度来自四面八方射过来的光的总和。渲染器要算的正是这个“所有方向的平均”，而方向有无限多个，算不完。所以路径追踪用**蒙特卡洛采样**：随机挑几个方向发光线，用这少数几个样本的平均值代表整体平均。

每帧每像素只发 1 条光线，就是拿 1 个随机样本来猜这个平均值。猜得准不准是随机的，猜出来的偏差就是画面上那层颗粒。

关键在于偏差下降得很慢，大致按 $1/\sqrt{N}$ 走（$N$ 是样本数）：从 1 spp 提到 4 spp，误差只减一半；想让误差降到十分之一，需要 100 倍光线。正是这条平方根曲线，让“再多采样一点”从解法变成了不可能——实时预算就那几条光线，缺口只能靠降噪补 [1]。

## 同样是 1 spp，为什么有的地方干净、有的地方满屏颗粒

噪声大小取决于要估的那个分布有多“尖”。

面向一大片光源只算直接光时，几乎朝哪边扔都能碰到灯，样本彼此差别不大，平均一下就准，所以亮面和阴影内部往往很干净。

而间接光要弹几次才落到光源上，光源在场景里常常只是一个小而亮的区域。随机扔出去的光线绝大多数碰不到它，偶尔碰到的那一次带回极大的一笔。同一个像素，这一帧拿到 0，下一帧拿到 10——忽明忽暗，看起来就像画面在“沸腾”（boiling）。极端的版本叫 fireflies（火萤）：少数样本贡献极大，画面上冒出孤立的亮点 [5]。

要记住的是：噪点不是“画错了”，而是“估计得不够准”。

## 降噪器补的是什么：拿邻居和过去当额外样本

降噪器不在“推测画面里应该有什么”，它做的是用空间和时间上的冗余，去换那些没发出来的光线。

**空间滤波**：一个像素的邻居看的是同一块表面上附近的一点，光照理应差不多。把邻域的值加权平均，等于帮这个像素凑出更多样本。

**时间累积**：用**运动矢量**（motion vector）把当前像素投影回上一帧，找到它当时在屏幕上的位置，再把历史值和新帧按比例混合。新帧的权重常取 0.1–0.2，也就是 80%–90% 的颜色来自历史 [2]；静止不动时，几十帧累积下来，等效样本数能从每像素 1 条涨到几十条。

SVGF 就是这套做法的范例：输入是每像素一条路径，先用时间累积提高有效采样数，再估计每个像素的亮度方差，用方差决定哪里该多滤、哪里该少动，最后走一遍小波滤波，2017 年的硬件上跑 1080p 约 10 ms [1]。

它的全部本钱是“同一块表面在空间上大片相连、在时间上前后相似”。前提成立就能补；前提破了就会补错。

## 它会补错什么

**拖影（ghosting）。** 运动矢量描述的是几何的运动，但阴影和反射不跟着接收面走。影子从地面滑过时，地面的运动矢量长度是零，可“正确的历史”本该跟着影子移动；照着运动矢量去取历史，取到的是几帧前同一块地面的颜色，于是影子后面拖出一条浅色尾巴，而且这条尾巴和地面一样静止，用常规的遮挡检测抓不到 [2]。同一篇工作还给出两个同类失效：反射里的虚像在动而反射面不动；原本被前景挡住的背景露出来时，历史里那块记的是遮挡物的颜色。

**糊掉细节（overblur）。** 判断该滤多少靠方差：噪声会推高方差，方差大的地方就多滤。但反过来不成立——方差大不一定是噪声，也可能这里真有细节。在 1 spp 的输入下，渲染器分不清“这个像素亮是因为采样噪声，还是因为它本来就亮”，纹理的高频细节就和噪声一起被抹平。SVGF 的论文自己说，空间上算出的方差只是噪声的不完美代理：噪声会增加方差，但有方差不一定有噪声 [1]。NVIDIA 也提到，手工降噪器混得过多会丢掉高频信息，后面超分时没东西可用 [4]。

**慢半拍（lag）。** 历史占比越高越干净，也越“重”。镜头一转、光源一变，画面还拖着几帧前的信息。

对付拖影的标准做法叫**邻域钳制**：把从历史取回的颜色限制在当前帧邻域颜色的取值范围里，偏离太远就作废。但它只是把问题换了个形状——钳制越强，鬼影越少，可有效历史丢得越多，噪声和闪烁就回来；钳制越弱，画面稳，鬼影就出来。SIGGRAPH Asia 2024 那篇改进钳制方法的论文给出了实验结论：最不闪的版本鬼影最多，最不鬼影的版本最闪 [3]。

另外要说明的是，降噪后是**有偏**的：蒙特卡洛本身是对的，只是不准；滤波用偏差换方差，结果更接近真实光照，但不再是无偏估计 [1]。所以降噪器必须按场景手调，开发者实际上在选择“我愿意接受哪一种错”。

## 看到症状，判断原因

- 站着不动，颗粒还在轻轻沸腾：采样不够，降噪压不住。间接光和粗糙反射最容易出现。
- 快速移动时，物体边缘或阴影后拖出半透明尾巴：历史复用失败，ghosting。
- 转动视角时阴影或反射慢半拍：时间迟滞。
- 整体发糊、远处纹理发软、反光像被抹过：空间滤波过度。

这四种症状在同一档光追设置里此消彼长。理解了这个权衡，就能解释一件常被当成“优化差”的事：为什么同一个光追档位，在不同游戏、不同场景里的观感差别会那么大——它们只是在同一根滑杆上落在了不同的位置。

## 术语表

- 蒙特卡洛采样：算不出“所有方向的平均”时，随机抽几个方向取平均来近似，结果对但每次都有随机误差。
- 有效样本数：时间累积把多帧的 1 spp 结果堆起来，等效于提高每像素的样本数，但不增加本帧成本。
- 运动矢量（motion vector）：记录每个像素从上一帧到这一帧在屏幕上的位移，降噪器靠它找到历史颜色的对应位置。
- 邻域钳制（clipping/clamping）：把取回的历史颜色限制在当前帧邻域的颜色范围内，超出就丢弃，用来压拖影。
- ghosting（拖影）：历史复用取了错误对应位置的颜色，画面上留下移动物体或阴影的残影。
- fireflies（火萤）：单个样本贡献极大而概率极小，导致画面上出现孤立的亮点。
- 方差作为噪声代理：用邻域亮度方差估计“这里有多少噪声”，但方差大也可能是真实细节，故只是不完美的代理。
- 偏差换方差：滤波让图像更干净，代价是不再是严格无偏的估计。

## 来源

1. [SVGF 论文：1 spp 输入、时间累积提高有效采样数、时空方差引导小波滤波，约 10 ms @1080p；明确指出空间方差只是噪声的不完美代理，降噪以引入偏差为代价](https://cwyman.org/papers/hpg17_svgf.pdf)
2. [Temporally Reliable Motion Vectors for Real-time Ray Tracing — 运动矢量在阴影、粗糙反射、遮挡三种情况下的失效；时间混合中新帧权重常取 0.1–0.2](https://sites.cs.ucsb.edu/~lingqi/publications/paper_trmv.pdf)
3. [k-DOP Clipping: Robust Ghosting Mitigation in Temporal Antialiasing（SIGGRAPH Asia 2024）— 邻域钳制方法比较，给出时间稳定与鬼影最小两个目标互相矛盾的实验结果](https://dl.acm.org/doi/full/10.1145/3681758.3697996)
4. [NVIDIA DLSS 3.5 Ray Reconstruction — 手工降噪器的过度混合问题：混得太多会丢掉高频信息，削弱后续超分可用的细节](https://www.nvidia.com/en-us/geforce/news/nvidia-dlss-3-5-ray-reconstruction/)
5. [Blender Cycles 文档：减少噪点 — 火萤的典型来源：焦散路径与极小极亮的高光，概率低因而偶尔才被采样到](https://docs.blender.org/manual/en/4.5/render/cycles/optimizations/reducing_noise.html)

---

原文：https://pangzhengboyin.com/articles/why-ray-tracing-noise-needs-denoising-7e025603

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
