欢迎光临散文网 会员登陆 & 注册

[光线追踪] 03 -- 蒙特卡洛积分

2022-05-24 13:10 作者:nyasyamorina  | 我要投稿

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


蒙特卡洛积分

在深入讲解积分内包含求解量的复杂积分前,  首先来看看最简单的积分 I%3D%5Cint_a%5Ebf(x)dx.

如果这个积分无法直接求出,  那么有很多方法可以求得这个积分的近似值,  但是这里不会介绍 Gauss–Kronrod 求积之类复杂的东西.

首先回顾积分的定义可以知道: I%3D%5Clim_%7Bn%5Crightarrow%2B%5Cinfty%7D%5Cfrac%7Bb-a%7D%7Bn%7D%5Csum_%7Bi%3D0%7D%5Enf%5Cleft(%5Cfrac%7Bb-a%7D%7Bn%7Di%5Cright),  在学习积分时,  常把积分看作一吨长方形面积相加,  上式的 f%5Cleft(%5Cfrac%7Bb-a%7D%7Bn%7Di%5Cright) 作为长方形的高,  %5Cfrac%7Bb-a%7D%7Bn%7D 作为底.  但是可以把符号进行重新解释:  x_i%3D%5Cfrac%7Bb-a%7D%7Bn%7Di 作为某种均匀分布在 %5Ba%2Cb%5D 上的采样,  并且 xᵢ 的概率密度函数为 p(x)%3D%5Cfrac%7B1%7D%7Bb-a%7D,  那么积分定义可以改写为 I%3D%5Clim_%7Bn%5Crightarrow%2B%5Cinfty%7D%5Cfrac%7B1%7D%7Bn%7D%5Csum_%7Bi%3D1%7D%5En%5Cfrac%7Bf(x_i)%7D%7Bp(x_i)%7D.

蒙特卡洛积分 (下面简称 MC 积分) 与上式的形式相同,  但 xᵢ 不再是依赖于下标 i 的数值,  而是符合 p 分布的随机数.  那么 MC 积分为 %5Cleft%5Clangle%20I%5Cright%5Crangle%3D%5Cfrac%7B1%7D%7Bn%7D%5Csum_%7Bi%3D1%7D%5En%5Cfrac%7Bf(x_i)%7D%7Bp(x_i)%7D%2C%5C%2Cx_i%20%0A%5Csim%20p.

例子:   f(x)%3Dx%2Bx%5E2,  积分区间为 %5B0%2C1%5D,  使用两种分布展示 MC 积分的正确性:  均匀分布 和 正态分布(σ=0.5, μ=1.),  如下图所示

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

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


误差 & 重要性采样

在 MC 积分里,  选取合适的分布函数可以使得积分计算快速收敛.  为了量化累加收敛的速度,  需要计算累加项的误差:  %5Csigma%5E2%3D%5Cfrac%7B1%7D%7Bn%7D%5Csum_i%5Cleft(%5Cfrac%7Bf(x_i)%7D%7Bp(x_i)%7D-%5Clangle%20I%5Crangle%5Cright)%5E2,  当 σ 值越小时说明收敛速度越快.

在给定 f 时,  σ 的值与分布 p 相关.  为了降低 σ,  应该使每一项 %5Cfrac%7Bf(x_i)%7D%7Bp(x_i)%7D 与 %5Clangle%20I%5Crangle 接近,  当 σ 取最小值 0 时有 %5Cfrac%7Bf(x)%7D%7Bp(x)%7D%3D%5Clangle%20I%5Crangle,  也就是当分布 p 为 f 本身时使得误差最小.  但绝大部分情况下,  f 分布是很难或不能求出的,  所以应该选取与 f 尽可能接近的分布 p,  这就叫做重要性采样.

例子:  f(x) = x + x²,  积分区间 [0, 1],  考虑 3 个积分:  均匀分布,  正态分布 (σ=.5, μ=1) 和 正态分布 (σ=.5, μ=0),  如下图所示

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

可以看到误差与分布形状相关,  分布形状越接近 f 的误差越小.

另外有一个可取的"捷径",  如果需要计算积分 I%3D%5Cint_a%5Ebf(x)p(x)dx,  由 MC 积分给出: %5Clangle%20I%5Crangle%3D%5Cfrac%7BN_p%7D%7Bn%7D%5Csum_%7Bi%3D1%7D%5Enf(x_i)%2C%5C%2Cx_i%5Csim%20p,  其中 Nₚ 是 p 的归一化因子 N_p%3D%5Cint_a%5Ebp(x)dx,  这种方法可以化简计算.


上面例子使用的程序如下 (julia)

MC 积分在光追里的应用

MC 积分比起其他类型的积分有一个优势,  就是 MC 积分是依赖于采样方法进行的,  也就是说高维积分,  比如半球面上的 %5Cint_%7B2%5Cpi%5E%2B%7Df(%5Comega)d%5Comega,  如果存在直接从半球面上生成采样的方法 (见采样方法的两篇专栏: 1 和 2),  那么 MC 积分就可以如同一维积分一样直接进行计算,  而其他方法还需要对高维积分下的每个变量进行积分计算.

对于半球模型 (符号就不写完整了, 并且忽略 L)L_o%3D%5Cint_%7B2%5Cpi%5E%2B%7Df_rL_o%5Ccos%5Ctheta_id%5Comega_i,  可以看到积分里有两个描述分布的项: f_r 和 %5Ccos%5Ctheta_i,  由 MC 积分给出求解: %5Clangle%20L_o%5Crangle%3D%5Cfrac%7BN%7D%7Bn%7D%5Csum_iL_o%2C%5C%2C%5Comega_i%5Csim%20f_r%5Ccos%5Ctheta.  当分布 fᵣcosθ 不能给出时,  可以计算 %5Clangle%20L_o%5Crangle%3D%5Cfrac%7B%5Cpi%7D%7Bn%7D%5Csum_if_rL_o%2C%5C%2C%5Comega_i%5Csim%5Ccos%5Ctheta,  其中 cosθ 分布即是集中度为 1 的半球分布,  半球采样已经在之前的专栏里讨论过了.  使用 cosθ 分布求解光追的收敛速度尽管没有使用 fᵣcosθ 的那么快,  但也比半球的均匀分布更好,  下面是使用 cosθ 分布 (上) 和均匀分布 (下) 的渲染结果 (64个采样)


对于面积模型:  L_o%3D%5Cint_Af_rL_ov(%5Cvec%20p%2C%5Cvec%20q)%5Cfrac%7B%5Ccos%5Ctheta_%7Bi%2C%5Cvec%20p%7D%5Ccos%5Ctheta_%7Bo%2C%5Cvec%20q%7D%7D%7B%7C%5Cvec%20q-%5Cvec%20p%7C%5E2%7DdA(%5Cvec%20q),  因为入射方向是由 q 确定的,  所以这里是不能使用 fᵣ 或 cosθ 作为分布去计算积分,  因为 q 是分布在物体上的,  所以对物体进行均匀采样,  那么面积模型的求解为 %5Clangle%20L_o%5Crangle%3D%5Cfrac%7BA%7D%7Bn%7D%5Csum_%7Bi%3D1%7D%5Enf_rL_ov(%5Cvec%20p%2C%5Cvec%20q)%5Cfrac%7B%5Ccos%5Ctheta_%7Bi%2C%5Cvec%20p%7D%5Ccos%5Ctheta_%7Bo%2C%5Cvec%20q%7D%7D%7B%7C%5Cvec%20q-%5Cvec%20p%7C%5E2%7D,  其中 A 是物体的表面积.  看上去面积模型并不能使用 MC 积分化简计算,  但在实际使用里是用面积模型去化简半球模型 (见下).


渲染模型的混合使用

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

另外,  因为 light 已经在 Kₛ∘Lₒ 项计算过了,  所以如果出现 Kₕ∘Lₒ 指向 light 时,  应该返回 0 辐照度,  否则意味着 light 会被渲染两次.

最后,  为了化简模型,  可以大胆假设光源不反射任何光线,  即是 L_%7Bo%2C%5Cmathrm%7Blight%7D%7D%3DL_e.  看上去这个假设非常牵强,  但实际上渲染出的图像仍然是足够真实的,  因为在 LDR 渲染里,  光源光线的辐照度可以到 50 以上,  而对比物体的反射光线最大只有 1 左右,  所以这个假设并不是无稽之谈.  但在 HDR 渲染里,  为了渲染真实场景,  部分光源(比如太阳)的辐照度可能到几万以上,  反射光线的辐照度会大于普通光源的辐照度,  这时的这个假设就会造成无法正确渲染了,  但实际上把光源的反射光线算上并不会对模型造成过大的更改.


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


封面pid: 94213121

[光线追踪] 03 -- 蒙特卡洛积分的评论 (共 条)

分享到微博请遵守国家法律