渲染方程的级数形式

首先,给出一般的「渲染方程」

\[ L_o(x, \omega_o)=L_e(x, \omega_o)+\int_{\Omega}f_r(x, \omega_o, \omega_i)L_i(x, \omega_i)\cos \theta d\omega_i \]

这个方程显然带有递归性质:从 \(x\) 点射出的光线 \(L_o\) 又会成为射入下一个交点 \(x^{'}\) 的入射光线

\[ L_o(x, \omega_o)=L_i(x^{'},-\omega_o) \]

在对一条光路进行「路径追踪」时,要递归多次以计算出最终进入相机的 \(L_o\) ,将 \(L_o\) 其记作 \(L_i^{0}\),上标表示递归的层级。

再看方程的积分项。路径追踪中,利用「蒙特卡洛积分」将积分项化成单纯的乘法运算,表示如下

\[ \int_{\Omega}f_rL_i\cos \theta d\omega_i\approx f_rL_i\cos \theta/p(\omega_i)=kL_i \]

综上,把渲染方程写成

\[ L_i^n=L_e^n+k_nL_i^{n+1} \]

由这个递推关系,展开最后的结果 \(L_i^0\),记 \(K_n=\prod \limits_{i=0}^{n-1}k_i\)

\[ \begin{aligned} L_i^0&=L_e^0+k_0L_e^1+k_0k_1L_e^2+k_0k_1k_2L_e^3+\cdots \\&=L_e^0+K_1L_e^1+K_2L_e^2+K_3L_e^3+\cdots \\&=\sum\limits_{i=0}^{+\infty}K_iL_e^i \end{aligned} \]

上式就是我们在「路径追踪」中实际使用的计算公式,这是一个单调收敛的无穷项级数,一般还要用「俄罗斯轮盘赌」方法控制项数。做这样的的变换有利于我们在编程时将渲染过程写成迭代而非递归。

此外,观察这个公式,可以对渲染方程有更深的理解:所有进入相机的光线源头都是 \(L_e\)\(L_e^0\) 是直接光照, \(K_1L_e^1\) 是经过一次折射或反射的间接光照,一般光栅化管线处理到这里为止。利用路径追踪,我们可以继续计算这个级数的更多项以得到「全局光照」。

如果更深一步,把渲染方程抽象成线性算子形式

\[ \begin{aligned} L=E+KL \end{aligned} \]

可以展开为

\[ L=(1-K)^{-1}E=E(1+K+K^2+\cdots) \]

思路上和我一致,只不过我是在更具体的情形下推导的,没有这么抽象,看看就好。


渲染方程的级数形式
https://adven00.github.io/2022/01/14/渲染方程的级数形式/
作者
Adven
发布于
2022年1月14日
许可协议