19、计算机图形学——蒙特卡洛路径追踪

一、蒙特卡洛积分

蒙特卡洛积分主要解决的问题是当被积函数很难被以函数的形式表示时,需要对该被积函数指定概率密度函数并进行多次采样。然后用采样得到的局部面积除以局部采样点的概率来近似得到整体的面积(积分)。

当采样次数足够多时,将这些整体近似值除以采样次数,就能得到一个整体值得平局,则该整体值的平均就表示该积分的近似值。

可见,采样次数越多,最后得到的值越精确

二、蒙特卡洛路径追踪

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

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值