Path Tracing in Full: Three Materials & Convergence
路径追踪慢,不是写法烂,是计算量本来就大。把这笔账精确化:
| 量 | 数值 |
|---|---|
| 分辨率 | 像素(约 80 万) |
| 每像素采样 | 条路径 |
| 每条路径平均弹射 | 次 |
| 总射线数 |
约 60 亿次射线-场景求交,这就是一张干净画面的代价。注意每”弹射一次”都要重新做一次最近交点查询,所以路径长度直接乘进总射线数。
渲染方程的积分用蒙特卡洛估计,估计量的标准差按
衰减,其中 是采样数、 是单次样本的标准差。把噪声降到一半需要把 翻 4 倍——这就是旁白里”采样翻四倍,噪声才减半”的数学根源。它和像素数无关,是蒙特卡洛方法的内在规律,适用于任何蒙特卡洛积分。
代价换算:要把噪声再降一半,渲染时间要 ×4。所以”干净”是指数级烧出来的:
| 目标噪声(相对) | 需要的采样数 | 相对时间 |
|---|---|---|
这是为什么电影一帧能渲染几小时:他们要的噪声水平远低于 1%。
俄罗斯轮盘赌保证了无偏估计(期望值正确),代价是方差大、收敛慢。有偏方法(比如限死最大弹射次数、加环境光近似)能更快出干净图,但物理上不正确。smallpt 选择无偏,所以慢得”理直气壮”。
smallpt 全场景只有 9 个球,没有别的几何类型。这不是图省事,是为了让求交代码只写一遍:所有几何体走同一条射线-球求交路径,99 行才装得下。代价是”墙”也得用球凑。
球面是弯的,墙是平的。当半径大到 量级,球面上的一小段弧——相对半径只占千分之几——曲率趋近 0,肉眼就是平面。左墙球心在 、半径 ,球面最靠近房间的点是
于是这个巨型球从外面”顶住”了 这面墙。其余五面墙同理,方向相反的球顶住各自平面。房间宽约 98,相对半径仅约 ,曲率可忽略。
| 角色 | 半径 | 数量 | 作用 |
|---|---|---|---|
| 六面墙 | 6 | 从外侧顶住房间各面(左红右蓝余白) | |
| 镜面球 | 1 | 镜面反射 | |
| 玻璃球 | 1 | 折射 | |
| 光源 | — | 1 | 自发光 |
合计 9 个球。前墙颜色设为黑(不发光不反光),等于这面”不存在”,房间开口朝相机才看得见里面。
没有加速结构,每条射线对 9 个球逐个求解、保留最近命中。对单个球,求交是射线方程 代入球面方程 ,得到关于 的一元二次方程:
方向 归一化后 ,判别式决定命中与否: 未命中, 取较小的正根作为最近交点。9 个球各算一遍取最小 ,没有命中返回 0。
只有 9 个球,单条射线 9 次求交耗时极短,暴力遍历就是最优解,加速结构(BVH、kd-tree)的构建开销反而更高。这是场景规模决定的,不是偷懒。换到上百万三角形的真实场景,才必须用层次包围盒把绝大多数几何提前剪掉。
两者都属于光线追踪大类(从相机发射射线、与场景求交),但设计目标完全相反:Raymarching 追求实时(毫秒级),路径追踪追求物理正确(分钟到小时级)。下面逐项拆开差异的技术根源。
Raymarching 跑在 GPU 片元着色器里,每个像素一条射线、上千个像素并行,16 ms 内画完一帧、可实时交互。路径追踪在 CPU 上单线程离线跑,一张图几分钟到几小时。差异来自并行度和采样量:GPU 把”每像素独立”天然并行化,但每像素只发少量射线(实时没预算做上千次蒙特卡洛采样);CPU 路径追踪每像素要发上千条射线才能压噪,单机算力远不够实时。
| Raymarching | 路径追踪(smallpt) | |
|---|---|---|
| 几何 | SDF(符号距离函数) | 球体解析方程 |
| 图元 | 球、盒、圆环、胶囊等二十多种 | 只有球 |
| 布尔 | 平滑并集、差集(smin) | 不支持 |
| 平面 | 直接 SDF 平面 | 用半径 大球近似 |
SDF 的代价是距离场是近似的(除了基本图元),布尔运算会引入失真;解析球精确无误但几何单一。
这是最核心的算法差异。
Raymarching(球面追踪):沿射线步进,每步查当前点的 SDF 值 。因为 是到最近表面的距离,直接跳过 这么远一定不会穿墙——这就是”安全步进”。最多迭代 70 步,大多数射线 20 步内收敛:
float t = 0.0;
for (int i = 0; i < 70; i++) {
float d = map(ro + t*rd); // SDF 距离
if (d < EPS) break; // 命中
t += d; // 安全跳过
if (t > MAX_DIST) break;
}
优点对任何 SDF 通用;缺点有迭代开销,每步都要算一次 map()(场景里全部图元的最小距离)。
路径追踪(解析求解):射线 代入球面方程 ,得到 的一元二次方程,一步出精确解,无迭代、无近似。但只对解析几何有效——能写出求交公式的几何才能这么算,球是其中最简单的一种。
一句话:球面追踪是迭代逼近,解析求交是一步精确;前者通用,后者高效。
这是根本性的理念差异。
Raymarching 用经验光照模型——四个手工放置的光源(太阳光、天空光、背光、补光),明暗用朗伯(Lambert)漫反射 + 布林-冯(Blinn-Phong)高光,反射用施利克(Schlick)近似,阴影和环境光遮蔽(AO)也是单独近似叠上去。效果好看、可控、实时,但不是物理正确:光不会真的弹射,间接光照、颜色溢出(color bleeding)都得靠手工近似拼。
路径追踪直接数值求解渲染方程 。光线按材质随机弹射,间接照明、颜色溢出、透明折射全部自动涌现——不需要手工放光源(光源就是自发光球),不需要调经验参数。代价是蒙特卡洛噪声:标准差按 衰减,采样翻 4 倍噪声才减半,所以要慢得多。
| 适合 | |
|---|---|
| Raymarching | 游戏、实时可视化、Shader 艺术 |
| 路径追踪 | 电影、建筑渲染、离线高质量图 |
两者互补而非替代。现代 NVIDIA RTX 在 GPU 上用硬件加速(RT Core 做射线遍历、Tensor Core 做 AI 降噪)跑路径追踪——把 GPU 的并行度和路径追踪的物理正确性合起来,再靠降噪器在低采样下补出干净画面,这就是二者融合的现代形态。