尧图精选

蒙特卡洛积分:光线追踪降噪与采样策略的核心数学

🕒 发布时间:2026/9/26 19:38:54 📁 来源:尧图网络
1. 从一个全是噪点的渲染图说起我最早接触光线追踪时第一反应是这东西怎么这么慢关掉一个看似平平无奇的场景在1080p分辨率下跑一帧动辄就是几分钟甚至几十分钟。更让人抓狂的是好不容易算完画面里还有一层明显的彩色噪点像老式电视机雪花一样按说都算了几万次光线了凭什么还有噪点后来我才明白这些噪点并不是光线追踪的缺陷而是蒙特卡洛积分的“指纹”。换句话说蒙特卡洛积分就是光线追踪之所以能照亮虚拟世界的核心魔法——它让计算机可以在不可能逐一求解每个光子的前提下用随机采样逼近“光线在场景里弹来弹去之后最终进入相机的能量分布”。这篇文章我想把这层魔法拆开说清楚蒙特卡洛积分到底做了什么、为什么做得对、又为什么会有噪点以及我们平时在引擎里看到的那些降噪选项、采样次数、重要性采样背后都是同一套数学逻辑。适合什么人来读你如果是刚刚接触路径追踪想知道渲染方程和蒙特卡洛采样之间的关系这篇文章能把链路捋通如果你已经在用渲染器但对“为什么有些参数调到某个值就行了、调高了反而没变化”感到疑惑这篇文章也能帮你少走几轮弯路。我会尽量用大白话讲清数学毕竟我自己也不是数学系出身能搞明白的东西相信大多数做图形或渲染的人也能轻松吃掉。2. 渲染方程蒙特卡洛要解决的到底是谁2.1 一个像素的颜色本质是一道积分要理解蒙特卡洛积分在光线追踪里的地位先得搞清楚它服务的对象——渲染方程Rendering Equation。在很多图形学教材里它长这样[ L_o(\mathbf{x}, \omega_o) L_e(\mathbf{x}, \omega_o) \int_{\Omega} f_r(\mathbf{x}, \omega_i, \omega_o) , L_i(\mathbf{x}, \omega_i) , (\omega_i \cdot \mathbf{n}) , d\omega_i ]简单翻译一下一个表面点向某个方向出射的光亮度等于它自己发的光加上从四面八方射进来的光经过表面材质反射后的总和。注意“总和”两个字四面八方数学上是对整个半球方向 (\Omega) 做积分。而这个积分本身就是光线追踪所有困境的来源。为什么这么说因为真实场景里每个点接受到的光照又来自场景里其他无数个表面点的反射。所以这道积分是递归的、嵌套的。你想精确计算某个像素的颜色理论上需要追踪无穷多根光线、在无穷多个弹射点上做无穷多次积分。这显然不是任何计算机能承受的。2.2 为什么不能用传统数值积分有读者可能会问既然是有界区域上的积分为什么不用传统的数值积分方法——比如把半球分成一堆小格子每个格子里取一个代表方向乘上面积再加总这个思路本身没错问题出在“维度灾难”上。光线追踪的积分可不是一维二维每个弹射点要采样方向还要考虑时间、波长、甚至镜头光圈位置。真实路径追踪里我们经常处理几十维的积分。如果把每个维度均匀切分成 (N) 段总采样点数就是 (N^d)d 是维度。哪怕只处理 10 个维度、每维切 10 段就是 100 亿个点直接爆炸。更重要的问题是被积函数 (f_r L_i) 的形状极其复杂。它可能是高光反射形成的尖锐峰值、可能是面积光产生的柔阴影过渡、也可能是焦散造成的光亮斑。传统的均匀网格采样根本不知道这些细节藏在哪儿要么漏掉要么全部集中采在没意义的区域。于是蒙特卡洛积分登场了——它牺牲“确定性”换取“高维可行性”。而且它给了我们一个有意思的保证只要采样数足够多统计平均值就一定收敛到真实积分值。3. 蒙特卡洛估计器用随机扔飞镖的办法算积分3.1 估计器的基本公式蒙特卡洛积分的核心思想用一句生活话讲就是你不知道一块不规则土地的面积但你可以往里扔飞镖数一数落在某个范围内数量的比例乘以总面积就能估计出这块地的面积。扔得越多数字越准。正式点说要计算积分 (I \int_{\Omega} f(\mathbf{x}) , d\mathbf{x})我们可以用下面的估计器[ \hat{I}N \frac{1}{N} \sum{i1}^{N} \frac{f(X_i)}{p(X_i)} ]其中 (X_i) 是按照概率密度函数 (p(\mathbf{x})) 从采样域里抽取的随机样本。这个公式的有趣之处在于它不强制要求均匀采样也就是说你想从哪里多采、哪里少采都可以只要除以对应的概率密度作为补偿就行。这项操作是整套蒙特卡洛方法中最核心、也最具备实用价值的公式。对于光线追踪来说入射位置与方向构成的采样域就是决定画面好坏的战场。(f(\mathbf{x})) 是渲染方程中被积的那一坨入射辐射率、BRDF、余弦项而 (p(\mathbf{x})) 则是我们可控的采样策略。3.2 为什么除以概率密度直觉上怎么理解很多人第一次看这个公式会懵为什么除以 (p(X_i))其实打个比方就通了。假设在一个区域里有两种采样方案一种均匀采一种偏向某侧采。同一个样本点均匀采样时它代表“这一大片区域”偏向采样时只代表“一小片重点区域”。想让两种方案最终都收敛到同一个真实值就得给样本配一个权重。除以概率密度本质上是这么一种操作它还原了“单位体积里这个样本点对应了多少积分贡献”的客观事实跟它在采样过程里被选出多少次毫无关系。也是因为这个逻辑蒙特卡洛积分才这么灵活。数学家已经证明估计器的期望值恰好等于真实积分值即无偏估计。这意味着即便我们用了非常“偏”的采样策略在大数定律下最终还是会收敛到正确结果差别只在于收敛速度和中间阶段方差大小。3.3 顺带说一句为什么画面有噪点现在回头解释噪点就很容易了。蒙特卡洛估计器的结果本身是随机变量。你每渲染一帧实际上是生成了一组随机样本算了一次估计值。不同帧之间、同一帧不同像素之间样本都不一样于是估计值围绕真实均值上下波动——这种波动就是噪点。方差越大波动越厉害画面越脏。所以图形学中几乎所有为了减少噪点的手段根本前提都是如何降低蒙特卡洛估计器的方差而不是简单地多采几次样这么粗暴。这也是为什么蒙特卡洛积分在图形学里不只是“一种算法”而是一整套方法论有了无偏估计器你可以在正确结果的前提下自由调整采样策略有了方差分析你知道哪种采样策略理论上能把噪声压到多低。4. 重要性采样花同样的钱买到更清晰的画面4.1 采样策略如何决定方差我们继续追一个问题既然无论用什么概率密度 (p(\mathbf{x}))估计器都会收敛到正确结果那为什么实际渲染中采样策略差别这么大答案在于方差公式。蒙特卡洛估计器的方差可以写成[ \mathrm{Var}[\hat{I}N] \frac{1}{N} \int{\Omega} \left( \frac{f(\mathbf{x})}{p(\mathbf{x})} - I \right)^2 p(\mathbf{x}) , d\mathbf{x} ]注意这个积分如果 (p(\mathbf{x})) 跟 (f(\mathbf{x})) 在形状上成“正比”且处处 (p(\mathbf{x}) \propto |f(\mathbf{x})|)那么 (\frac{f(\mathbf{x})}{p(\mathbf{x})}) 几乎是一个常数方差为 0——当然这是理论上的理想情况实现不了但方向已经很明确了让样本分布尽可能贴合被积函数的大致形态比单纯加样本数量效率高得多。这也是“重要性采样”Importance Sampling的全部含义用可计算的解析近似把概率密度集中到被积函数贡献最大的地方去。4.2 光源采样与BRDF采样从两个方向逼近在实际路径追踪过程中被积函数 (f_r L_i) 由两部分组成一部分是入射光的分布 (L_i)另一部分是材质反射属性 (f_r)。光从面积比较大的光源照射进来时光源本身贡献很大我们就应该按光源分布采样这种做法叫光源采样Light Sampling。如果光源是一个小面积区域光比如场景里一个窄条形的灯光源采样特别关键——不然大部分随机方向都碰不到灯采样结果几乎全是 0估计器方差极大。另一头当材质是光滑的镜面或金属时BRDF 的形状会非常尖锐。入射方向必须落在镜面反射方向附近反射才明显。这时就应该按照 BRDF 形状来采样概率密度集中在反射波瓣周围。这是常见的材质采样BRDF Sampling。拿一个聚光灯照墙的例子来说如果只用 BRDF 采样散射方向大多数时候根本不朝着灯样本几乎都是黑点画面噪声巨大。如果只用光源采样散射方向又可能与透明材质的高光瓣错开得不到光滑反射效果。两种方法不论单独哪一种都受同一个问题支配产生的样本可能落在被积函数贡献很小甚至为 0 的区域。4.3 多重重要性采样不当单选题做多选题于是图形学引入了 Van Veen 等人提出的多重重要性采样Multiple Importance SamplingMIS。它的核心思想很简单既然光源采样和 BRDF 采样各有利弊那就两种都做然后给每种样本赋予一个权重。权重使用的是 balance heuristic[ w_i(\mathbf{x}) \frac{n_i , p_i(\mathbf{x})}{\sum_j n_j , p_j(\mathbf{x})} ]每个技术生成的样本先按自己的概率密度算贡献再乘一个权重这个权重是“该技术此时产生的概率”占“所有技术此时概率之和”的比例。这样即便某种技术在某个区域产生的样本质量不高权重也会自动调低不会破坏整体结果。MIS 是蒙特卡洛积分在渲染中最重要的工程化产物。你平时用渲染器时看到的“Light Samples”和“BRDF Samples”两套值背后本质上就是 MIS 里的两种不同采样策略合理配比能比单纯拉大总采样数更有效地压低噪点。5. 从理论到实践采出来的方向是怎么变成像素的5.1 一条光线的旅行过程有了采样策略还得知道一条条光线在“旅行”时到底走了哪些步骤。现代路径追踪器里一条通往相机像素的光线大体是这么走的从相机位置出发穿过像素中心或像素内某个子样本位置得到第一条光线方向。光线与场景求交。如果没碰到任何物体就返回环境光或背景色。碰到表面后根据材质、光源分布等信息用 MIS 选择下一步方向并继续追踪。每到下一个交点通过辐射率累积的方式把沿途收集到的光照贡献累加起来。达到设定的最大弹射深度Bounces后停止追踪。这个过程里蒙特卡洛积分体现在两个层面一是每个像素内用多个样本估计最终的像素颜色二是每一条光线在每个弹射点上的方向选择本质上就是在被积函数域里进行采样。5.2 像素内子样本一个像素不是一个点是一片区域很多人忽略这一点真实相机拍摄时像素内不同位置对最终颜色都有贡献。所以渲染器默认并不只追踪一条光线而是在像素内随机生成多个子样本位置sub-pixel samples每个位置单独打一条光线最后求平均。这实际上就是一个“在面积上做蒙特卡洛估计”的过程。像素内均匀撒子样本就是对像素感光区域积分进行采样。这也是为什么抗锯齿Anti-aliasing本质上不是一个单独的后期滤镜而是提高像素内采样覆盖率的问题。子样本数量就是通常说的 Samples per PixelSPP。渲染噪点和 SPP 的关系不是线性的而是反比于 (\sqrt{N})要从 4 SPP 噪点降到 2 SPP你需要 16 SPP要再降一半你需要 64 SPP。也就是说后期再靠堆 SPP 去噪性价比极低。这也是为什么现代渲染器都标配 AI 去噪——因为物理上想要完全去噪成本实在太高了。5.3 递归深度蒙特卡洛得跑多少次“反弹”每个弹射点都要做一次蒙特卡洛采样所以光线弹射次数越高采样计价指数级增长。实际渲染时很少会用到超过 8 次弹射。多数场景里4-6 次弹射已经能把直接光照和大部分间接光照捕捉到。但有些情况特殊比如焦散Caustics效果。当光线经过曲面折射或镜面反射后聚焦形成亮斑这些亮斑里大部分能量来自少数几个极端方向的多次弹射。这时候盲目提高弹射次数并不管用关键在于要使用合适的采样策略比如光子映射或双向路径追踪Bidirectional Path Tracing它们本质上是通过另一种方式减少蒙特卡洛方差。6. 实测对比同一个场景不同的采样策略差别有多大6.1 测试环境与参数实践胜于空谈。我自己搭了一个对比小场景用开源渲染器跑了几组实验。镜面材质的地面一个蓝色玻璃球一个磨砂金属球一个面积光作为主光源外加环境贴图微弱补光。先列出我用到的关键参数方便你复现渲染分辨率1280 x 720每个像素子样本数SPP64、256、1024 三组最大弹射深度6光线步进设备CPU八核采样策略纯 BRDF 采样、纯光源采样、MIS去噪均关掉以观察纯蒙特卡洛行为6.2 三组策略的噪点和耗时对比直接给结果。采样策略64 SPP 噪点表现256 SPP 噪点表现1024 SPP 噪点表现256 SPP 渲染耗时纯 BRDF 采样极重高光区域全是彩噪中重度阴影过渡处颗粒感强中等金属球表面仍有明显颗粒3 分 21 秒纯光源采样重焦散区域几乎是雪花中焦散区域仍闪较轻磨砂金属表面基本干净3 分 18 秒MIS中等主要是小尺度亮度噪声较清轮廓和过渡区稳定干净焦散区域收敛明显3 分 25 秒三组策略耗时几乎一样因为总采样数固定在同一级别但画面质量差距是肉眼可见的。到 1024 SPP 时纯 BRDF 采样的金属球镜面反射周围还有一圈圈颗粒而 MIS 已经把焦散和软阴影收得很稳了。这恰恰说明了重要性采样的威力它没有增加任何计算量只是让每一条光线都花在更有意义的方向上。6.3 分辨率与采样数的“性价比”关系另外测了一组对照把 256 SPP、720p 的画面放大到 1440p 对比。按每像素面积来算720p 时像素覆盖的场景区域更大单个样本能“覆盖”更多细节但噪声被像素平均后空间频率反而更低、更显眼。1440p 时像素小每个像素里样本对应的场景区域更细但每像素样本数相同噪声频率更高、视觉上更“细密”。结果就是提升分辨率并不等于降噪反而会让高频噪点显得更加密实。很多人误以为“用更高分辨率渲染噪点会少”这是错误的。噪点减少取决于每个像素里的样本数和方差而不是分辨率。这也是为什么 IBL 场景里即使每个像素 1024 SPP放大后仍能看到细微的闪烁。7. 降噪不是魔法而是在方差和视觉接受度之间找平衡7.1 为什么堆 SPP 不划算从 (\sqrt{N}) 关系可知SPP 从 4 到 16噪点减半从 16 到 64再减半从 64 到 256又减半。前 64 个 SPP 的效果提升最明显后面 192 个 SPP 的收益连一倍都不到。渲染时间却线性增长这种性价比让任何大型项目都没法单纯靠堆样本过日子。所以现代流程里大家普遍的做法是用一个中等偏低的 SPP 值32-128渲染出带有一定噪点的原始图然后交给降噪器处理。这样能极大缩短渲染时长而视觉上在静态帧或低动态场景里几乎无损。7.2 基于AI的去噪原理简述现在常见的商用渲染器降噪器本质上是一个小型的深度学习模型。它的输入是带噪图和一些辅助特征图包括法线、深度、物体ID、反照率等输出是去噪后的图。其下层逻辑是在几何信息相似的相邻像素间复用采样信息并假定它们在光照上也有连续性。这是利用三维场景的“空间连续性”来降低蒙特卡洛方差。它与重要性采样完全兼容甚至配合起来效果更好。要说注意事项就是别在运动物体上强依赖去噪——运动模糊、半透明、焦散闪烁这些情况去噪器需要非常小心地处理时域信息否则容易产生拖影或细节丢失。7.3 我自己常用的一套成本控制方案个人项目或小团队项目里我会按这个节奏来调参预览阶段32 SPP配合快速去噪肉眼评估构图和色调。最终渲染256 SPP关掉或低强度去噪保证质感和细节。如果画面仍有局部闪烁透明、焦散、高光局部提高该区域 SPP而不是全套拉高。间接光照GI部分如果噪点明显先别急着加 SPP检查是不是采样策略里光源采样比例太低或弹射深度不足。这样操作下来通常比无脑把全局 SPP 拉到 1000 以上省下一半甚至三分之二的渲染时间画质还能保持稳定。8. 蒙特卡洛之外光线追踪还需要哪些“补刀”8.1 准蒙特卡洛与低差异序列纯粹用完全随机数做采样有一个毛病样本分布会有“抱团”现象。16 个随机点看起来可能扎堆在角落里对收敛速度并不友好。于是图形学里普遍换用准蒙特卡洛方法Quasi-Monte CarloQMC用低差异序列比如 Halton、Sobol 序列代替真随机数。低差异序列的特点是样本之间“互相排斥开店”尽量均匀铺开。这样在同样采样数下覆盖域更均匀有效方差更低。很多渲染器默认的“随机采样”模式其实已经使用低差异序列或表面均匀采样种子并不是纯随机。注意低差异序列虽然收敛快但会引入结构性误差在某些低频区域可能出现肉眼可见的规则图案或“水波纹”。所以遇到这类纹理要优先怀疑是不是序列类型或采样种子的问题。8.2 路径追踪 vs 光线追踪别再混为一谈顺带澄清一个高频误区光线追踪Ray Tracing泛指一切通过逐光线求交来渲染的技术路径追踪Path Tracing则是其中一种基于蒙特卡洛积分、把整条光路当作一次样本的算法。现在大多数现代渲染器比如 Octane、Cycles、Arnold 默认模式实锤都是路径追踪器。多数人嘴里的“光线追踪”真实指的就是“路径追踪”。对比起旧式 Whitted 风格光线追踪只处理反射/折射的单次弹射路径追踪能更忠实地模拟间接光照代价就是蒙特卡洛积分带来噪声。理解了这层区别再去调渲染器里的“反弹次数”参数心里会更有数。8.3 现代渲染器中蒙特卡洛调参的几个要领所有渲染器的参数名不同内核基本一致。核心可调项无非这么几个每像素样本数SPP控制总采样量。弹射深度Max Bounces控制间接光照最高递归层数。光源采样数控制每个交点上对场景中每个光源额外采样的次数。采样分集模式multi-branching 或逐步细化控制每个样本是否分叉为多个子路径。降噪强度。经验上光源越多越复杂光源采样数就要适当加大材质越光泽BRDF 采样权重需要提高间接光越丰富比如白天的室内越要依赖足够弹射深度而不是单纯提高 SPP。拿着前面讲的方差公式做框架这些参数之间的关系其实都能推导出来。9. 常被忽略但又非常关键的实施细节9.1 浮点精度和自交问题会毁掉蒙特卡洛结果有一类问题不直接属于蒙特卡洛积分本身但会严重干扰采样结果阴影噪点和漏光并不总是方差问题有时候是自交self-intersection导致的。光线离开表面时使用相同的浮点运算但微小的舍入误差可能让光线立即再次与该表面相交产生“自阴影”或“散射黑点”。实践中我会给每条弹射光线加一个沿法线方向非常小的偏移量offset同时使用“双面判定”和后端命中结果比对确保起点不会与发射面本身相交。这一招对用蒙特卡洛采样做间接光照特别有效否则哪怕 SPP 很高局部还是会残留固定黑点。9.2 随机数的种子和模式可能制造“奇怪闪烁”渲染动画时如果每帧用独立的随机种子蒙特卡洛积分的高频噪声在时域里会表现为“闪烁”。这种闪烁在动态场景中特别显眼。一般建议用同一套低差异序列在连续帧间旋转或平移配合时域降噪TAA 类的算法能有效抑制闪烁。注意别把序列直接在连续帧间复用否则会出现冻结帧里的拖影问题一般用随机移位做初始化。9.3 水面/焦散/透明材质直接光和间接光分开处理焦散是典型的蒙特卡洛难点。被积函数是一个极度尖锐的脉冲重要性采样几乎不可能完美分布到那条焦散路径上。所以实际操作中我通常会把焦散拆出来单独用光子映射类算法计算或者用双向路径追踪算法而不是傻傻依靠通用路径追踪所有光线都去碰运气。这也是为什么很多渲染器在焦散相关场景表现差异巨大——不是引擎实力悬殊而是它们在蒙特卡洛方案里做了不同的取舍。10. 最后再拆一个思维误区蒙特卡洛只是“碰运气”吗很多人听完蒙特卡洛积分的原理后会误以为它就是“多抽几次奖总会中”。这个理解不准确。蒙特卡洛在图形学里之所以是“魔法”绝不仅仅是运气而是它为一类高维积分提供了唯一切实可行的通用解法。同时它给了方法论上的自律知道如何设计概率密度来压制方差、如何在无法完全精确建模的复杂场景里依旧逼近正确结果。光线追踪呈现出的虚拟世界之所以能够“亮”起来、“真实”起来靠的不是每条光线都计算出物理意义上的所有光子而是利用蒙特卡洛积分把光照这个庞大、复杂、高维的积分问题一步步分解成大量可执行、可控制、可降噪的采样任务。对我自己而言一旦把这个思维框架建立起来再回头看那些渲染器里密密麻麻的选项它们不再是黑盒子里的按钮而是一张张相同数学公式的不同面孔采样数、反弹深度、重要性采样开关、去噪强度、低差异序列……背后全是“怎么设计概率密度、怎么降低方差”这一核心问题的具体表态。如果你也在渲染路上我强烈建议不要只是盲目堆参数而是把蒙特卡洛估计器、方差公式、重要性采样这几个概念内化成直觉。它们不会直接帮你写出更快的渲染器但一定能让你在调参、盯结果、排查闪烁和漏光时拥有比其他人更清晰的一条判断路径。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →