蒙特卡洛积分主要解决的问题是当被积函数很难被以函数的形式表示时,需要对该被积函数指定概率密度函数并进行多次采样。然后用采样得到的局部面积除以局部采样点的概率来近似得到整体的面积(积分)。
当采样次数足够多时,将这些整体近似值除以采样次数,就能得到一个整体值得平局,则该整体值的平均就表示该积分的近似值。
在https://blog.csdn.net/Master_Cui/article/details/119898277中,渲染方程的形式如下
但是问题在于,如何对该渲染方程的积分项进行求解呢?在这里,就用到了蒙特卡洛积分
先只考虑直接光照,表示如下图所示,积分项一共有三个,所以,fx就是入射radiance*brdf*n.wi
再看下图,假设入射光线的概率密度函数服从均匀分布,因此,就可以从单位半球上的任意一点入射,因此,任意一点的概率就是1/2π,2π是单位半球的面积
考虑完直接光照后,再考虑间接光照(弹射),该如何计算Q点反射出能radiance呢
Q点本身是直接接受光照,反射出来的光线自然就是和上述的直接光照相同,只不过,Q点反射出来的光线需要再被当做入射光线,因此,这是个递归的过程,伪代码如下
考虑下图,比如从一百个方向进行采样,最终进入相机的光线只有一个,但是,如果这100个光线是经过了一次反射之后得到的,那么,这100个光线中的每个光线也要采样100次,那么也就是说,此时场景中需要有10000个光线,随着反射次数增多,场景中的光线就会出现指数级别的增长,对渲染速率有消耗
解决这个问题的办法就是每次只在一个方向上进行采样,因此,伪代码需要进行如下修改
但是,由于只进行一次采样,随机性太大,效果必然不好,那么就可以进行对多条路径分别采样求平均即可,如下图
第二个问题是上述递归没有退出条件,这个退出条件该如何写呢,这里借助了概率的思想。假设光线会出现反射的概率为P,那么,当光线相机接收到该光线时的Radiance就是L0/P,光线如果不仅进入相机的概率就是1-P,那么相应的radiance自然就是0。这样做之所以可行是因为整体的radiance期望L是不变的
到目前为止,蒙特卡洛光追算法基本OK,但是还有个小问题,就是有一部分光线被浪费了,导致效率不高
如下图所示,当对光线进行采样时,如果光源很大,那么能保证该光源发出的很多光线都被采样到,但是如果光源很小,那么,光源发出中的光可能只有极个别会被采样到,那么,光源中的其他光线就没法被采样到,这就导致光源的光线会被浪费。
因此,如果可以对光源的单位面积进行积分,那就可以解决光源光线浪费的问题。当前是对半球的单位立体角积分,所以,就需要找到半球单位立体角和光源单位面积的关系。
因为单位立体角等于单位面积除以半径的平方,可以,先计算出把dA的方向调整到与dw一致,调整后,dA调整后的值是dA*cosθ,最后在除以两点距离的平方,就能得到dA与dw的关系,如下
如果需要判断光线和反射点中间是否有物体遮挡,可以从光源发出一条光线,判断是否和物体相交即可
参考
GAMES101-现代计算机图形学入门-闫令琪_哔哩哔哩_bilibili
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出