[光线追踪] 03 -- 蒙特卡洛积分
在上一篇专栏里描述了两种渲染模型 -- 半球模型和面积模型, 两种模型都给出了包含积分项的式子, 那么渲染实际上就是求积分的近似值. 那么这篇专栏就来讨论如何求解这个积分.

蒙特卡洛积分
在深入讲解积分内包含求解量的复杂积分前, 首先来看看最简单的积分 .
如果这个积分无法直接求出, 那么有很多方法可以求得这个积分的近似值, 但是这里不会介绍 Gauss–Kronrod 求积之类复杂的东西.
首先回顾积分的定义可以知道: , 在学习积分时, 常把积分看作一吨长方形面积相加, 上式的
作为长方形的高,
作为底. 但是可以把符号进行重新解释:
作为某种均匀分布在
上的采样, 并且 xᵢ 的概率密度函数为
, 那么积分定义可以改写为
.
蒙特卡洛积分 (下面简称 MC 积分) 与上式的形式相同, 但 xᵢ 不再是依赖于下标 i 的数值, 而是符合 p 分布的随机数. 那么 MC 积分为 .
例子: , 积分区间为
, 使用两种分布展示 MC 积分的正确性: 均匀分布 和 正态分布(σ=0.5, μ=1.), 如下图所示

使用 10^5 采样数的结果如下:

可以看到两种分布都可以收敛至准确答案附近.

误差 & 重要性采样
在 MC 积分里, 选取合适的分布函数可以使得积分计算快速收敛. 为了量化累加收敛的速度, 需要计算累加项的误差: , 当 σ 值越小时说明收敛速度越快.
在给定 f 时, σ 的值与分布 p 相关. 为了降低 σ, 应该使每一项 与
接近, 当 σ 取最小值 0 时有
, 也就是当分布 p 为 f 本身时使得误差最小. 但绝大部分情况下, f 分布是很难或不能求出的, 所以应该选取与 f 尽可能接近的分布 p, 这就叫做重要性采样.
例子: f(x) = x + x², 积分区间 [0, 1], 考虑 3 个积分: 均匀分布, 正态分布 (σ=.5, μ=1) 和 正态分布 (σ=.5, μ=0), 如下图所示

使用 10^5 采样数计算误差为:

可以看到误差与分布形状相关, 分布形状越接近 f 的误差越小.
另外有一个可取的"捷径", 如果需要计算积分 , 由 MC 积分给出:
, 其中 Nₚ 是 p 的归一化因子
, 这种方法可以化简计算.
上面例子使用的程序如下 (julia)


MC 积分在光追里的应用
MC 积分比起其他类型的积分有一个优势, 就是 MC 积分是依赖于采样方法进行的, 也就是说高维积分, 比如半球面上的 , 如果存在直接从半球面上生成采样的方法 (见采样方法的两篇专栏: 1 和 2), 那么 MC 积分就可以如同一维积分一样直接进行计算, 而其他方法还需要对高维积分下的每个变量进行积分计算.
对于半球模型 (符号就不写完整了, 并且忽略 Lₑ): , 可以看到积分里有两个描述分布的项:
和
, 由 MC 积分给出求解:
. 当分布 fᵣcosθ 不能给出时, 可以计算
, 其中 cosθ 分布即是集中度为 1 的半球分布, 半球采样已经在之前的专栏里讨论过了. 使用 cosθ 分布求解光追的收敛速度尽管没有使用 fᵣcosθ 的那么快, 但也比半球的均匀分布更好, 下面是使用 cosθ 分布 (上) 和均匀分布 (下) 的渲染结果 (64个采样)


对于面积模型: , 因为入射方向是由 q 确定的, 所以这里是不能使用 fᵣ 或 cosθ 作为分布去计算积分, 因为 q 是分布在物体上的, 所以对物体进行均匀采样, 那么面积模型的求解为
, 其中 A 是物体的表面积. 看上去面积模型并不能使用 MC 积分化简计算, 但在实际使用里是用面积模型去化简半球模型 (见下).

渲染模型的混合使用
在常见场景里, 发光物体的数量是远远少于不发光物体的数量, 并且光源的直接照射对 Lₒ 的贡献是很大的, 所以在计算 Lₒ 时对每个光源单独计算积分可以使收敛速度大大加快. 所以对算符形式的渲染模型 进行修改, 把发光物体和不发光物体分离得到
, 其中 Lₒ,obj 代表不发光物体表面的出射辐照度, Lₒ,light 代表发光物体表面的出射辐照度, Kₕ 表示半球渲染, Kₛ 表示面积渲染, 那么这个渲染模型实际为

另外, 因为 light 已经在 Kₛ∘Lₒ 项计算过了, 所以如果出现 Kₕ∘Lₒ 指向 light 时, 应该返回 0 辐照度, 否则意味着 light 会被渲染两次.
最后, 为了化简模型, 可以大胆假设光源不反射任何光线, 即是 . 看上去这个假设非常牵强, 但实际上渲染出的图像仍然是足够真实的, 因为在 LDR 渲染里, 光源光线的辐照度可以到 50 以上, 而对比物体的反射光线最大只有 1 左右, 所以这个假设并不是无稽之谈. 但在 HDR 渲染里, 为了渲染真实场景, 部分光源(比如太阳)的辐照度可能到几万以上, 反射光线的辐照度会大于普通光源的辐照度, 这时的这个假设就会造成无法正确渲染了, 但实际上把光源的反射光线算上并不会对模型造成过大的更改.

光追的数学模型到这里就基本上固定下来了, 下一篇专栏对光追程序的结构进行一个简述, 然后就可以开始构建光追的实际程序了.
封面pid: 94213121

