Cook 1986 — 用噪声换掉锯齿
是什么
Cook 1986 提出:渲染图像时故意把规则的采样位置打乱,让本来会出现的”锯齿/摩尔纹”变成肉眼看不太见的”颗粒噪点”。
日常类比:拍格栅栏。
- 如果你等距地一格一格按下快门,照片上会出现奇怪的条纹(摩尔纹)——这就是 aliasing
- 如果你抖一下相机再拍,得到的是轻微毛刺——这是 noise
- 人眼对毛刺很宽容,对条纹特别敏感
stochastic sampling 就是把第一种错误(眼睛敏感)转成第二种错误(眼睛宽容)。
为什么重要
不理解 stochastic sampling,下面这些事都没法解释:
- 为什么 Pixar 的 RenderMan 在 1986 年就能渲出没有锯齿、有自然运动模糊的电影画面
- 为什么离线渲染至今还在用 jittered / Poisson disk 这两个 1986 年的采样模式
- 为什么 Monte Carlo path tracing 一定要”随机”——不是为了”模拟物理”,是为了”骗过眼睛”
- 为什么游戏引擎做 TAA 也要把每帧采样位置抖一下
核心要点
Cook 论文的核心可以拆成 三层:
-
诊断:规则采样(每像素中心一个样本)会把高频信号”折叠”成低频假信号——这就是 aliasing。数学上叫 Nyquist 极限:采样频率 < 信号频率两倍时必出错。
-
关键洞察:信号本身没法降低频率(场景就是那么细),但错误的样子可以换。把”等距采样”换成”非均匀采样”,能量从”几个高峰”散成”宽频底噪”。
-
两种实现:
- Poisson disk:随机撒点,但任意两点间距离 ≥ r。模仿视网膜光感受器排布(Yellott 1982/83)。质量好,但生成慢。
- Jittered:把像素切成 N×N 子格,每子格随机放一个样本。质量略差于 Poisson disk,但几乎免费。Pixar 用的就是这个。
实践案例
案例 1:抗锯齿对比(最直观)
一张高频条纹纹理,正前方拍:
- 规则采样:屏幕上出现完全不存在的粗条纹(aliasing)
- jittered 采样:高频部分变成沙粒状颗粒,主体清晰
人眼几乎察觉不到颗粒,但条纹一眼就看见。Cook 用这个对比一锤定音。
案例 2:运动模糊(多维抖动的威力)
电影里飞过的子弹应该有拖影。传统做法是渲多帧再叠加——慢且依然有锯齿。
Cook 的做法:
- 给每个样本分配一个时间值 t ∈ [0, 1](在快门打开期间随机)
- 渲染那一时刻的场景
- 同一像素内多个样本对应的是不同时刻的子弹位置
聚合后自然得到拖影,没有任何额外帧。
景深、软阴影、glossy 反射全是同一招——把”不知道怎么积分的维度”丢给随机采样。
案例 3:游戏 TAA(同思想,跨 30 年)
UE4 的 Temporal AA:每帧把样本位置在像素内抖一个 sub-pixel 偏移(jittered 序列),跨帧累加。
第 1 帧:样本在 (0.25, 0.25)第 2 帧:样本在 (0.75, 0.25)第 3 帧:样本在 (0.25, 0.75)第 4 帧:样本在 (0.75, 0.75)四帧合起来等价于每像素 4× 超采样。这就是 Cook 1986 的思路在实时图形里的复用。
案例 4:景深为什么”自然”
胶片相机的景深来自光线经过透镜不同位置时走的路径不同。要在渲染里复刻:
- 把透镜看成一个圆盘
- 每个样本随机选透镜上一个点(jittered 在 2D 圆盘上)
- 从那个点出发追光线
聚焦平面上的物体,所有光线都会汇到同一像素,清晰;不在焦面的物体,每条光线打到不同像素,散开变模糊。
这就是物理上发生的事,stochastic sampling 只是把它忠实地采样了一遍。
踩过的坑
-
“随机”不等于”乱”:纯均匀随机(白噪声)会出现簇——某些区域样本扎堆、另一些区域空白。Poisson disk 加最小距离约束才得到”看起来均匀”的噪声(蓝噪声)。
-
维度爆炸的暗坑:运动模糊把样本撒到 (x, y, t) 三维空间。如果三维都”独立”地 jitter,t 维上仍可能出现条带。Cook 后来提出 N-rooks / Latin hypercube——保证每条投影都覆盖均匀。
-
样本数从哪儿来:要让 noise 真的低于人眼阈值,每像素 ≥ 16 样本才稳。早年算力贵,每样本一条光线,电影一帧要算几小时。
-
不是越随机越好:纯 Poisson 比 jittered 慢一个数量级,工程上够用就好。绝大多数离线渲染器选了 jittered + 后处理 denoise。
-
白噪声 vs 蓝噪声常被混淆:白噪声是”频谱平坦”,蓝噪声是”低频少、高频多”。眼睛对低频更敏感,所以蓝噪声”看起来更均匀”。Poisson disk 自然产生的就是蓝噪声谱。
-
跨像素相关性破坏一致性:如果整张图共用同一个随机种子序列,会出现跨像素的”周期感”。每像素独立种子才稳。
适用 vs 不适用场景
适用:
- 离线渲染(电影 / VFX)的抗锯齿、运动模糊、景深、软阴影
- Monte Carlo path tracing 的所有积分(半球方向、面光源、BSDF)
- 实时引擎的 TAA / SSAO / 体积光采样
不适用:
- 极少样本场景(每像素 1 样本)→ 噪声过强,反而看起来脏
- 需要可重复确定性的场合(比如某些科学可视化)→ 改用低差异序列(Halton / Sobol)
- 1D 信号采样(如音频)→ 直接抗锯齿滤波即可,不需要 stochastic
历史小故事(可跳过)
- 1982 年:Yellott 研究猴子视网膜,发现光感受器不是规则排列,是 Poisson disk 模式。猜想这就是为什么人眼”不发生 aliasing”。
- 1984 年:Cook 发表 distributed ray tracing,第一次把”光线随机分布”用于渲染——但没系统讲为什么。
- 1986 年:Cook 这篇论文把 1984 的工程做法讲透了它的理论根——是采样理论 + 视觉感知,不是物理模拟。同年 Kajiya 发表渲染方程,两篇论文加起来定义了之后 30 年的离线渲染。
- 1990s:Pixar REYES / RenderMan 全面采用 jittered sampling。《玩具总动员》《虫虫危机》背后都是这套。
学到什么
- 错误的形态可以选——这是 Cook 1986 最深的一句话。aliasing 不是”对错”问题,是”哪种错眼睛能忍”
- 采样问题的本质是积分问题——要算的是像素覆盖的连续区域的平均,不是某个点
- 生物启发的工程优化:视网膜的随机排布给了 Poisson disk 灵感;生物已经解了这道题几亿年
- 理论 + 工程同步发表才有杀伤力:Cook 1984(工程)+ Cook 1986(理论)+ Kajiya 1986(理论)三篇定义了离线渲染
- 跨维度复用:同一招(抖一下采样位置)解决了抗锯齿、运动模糊、景深、软阴影、glossy 反射五件事——每一件单独研究都是一篇论文
- 工程取舍清单:质量从高到低是 Poisson disk > N-rooks > jittered > 白噪声 > 规则;速度反过来。Pixar 选 jittered 就是这条曲线的最佳工程点
延伸阅读
- 论文 PDF:Cook 1986 — Stochastic Sampling(10 页,可读性极高,配图清晰)
- 视频教程:TU Wien — Rendering Course Lecture on Sampling(学院派把 Nyquist 到 stochastic 一气讲完)
- 工程实战:PBRT 第 8 章 Sampling and Reconstruction(开源 PBR 教材,含可跑代码)
- cook-1984-distributed-ray-tracing —— 同作者前作,工程做法的源头
- kajiya-1986-rendering-equation —— 同年另一篇奠基论文,给出 stochastic 采样要算的那个积分
关联
- cook-1984-distributed-ray-tracing —— Cook 自己 2 年前提出的工程原型,本论文是它的理论说明书
- kajiya-1986-rendering-equation —— 渲染方程定义”要积什么”,stochastic sampling 给”怎么积”
- perlin-1985-noise —— 同时期的另一种”用噪声”思想,但 Perlin 是构造噪声当纹理,Cook 是用噪声当采样误差
- karis-2014-taa —— 30 年后实时图形里 stochastic sampling 思想的复用
- cook-torrance-1982 —— Cook 自己更早的微表面 BRDF 论文,三篇加起来构成离线渲染的 Cook 三联
反向链接
- cook-1984-distributed-ray-tracing —— Distributed Ray Tracing — 把所有”模糊”效果统一成随机采样
- cook-torrance-1982 —— Cook-Torrance 1982 — 把镜面反射拆成微面元 × 几何遮挡 × Fresnel
- dropout-2014 —— Dropout — 训练时随机关掉一半神经元,反而学得更好
- kajiya-1986-rendering-equation —— Kajiya 渲染方程 — 把所有渲染算法统一成一个积分方程
- perlin-1985-noise —— Perlin Noise — 让计算机生成的图像不再有”机器味”