PathTracing
渲染方程:
Lo(p,wo)=Le(p,wo)+∫Ω+Li(p,wi)fr(p,wi,wo)(n⋅wi)dwi
通过解渲染方程,可以得到正确的算法。
但它有以下两个难点:
- 公式的第二项是一个定积分,比较难求,可以使用Monto Calio方法解出它的近似值。
- 这是一个递归公式。
用 Monto Calio 方法解定积分
场景1[32:18]
先考虑一个简单场景:
只考虑这一个着色点、只考虑直接光照、且被照射点不发光。
有一个物体会遮住部分、有一个较大的面光源。
入射光线为上半球所有Wi,且均匀分布。出射光线为 Wo。
求这个点接收到并向wo辐射的能量。
根据渲染方程,有:
Lo(p,wo)=∫Ω+Li(p,wi)fr(p,wi,wo)(n⋅wi)dwi
由于本场景假设只考虑直接光照,那么Li(p,wi)只来自于光源。
用Monto Carlio解定积分,假设使用均匀采样,将公式代入以上公式,可将连续问题转化为离散问题,得到:
采样函数 | 积分函数 | 积分结果 | |
---|---|---|---|
理论上 | Xk∼p(x) | f(Xk) | 1N∑f(Xi)p(Xi) |
实际上 | 12π | Li(p,wi)fr(p,wi,wo)(n⋅wi) 均匀采样 | 2πNLi(p,wi)fr(p,wi,wo)(n⋅wi) |
其中wi来自采样
💡 连续问题往往比较难解。通过采样的方式把连续问题转化为离散问题,这样就只是需要考虑几个离散的点,就要好解得多。这是复杂问题简单化的一个思路。
场景2[40:40] 引入间接光照
P接收到的辐射不一定来自光源,也可以来自Q。
P接收到的来自Q的辐射 = Q向P发出的辐射。
对于P来说,辐射是来自直射光还是反射光,没有区别。
Lo(p,wo)≈1N∑func(wi)1/2π
当wi来自光源时,
fun=Li∗Fr∗cos
当wi来自其它物体q时,
fun=shade(q−wi)∗fr∗cos
场景3:一根光线会向多个方向弹射
[46:48] 光线路径数rays=Nbouns 这个量级下计算量会爆炸
因此取 N = l (即 path tracing),才不会发生爆炸。
即:每次使用Monto Calio求定积分时,只做一次采样。
虽然N取1会导致这个path在求定积分这一步引入较大的噪声。但是穿过像素的不止这一个path。[49:4] path足够多时,多个path的平均会缓解N=1带来的噪声。
如何解递归问题
从公式或者从上面的伪代码都能看出,这是一个递归问题。
递归本身不是问题。问题是这里的递归没有停止条件,会无限地递归下去。
人为定义 bounce 的次数
人为定义 bounce 的次数,当光线bounce这么多次(或者说递归到这个深度)后就强行停止。
这种方法能解决无限递归的问题,但会带来能量的损失。
Russian Roulette 俄罗斯轮盘赌
即不明确定义次数,而是以一定概率p决定是否继续 bounce。以此算出能量Lo。
最后使用Lo/p该点输出的能量。
这个结果的期望与无限 bounce 的理论结果相同,因为:
E = P * (Lo/ P) + (1-P) * 0 = Lo
到目前为止,已经得到一个正常的path tracing流程了。
本文出自CaterpillarStudyGroup,转载请注明出处。
https://caterpillarstudygroup.github.io/GAMES101_mdbook/