计算机图形学GAMES101(十五)光线追踪(蒙特卡洛积分与路径追踪)

本节涉及内容:

  • 蒙特卡罗积分
  • 路径追踪

蒙特卡罗积分

蒙特卡罗积分的核心思想还是求一个不规则图形的面积,它的做法是:首先在a和b之间找一个值xi然后求f(x)。接着以f(x)为高,ab为宽求矩形的面积,最后将所有的值求平均。当采样数量xi趋于无穷时,就近似求到了该不规则图形的面积。
在这里插入图片描述

怎么求蒙特卡罗积分

**FN**表示蒙特卡罗积分
**Xi~p(x)**表示概率分布
因为我们取xi时是在a到b之间均匀的取值,所以xi在ab上服从均匀分布。由均匀分布的概率密度函数可知 C=1/(b-a)
在这里插入图片描述
在这里插入图片描述
即p(xi)=1/(b-a)代入可得
从该式子可以看出,蒙特卡罗积分的思想:f(xi)表示图形的高度,b-a表示图形的宽度,1/N表示求平均值。这就从侧面说明了蒙特卡罗积分的核心思想。
在这里插入图片描述
求蒙特卡罗积分所需的条件:

  • 知道曲线上任何一个点的函数值,即f(xi
  • 知道采样的概率密度p(xi

路径追踪

这两个茶壶,左边这个完全光滑,是镜面反射,右边这个相对来讲没有那么光滑。在Whitted-Style Ray Tracing下,对于镜面反射的物体来讲没有什么问题,但是对于表面有些粗糙的物体,反射的光线应该朝向各个方向,如果认为还是认为沿着镜面反射方向反射,是不对的,因此这里产生了问题。
在这里插入图片描述
场景中的物体都是漫反射的,而如果用Whitted-style ray tracing,其定义当光线打到漫反射物体,那么这条光线就停下来了,那么两个物体之间的光线全部都得不到。右边是全局光照,光线打到一个漫反射物体上时,仍然继续传播直到射到我们的眼睛里,所有我们可以看到黑暗的地方。
在这里插入图片描述
因为Whitted-style ray tracing在物理上是错误的,所以需要一个之前的东西来替代它。即渲染方程
在这里插入图片描述
可以观察到渲染方程右边是一个积分,所以我们可以用蒙特卡罗积分来解。

在这一个简单场景中,我们就考虑清楚对于一个点(像素),他的直接光照是什么。

  • 有可能有其他物体会挡住光
  • 有一个相对较大的面光源
  • 观测方向:着色点到摄像机的方向ωo
  • 各个不同的进来的光(入射光方向):ωi(与Blinn-Phong一样,认为方向都是从着色点出发往外打)
    在这里插入图片描述
    对于一个着色点而言,它的光就是四面八方来的光被反射到观察点的光。(不考虑自发光)
    反射方程如下:
    在这里插入图片描述

那么怎么求这个渲染方程呢?

由蒙特卡罗积分可知要求一个积分要知道被积函数f(x)和概率密度p(x)

因为球的面积是4π,所以半球面积是2π,概率密度就是球上每一个点的均值即1/2π
在这里插入图片描述
将反射方程写成蒙特卡罗积分的形式
在这里插入图片描述

shade(p, wo)
Randomly choose N directions wi~pdf//随机选择n个采样点
Lo = 0.0
For each wi
	Trace a ray r(p, wi)
	If ray r hit the light
		Lo += (1 / N) * L_i * f_r * cosine / pdf(wi)//表示渲染方程
Return Lo

到此为止只是解决了直接光照的问题,但是我们最后的结果要是全局光照,因此再引入间接光照

因此我们需要计算由Q反射到P的光照,这个时候我们类比,就好像是在P点观察Q点,算出Q点的直接光照。Q点反射到P点的Radiance就相当于是在Q点算出的直接光照。
在这里插入图片描述
但是这样做就会产生一个问题,假如说一根光线射到一个物体上,反射出了一百根光线,然后又射到另一个物体上那就是一万根了,它是以指数级增长的,这样计算量太大了。
在这里插入图片描述
只有当N=1时计算量才时在可接受范围内,所以算法可以进行如下改进。

shade(p, wo)
Randomly choose ONE direction wi~pdf(w)   //只采样一次
Trace a ray r(p, wi)
If ray r hit the light
Return L_i * f_r * cosine / pdf(wi)
Else If ray r hit an object at q
Return shade(q, -wi) * f_r * cosine / pdf(wi)//这里进行递归,计算间接光照

当N=1时,这种追踪方式叫做路径追踪
当N!=1时,这种追踪方式叫做分布式光线追踪(计算量爆炸多)

虽然N=1会造成很大的噪声,但是穿过一个像素可以有很多条路径,然后对于这些路径求平均即可降低每条路径对于最终结果的影响。
在这里插入图片描述
下面是该方法的算法:

ray_generation(camPos, pixel)//camPos摄像机的位置,pixel待计算的像素值
Uniformly choose N sample positions within the pixel   //在这个像素内均匀的取N个不同的位置
	pixel_radiance = 0.0
	For each sample in the pixel  //对于任何一个位置都发射一条光线
		Shoot a ray r(camPos, cam_to_sample) 
		If ray r hit the scene at p  //如果打到了场景中
			pixel_radiance += 1 / N * shade(p, sample_to_cam)//计算该光线的着色
	Return pixel_radiance

但是这个递归算法并没有出口,这表示光线会弹射无数次,虽然显示生活中光线的确会经过无数次的弹射,但是计算机里面没办法模拟无数次,必须停止,如果直接规定最高弹射次数就会造成光线能量的损失,所以我们需要一种方法来停止弹射:
在这里插入图片描述

在这里插入图片描述
这种方法的算法表示:

shade(p, wo)
	Manually specify a probability P_RR //P_RR表示发射光线的概率
	Randomly select ksi in a uniform dist. in [0, 1] //ksi是[0, 1]的一个随机数
	If (ksi > P_RR) return 0.0;//如果ksi大于P_RR则表示不发出关系
	
Randomly choose ONE direction wi~pdf(w)//下面的算法和上面的一致
Trace a ray r(p, wi)
If ray r hit the light
	Return L_i * f_r * cosine / pdf(wi) / P_RR
Else If ray r hit an object at q
	Return shade(q, -wi) * f_r * cosine / pdf(wi) / P_RR

到此为止,这套算法就是正确的,而且可以计算间接光照的算法了。

虽然有了这套路径最终的方法但是并不高效,因为低SPP的画面效果很差,但是提高SPP后画面好,造成性能有负担。所以我们要解决的是在低SPP下也可以达到高SPP的画面效果。
在这里插入图片描述
之前我们实现路径追踪是在着色点朝着四面八方均匀的射出许多光线(均匀采样),当光源越来越小时能够射到光源上的光线就越少,就会使得很多光线都浪费了
在这里插入图片描述
所以我们需要找到一个更好的pdf采样方法。

如果我们直接从光源上采样,那么所有光线都不会被浪费了

假设对于着色点在光源上采样,那么对于这个面光源来讲,光源面积是A,均匀采样的PDF就是1/A

但是渲染方程是定义在半球中立体角上的,而不是在光源上的,

采样在光源上采样,积分在立体角上积分,如果要确保渲染方程还能用,就要把渲染方程写成在光源上的积分。
在这里插入图片描述
也就是说需要将渲染方程作为dA的积分 ,那么就要找到dω和dA之间的关系

因为立体角可以理解为将一块面积投影到一个单位球的表面上,所以只需要将dA投影到单位球的表面上,求出投影的面积,就得到了立体角,所以dω和dA之间的关系有如下公式:
在这里插入图片描述
把渲染方程写成在光源(dA)上的积分。那么就可以使用蒙特卡罗积分了,而且p(ω)=1/A
在这里插入图片描述
基于这种思想,改进的算法:

  • 第一部分来源于对光源的贡献,对光源采样
  • 第二部分来源于其他所有非光源的贡献(如物体反射的光),这部分还用原来哪个俄罗斯轮盘赌的方法进行计算
    在这里插入图片描述
shade(p, wo)
	//来自光源的贡献
	Uniformly sample the light at x’ (pdf_light = 1 / A)//均匀的对光源进行采用样即(1/A)
	L_dir = L_i * f_r * cos θ * cos θ’ / |x’ - p|^2 / pdf_light //写成dA形式的渲染方程
	
	//来自其他点的贡献,采用以前的俄罗斯轮盘赌方法
	L_indir = 0.0
	Test Russian Roulette with probability P_RR
	Uniformly sample the hemisphere toward wi (pdf_hemi = 1 / 2pi)
	Trace a ray r(p, wi)
	If ray r hit a non-emitting object at q  //打到了点q,确定点q不是光源(因为光源的贡献已经算出来了)
		L_indir = shade(q, -wi) * f_r * cos θ / pdf_hemi / P_RR
	Return L_dir + L_indir

左是照片,右边是通过路径追踪渲染出来的图像,几乎和现实一模一样。
在这里插入图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值