在真实感渲染的领域,除开PT系列算法(pt,bdpt,mlt等)外,还有一个很重要的算法,就是光子映射(photon mapping)算法,这是一种统计上有偏的离线渲染算法。PT系列算法是统计无偏的算法,但是它们最大的问题是在面对SDS路径时求解的低效,所谓SDS的典型就是一个焦散光斑经过镜面反射到眼睛里,而光子映射在这方面相对而言是有比较大的优势的。PM最早由Jensen于1996年引入,它是一个two-pass的全局光照算法,第一步从光源发射若干光子到场景空间,经过N次的发射或者折射直到光子被吸收,或者逸出场景。在漫反射表面记录下光子的每次碰撞数据,组成一个全局光子图(镜面则不需要,因为我们处理镜面的时候是按照传统raytrace的方法处理的)。第二步则是利用之前生成的光子图进行渲染,渲染通常采用分布式光线跟踪算法。下面的关键就是如何利用这张光子图,一般而言,有两种利用方法:
1.直接将光子图可视化:
顾名思义,就是直接利用全局光子图对图像上对应的场景中的每一个点进行最终颜色求值,这个求值过程本质上是一个概率密度估计的过程。就是估计一个点附近光子的密度,而后求出该点的亮度值。由于光子分布完全没有规律,所以我们采用非参数估计方法。典型的非参数估计有直方图估计,核函数估计,和K-近邻估计。对于三维空间,直方图估计就好比把整个场景分割成若干个小的立方体,然后计算每个立方体中光子个数占所有光子数的比率m,再除以整个立方体体积V后作为该区域所有点的光子密度(注意是所有点),这就造成了直方图估计得出的整个密度函数的不平滑。针对这一问题,核函数估计设定了每个光子的权重,在一定范围内的光子参与密度估计,而每个光子的权重随其到目标点的距离平滑衰减(直方图估计相当于设定了每个光子权重相同)。K-近邻估计是以目标点为球心,把半径r逐渐扩大,扩大到刚好可以包含K个光子为止,那么密度P=K/nV(n是光子总数量,V是体积)。目前一般采用K-近邻估计方法来估算亮度。
当然这只是亮度估计,由于我们最终要求的是该点的颜色值,所以需要对每个由KNN搜集到的光子进行颜色加权求和。为了高效地利用光子图对场景进行颜色估计,一般将光子图组织成kd-tree的结构(最好是平衡的kd-tree),这样可以提高效率。事实上,用光子图可视化的方法渲染场景,效率是相当高的,只是内存容量是一个问题,因为想要得到好的效果,需要海量的光子。
再说KNN搜集方法,会有一个半径r,正是这个r造成了PM算法的有偏性,只有当光子数量趋于无穷,r趋于0的时候,PM算法才能达到无偏。不仅如此,r的存在还导致了boundary bias和topological bias,也就是在物体边缘以及物体中凹凸不平的部分会造成计算偏差(若直接用球面估计的话,通常是过估计,这样在边界处就会比较亮;相反,若用碟形估计或者表面法向量约束则容易导致边界较黑)。07年Robert Herzog等人提出的Photon Ray Splatting方法能很大程度上解决boundary bias和topological bias。下图是一张利用直接将光子图可视化渲染的简单场景图:
2.只利用光子图计算间接光照和焦散光照:
可以看出直接可视化光子图的方法得到的结果效果很差,充满了低频噪声,使得整个图片看起来很脏,那么一个很自然的想法是既然光线跟踪算法能很好地表现直接光照,能不能只用光子图来渲染间接光照。这是可行的,我们把场景的光照分为四个部分:直接光照(漫反射表面),间接光照,焦散光照,镜面(透明面)光照,直接光照和镜面(透明面)光照可以由光线跟踪来计算,间接光照由光子图来计算,可以考虑像1中一样将光子图可视化,但是同样地会产生低频噪声使图片质量下降。这里,由于只需要计算间接光,所以有了另外一种方法,即利用final gathering计算每个点的间接光照。在这里,final gathering(简称FG)的主要工作原理是:在每个FG计算点上方,整个半球区域中的所有方向上发射大量 FG采样射线 (发射FG采样射线的点称为FG点),用这些FG采样射线采集场景中的不同点处(主要是Diffuse表面上)的照明能量,然后把采集到的能量返还给发射FG采样射线的FG点,FG点会对每条FG采样射线返回的能量值进行平均化处理,最后把相邻的不同的FG点中的能量均衡在一起,从而计算出表面上每一点的间接照明效果。最后是焦散,它不能由FG求得,只能是将光子图可视化,这样就要求光子图中除了保存全局光子外还要保存焦散光子,并且要得到尖锐的焦散边缘,焦散光子的数量一定要大,实际上在使用了Final gathering之后,全局光子数即使减少很多仍能达到很好的效果,并且FG能将低频噪声转化成高频噪声,使得图片看起来舒服一点。
但是FG过程本身是一个非常耗时的过程,因为想要达到较好的结果,每个像素点至少得发射上百条FG射线,每次FG采样包含一次场景空间物体求交和光子搜集。而且FG方法并不能消除boundary bias和topological bias(虽然可以在一定程度上缓和它们),因为在凹角处,会有大量的FG射线击中相邻的表面,导致过估计。为了提高间接光照效率,还有很多方法,比较重要的有irradiance caching,它建立在间接光在空间的变化不会过快的假设上,利用插值来求解间接光,不过该方法有时候容易造成artifact。下图是同一场景利用FG计算的结果:
如果说PT,BDPT,MLT算法要求解到正确结果需要时间上的无限性,那么PM算法就需要时间和空间两方面的无限资源,因为它需要存储无限的光子,幸而在08年提出的Progressive Photon Mapping将这个空间无限的要求剔除,其核心思想是颠倒了光子发射和光线跟踪计算的顺序,逐步求精计算结果,不过这已经超出了本文的讨论范围。
最后是两张焦散渲染的图片,由光子图可视化方法得到: