学习笔记:pbrt中的光子映射II

对于光子映射算法的渲染精度受限于存储空间的问题,可以采用渐进式光子映射算法解决。该方法不再预先计算并存储各光子的信息,而是对于屏幕上的每一个像素存储它对应光线所遇到的第一个漫反射点及到达该点的吞吐量系数。这个漫反射点可以是光线碰到的第一个交点,也可以是光线经过几次镜面反射或透射后碰到的第一个交点。由于针对屏幕各像素所对应的一个点的信息,因而所需的存储空间是非常小的。基于上述表述可知,渐进式光子映射算法主要用来处理间接光照产生的漫反射,而不适用于镜面反射和高光反射。对于这种情况,还有一种最终聚焦的算法。计算某点的漫反射光照时,从该点向周围空间发出若干光线,提取光线相交处的光子能量,然后将能量平均化作为该点的出射辐照度。

尽管渐进式光子映射算法对存储空间需求较小,但对于较高分辨率图像或需要考虑运动模糊或景深时,需要的空间还是比较大。为此采用随机渐进式光子映射,该算法能在这些场合中,避免存储空间的限制。它的核心思想是进行多轮计算,每一轮中每个像素仅存储一个交点的信息,利用光子计算完后,丢弃该交点,下次重新产生一个位置略有不同的交点。相对于渐进式算法,随机渐进式算法,所用公式上有两点变化:第一,与权重有关的核函数改为圆盘形状的常量函数;第二,在每次迭代时,圆盘的半径是动态调整的。当在圆盘范围内有更多的光子时,就有理由相信减小圆盘范围后的光子也是足够的,且越使用接近目标点的光子,渲染的结果就越准确。这里更多的光子指的是随着迭代次数的增加,累积作用的光子数增加。需要注意一点的是累积的光通量也要在每次迭代中随着半径的变化而按比例进行调整。还需要注意一点的是,圆盘半径是每个像素的属性,对于一个像素对应的全部交点,都使用这个半径值。

下面介绍随机光子映射在实现中的一些细节。1)该实现该算法的积分器继承自积分器接口而非采样积分器接口。2)每次迭代时,屏幕同一像素产生的有一点差异,从而有助于实现抗锯齿,动态模糊和景深效果。3)需要设定初始圆盘半径,一般选择对应于屏幕几个像素长度的值。4)为每个像素定义了一个数据结构,用于存储当前迭代相关值,历史迭代相关值以及相交点的几何信息和反射信息。5)每次迭代时按表面的辐照度确定光子的权重是一种很难实现的理想情况,书中给出的方法是选择相同的光子权重,而是以光源功率为比例射出光子数,用这种方法来确定光子在场景中的分布。6)也对屏幕像素进行区域划分,实现并行加速。7)在光子作用阶段,需要根据光子位置高效地找到满足作用范围的相交点。具体的,采用hash表存储每个像素的数据,而每个像素的数据是一个链表。8)在产生光子阶段,第一步,随机选择一个光源;第二步,为光源采样准备采样数据;第三步,产生一条光线和初始的光子相关数据;第四步,寻找光线相交点,在相交点处产生光子;第五步,判断光线是否继续前进产生新的光子,判断依据是光子数据在该处变换越少,继续前进的概率就越大。9)每轮迭代结束后要对各像素存储的相交点数据进行重置。

你可能感兴趣的:(学习笔记:pbrt中的光子映射II)