DirectLightingIntegrator(直接光照积分器)是PBRT-V3中介绍的第二个积分器。第一个WhittedIntegrator。
回忆一下WhittedIntegrator:
Q111:PBRT-V3系统概述中的5.1分段。
DirectLightingIntegrator和WhittedIntegrator有很多相同之处:
1,概念上:
都只考虑直接光照。(间接光照部分只考虑镜面反射和镜面折射)
2,方程上:
都是这个,
只是,DirectLightingIntegrator中将Li换成了Ld,以示direct (light)。
咱更为关心的是DirectLightingIntegrator和WhittedIntegrator的不同之处。不同之处表现在“怎么求反射光线中来自直接光照的那部分光”。
WhittedIntegrator:
1-光源进行采样,得到一个采样点及其概率,确定入射光线wi,确定wi是否能够顺利到达撞击点。
2-根据wi和wo求出Bxdf(即f)
3-累加所有光源的效果
WhittedIntegrator存在的问题:
1-图片上每个像素点的一次采样对应一条反射光线,对应一条阴影光线,WhittedIntegrator中一条反射光线同时对应光源上一个采样点。
问题:如果要对光源进行很多次采样,则必须相应增加图片上每个像素点的采样次数,这样也就增加了阴影光线的条数。
2-WhittedIntegrator是先对光源进行采样获得wi,然后根据wi和wo求BxDF。
问题:并不是每个wi都能在wo上产生效果,BxDF的值可能为0。如果BxDF=0的情况很多,那么计算结果的方差就很大。(比如,镜面反射,一个wo只对应一个wi,那么对光源随机采样获得的“wi”基本都是无效的)
DirectLightingIntegrator则会解决这两个问题。
DirectLightingIntegrator将会怎样解决WhittedIntegrator中的那两个问题?
针对第一个问题,DirectLightingIntegrator为光源提供了两种采样策略;
针对第二个问题,DirectLightingIntegrator使用“复合重要性采样”;参考:Q119:PBRT-V3,“复合重要性采样”(13.10章节)。(分别对Light和BSDF进行重要性采样)
一、对光源的采样策略
DirectLightingIntegrator对光源提供了两种采样策略:
UniformSampleAll, UniformSampleOne。
UniformSampleAll,循环所有光源,对每个光源进行多次采样;
UniformSampleOne,随机选取一个光源,进行一次采样。
这两种策略在特定的情况下都是非常有用的:
UniformSampleAll,其实可以说解决了WhittedIntegrator中存在的问题1。在不想增加单像素点上的采样次数,又想增加光源的采样次数的情况下,针对每一条反射光线,就选择UniformSampleAll(循环所有光源,对每个光源进行多次采样)。
UniformSampleOne。有时候为了生成理想效果的图片,必须对单像素点进行多次采样(比如,理想效果的景深)。这时候反射光线本来就很多,针对每一条反射光线,选择UniformSampleOne(随机选取一个光源,进行一次采样)。
我们知道,进行采样时,需要给采样器提供随机数。
不同的采样策略需要的随机数的类型和数目是不同的。
进行一次采样时:两个用Sampler::Get2D()获取的二维随机数就可以了——一个用于Light的采样,一个用于光源的采样。
进行多次采样时:使用二维随机数数组更为合适。相比于Sampler::Get2D()获取的二维随机数,二维随机数数组有如下优势:
it gives the sampler an opportunity to use improved sample placement techniques, optimizing the distribution of samples over the entire array and thus, over all of the light source samples for the current point being shaded.
接下来,看看DirectLightingIntegrator::Li(),截图如下:
1.1 UniformSampleAll
前面提到对光源进行多次采样时,需要给采样器提供二维随机数数组。
the integrator requests sample arrays from the sampler before the main rendering process begins.
所以:
关于“二维随机数数组”,需要注意两点:
第一点是说,当同时存在镜面反射和镜面折射时,随机数数组会不够用。不够用了怎么办?没有随机数数组,那就只能使用随机数了,只能对光源进行单点采样了。
第二点就是前面preprocess()截图中提到的“一个撞击点,一个光源,两个随机数数组”。
随机数的具体使用时,也是成对使用的。
1.2 UniformSampleOne
这里有个问题需要注意一下:
为什么可以随机选取一个光源???
原因是:
单个像素点进行了多次采样,这样对于光源就“随机选取”了多次,最终计算的期望和“循环所有光源”时计算的期望是一样的。
二、EstimateDirect()
接下来就是用“复合重要性采样”求解“直接光照积分器”对应的积分啦!
“复合重要性采样”,参考:Q119:PBRT-V3,“复合重要性采样”(13.10章节)
为了“精确”求解图片上某像素点对应的“直接光照”的效果,需要调用EstimateDirect()函数nf次,然后对这nf次的计算结果求平均值。
“调用EstimateDirect()函数nf次”对应着“进行了nf次采样”。
这nf次采样怎么来呢?
若对图片上单像素点采样n1次,对n2个光源进行采样,每个光源采样n3次,那么nf=n1*n2*n3。
UniformSampleAll的情况大概是:n1=1,nf=n2*n3;
UniformSampleOne的情况大概是:n1=nf,nf=n1;
不管是哪种情况,反正最终是对光源进行了nf次采样,每次采样调用一次EstimateDirect()。
EstimateDiret()的代码截图如下: