蒙特卡洛积分与路径追踪
(1)蒙特卡洛积分(Monte Carlo Integration)
函数比较复杂,它不好通过解析的方式积出来。
蒙特卡洛积分是一种数值方法,我只关心这个积分最后出来的值是多少,我们不需要把解析式算出来。
黎曼积分(即定积分)的方法很简单,比如将区间 [a, b] 拆分成 100 份,每一份我取区间中点的值,每一份都视作微小的长方形,就可以把整个曲线下方的面积分解成各个不同的小的长方形面积之和。
而蒙特卡洛积分是采用一种随机的采样的方法。它在 a 和 b 之间随机取一个数,它对应 f(x) 的值作为长方形的宽,区间宽度作为长方形的长,也就是说,我用这么一个长方形的面积来近似曲线下围出来的面积。这么一个过程我可以重复做很多次,我每一次得到的长方形的面积可能各不相同,然后我把这些长方形的面积平均起来,就能得到一个相对准确的结果。
这是一个比较直观的解释,那么如何真正去定义一个蒙特卡洛积分的这么一个过程呢?
举一个简单的例子:
概率密度:
PDF = 1 / (b - a) 很好理解,均匀地在区间域采样。
需要除以 p(x),是因为和布丰投针类似,通过频率估算概率,基于大数定律,这里除以 p(x) 是为了使得其数学期望等于所求积分。
所以蒙特卡洛积分有一个特殊的情况,随机变量是均匀采样的。
我只需要在积分域内以一个 PDF 采样,采样出来以后,这个样本对应的 f(x) 是多少,对应的概率密度 p(x) 是多少,两个一除,求平均就完了。任何的积分都可以这样做,我只需要知道这种采样对应的 PDF 是多少就可以了。
(2)路径追踪(Path Tracing)
路径追踪正是为了解决 Whitted-style 光线追踪里面很多非基于物理的,或者说不正确的问题。
左边的是镜面反射的效果,右边的是磨砂的效果。
注意第二幅图黄色方块侧面分别被反射出红色和绿色。
这个模型被广泛应用于测试各种各样不同的全局光照效果,因为太明显了,没有全局光照,天花板就是黑的。
我们意识到 Whitted-style Ray Tracing 是错的,那么谁是对的?辐射度量学正是为了提供这样一个标准。我们从辐射度量学知道,渲染方程是对的,因为我们是完完全全通过物理量推导出来的。
我们要的是积分出来的一个值。
对于这个点的直接光照是多少?
它本身不发光,自然来自于四面八方入射的光线。
均匀采样。
着色的伪代码:
我们要引入间接光照
支持全局光照的路径追踪算法:
指数爆炸。
随机往一个方向进行采样。
只用 N = 1 来做蒙特卡洛积分,就叫做路径追踪。如果 N ≠ 1,那就是分布式光线追踪,那就真的会出现指数爆炸。
红色一条路径,蓝色一条路径,黑色一条路径 ...... 这些所有的路径都会穿过这个像素,这个像素最后是多少,就是对这些路径求平均,那么我只要用足够多的 Path 就可以了。
真实世界中光线也不会停!
用俄罗斯轮盘赌的方式以一定的概率去停下继续往下去追踪。
最后,你仍然可以期望最后得到的结果是 Lo
我们希望在 Low SPP 的情况下也能够提高它。
先分析问题出在了哪?
打不打得到光源是看运气的,有很多的光线浪费掉了,是因为我们在着色点上均匀地往四面八方去采样的。
那我们不希望这么浪费,是不是有别的采样方法?
怎么才是完全不浪费光线的采样方法?
直接在光源上采样,就是不管光源有多大,我采样的样本都分布在光源的表面上,这样所有的光线都没有浪费了。
光源本身有一个朝向,法线 n' ,可以和着色点连线起来,会产生两个角,一个是光源和着色点法线的 θ 角,一个是光源和自己法线的 θ' 角。那我现在想采样光源,光源是二维的,理解成一个框,我在这个二维平面上均匀采样,那么我用的 PDF 就是 1 / A。我们采样是在光源上采样,但是这个渲染方程可不是定义在光源上的,渲染方程是定义在那个半球的立体角上的一个积分。蒙特卡洛要求在一个积分域上,比如我对 x 进行积分,那我采样就得在 x 上进行采样,而现在不对,我采样是在光源的面积上采样,但是我积分是在立体角上积分,那么蒙特卡洛就不能用。如果我还想让蒙特卡洛还继续生效,怎么办呢?我采样已经是在光源上采样了,我得把渲染方程写成在光源上的积分。
改写一下渲染方程,让它是对 dA 的一个积分,而不是对 dω 的一个积分。只要知道 dω 和 dA 的关系就可以了。
dA 是光源上的一个小的表面,dω 是这个小的表面到这个单位球上面的立体角,因为是单位球,所以这个投影的面积就是立体角。
这个式子就把 dω 和 dA 联系起来了。
重写渲染方程,现在的积分就是对光源 dA 的积分。现在问题就变得无比简单,我对光源进行采样,我对光源进行积分。
这一点最后的着色结果肯定来源于两部分,光源的贡献和来自其它所有非光源的贡献。
只有涉及到更多次弹射才用到俄罗斯轮盘赌。
现在版本的着色伪代码:
我对光源进行采样之后就考虑它对着色点的贡献,这是假设光源中间完完全全不会被挡到才能进行计算。那如果中间有物体被挡到怎么办?那就要判断一下光线能不能贡献到这个着色点。
Path Tracing 确实很难
Path Tracing 几乎是百分之百正确的一个算法。
之前用到的 Cornell box 是真实存在的,它是一张照片,右边就是全局光照的 Path Tracing 能算出来的结果。Path Tracing 能做到照片级真实感。
网站见 http://www.graphics.cornell.edu/online/box/compare.html
以前说 Ray Tracing 就是 Whitted-style 的 Ray Tracing,现在是所有光线传播方法的大集合。