球谐光照是实时渲染技术中的一种,属于Precompute Radiance Transfer(PRT)的范畴。经过预处理并存储相应的信息之后,它可以产生高质量的渲染及阴影效果。球谐光照需要使用新的光照方程来代替通常的光照方程,并将该方程中的相关信息使用球谐基函数来投影到频度空间,并用系数进行表示(该变换与信号处理中的Fourier变换同样的道理)以一定的方式存储。在渲染的过程中就结合球谐变换的特性以及这些预先存储的系数信息来对原始的光照方程进行还原并对场景进行着色。这个过程是对无限积分进行有限近似的过程,但是通常却可以得到较为理想的效果。当然,球谐函数也具有很多神奇的特性(比如旋转不变性,rotation invariant),这些特性就为其在渲染以及其它领域中的应用又带来很多优势。之前关注的三维模型检索以及特征值的提取就同样可以借助于球谐变换来对3D模型进行基于内容的特征分析与变换(3D model & Spherical Harmonic & moments),效果也非常好。一般来说使用球谐变换的特性可以得到一定程度上动态的光照渲染效果,比如场景或环境光的旋转等。但是场景中的相对物体却不能实现动态的变化,这是由于对整个场景的预处理是与其在空间场景中的位置相关的。当然,近年来的一些研究也都已经把这些个问题作为相应的研究方向,比如对光照方程进行更为多样、合理的分解等。
综合说来球谐光照的基本框架如下所述:
连续的光照方程 -> 离散的光照方程 -> 分解后的光照方程 -> 球谐变换得到球谐系数 -> 利用球谐系数还原光照方程
球谐光照分析与变换中常用的光照模型通常如下式所示:
该光照方程较为复杂但却典型,经常出现在各种基于物理渲染染的文章中(可以研究下Physcially based Rendering中相关章节的内容深入理解下)。作为球谐变换光照的基本切入点,需要对这一光照方法进行简单的解析,其中的积分下标表述了对应的积分空间,在实际中即为当前点的法线方向所对应到的一个半球空间。其余各项:
为点x处在w方向上的光密度;
为物体自身在点x处发出的光线;
为表面上x处的BRDF,它将从wi方向上进入到该点的光反射并变换到wo方向上;
为从其它物体上的点x'处沿wi方向到达的光线;
为两x,x'间(分别属于不同的物体)的几何关系;
为两点x,x'间的可见性关系,取值为0或1。
有了光照方程之后如何对其求解就成为渲染的关键。很显然,为了效率不能对这样的一个积分方程进行直接求解,因而这里就需要用到基于随机化算法的蒙特卡洛积分方法。
随机化方法是各个科研领域中经常用到的一种方法,毕竟神奇的自然界中充满了不确定的随机情况,对此我们只能用随机理论进行分析。计算机算法中的随机化方法同样以随机化的分析作为理论基础,由此看来学校里的随机过程还是很有用的一门课,但就是太抽象了,如果能与具体的应用相互结合来授课的话肯定事半功倍。蒙特卡洛积分就是利用随机理论来对无限积分进行近似的模拟,最常见的一种应用就是随机投点来计算\pi的值。
首先,需要在原始连续的积分空间上采样一定数量足够随机的离散采样点替代原始的连续空间,这个过程对于不同类型的积分空间有不同的方法,其中涉及到不少概率函数和概率密度的知识。
对于球面空间的积分区域即需要在整个球面上采样分布离散的点,其方法可以通过某种策略首先采样得到的2D点,然后将其映射到球面空间上:
注意采样点在2D中的分布规律,两边多中间少,而正是这样的才能保证将采样点映射到球面坐标系统之后可能保证条样点的均匀且随机。
有了离散的采样点之后即可在这些点组成的新的空间上对原始积分方程进行近似即可。
其中N为采样点的数量,权重函数w(xi)是由采样点i所对应的出现概率来决定,它可以表示为1 / p(xi)。这里得到的每个球面采样点的概率是相同的,因而w(xi)就退化为一常数因子,其取决于单位球的表面积,因而代入之后我们就得到上式中的离散积分表达式。
信号处理中很常用的一种方法就是傅立叶级数分解,这其实是用相互正交的Sin和Cos函数来近似表述其它的周期函数。其中的Sin和Cos之间的正交性是该变换的关键,一般称其为正交基函数。当前,有多种实用的正交基函数,其用途各不相同。在球谐变换中使用的基函数就是球谐基函数,其与勒让德多项式(Legendre polynomials)密切相关。勒让德多项式主要有以下三个属性:
通过这三个属性方程就可以递归地产生各个索引下的勒让德值。
通常的球谐函数是定义在复数空间的,但是这里的话只需要其实部就足够了。由伴随勒让德多项式而得到的实值球谐函数可以表述为如下形式:
其中的P即为相应的伴随勒让德多项式,K为SH球谐函数的缩放因子,其公式表述如下:
由了上述参数化的表示之后即可以求得蒙特卡洛采样后的球面空间上的球谐函数,其可视化之后的形状一般如下图所示:
假设一个原始的分布于球面空间上的函数为,其用球谐基函数表示后的形式为,可知, 而近似函数和球谐系数分别为:
将l,m索引化为i=l(l+1)+m后可得:
再对ci中的积分式用上述蒙特卡洛方法离散化后即可得
有了上述[2]和[3]之后我们就可以对一个球面空间上的函数进行球谐投影并还原,这是下一步进行预处理与渲染计算的基础。下图给出了使用球谐变换对某球面函数进行投影与重建的情形。
从图中可以看出随着变换波段的不断增大,对原始函数的投影与重建质量就越高,但相应的球谐因子也就不断增多。
此外,球谐变换还有一个非常重要的特性[特性1],即两个函数的乘积在球面空间上的积分值与它们的球谐系数向量组的点积相同。这也是将其应用于渲染方程中的一个关键。假设有两组分布于球面空间上的函数f1,f2,其投影到球谐基函数上后对应的近似为,变换过程中对应的球谐系数向量组分别为c1,c2。那么该特性可公式化为如下形式:
有了上述一大堆公式及理论支持后,实现一个具体的球谐光照算法就显得很直观了,如果手边已经有一个渲染引擎的话那就更加方便了。首先对于三维模型的格式,最好是索引形式的,因为需要对其中的顶点进行逐一计算球谐系数,而且对于具有相同Position和Normal的顶点得到的球谐系数相同,因而最好在向预处理计算过程中传入顶点前先剔除其中的冗余点。这些个都可以根据具体的实现以及个人的喜好适当的进行调整。
回头再看原始的光照方程[1],其中的BRDF分量对于一个Diffuse表面来说在各个方向上反射光线均相同,因而可以代替为一个恒量来控制,此时原始方程可简化为(不考虑Le分量):
而根据[特性1],又可以将其中的与其余部分分开处理,因而更加简化的方程模型即变为:
对于单纯的Diffuse情形,只需要处理式[4]中的G(x,x')分部即可,而其也只是简单的光线与顶点法向之间的夹角关系而己。我们只需要计算出夹角之间的cos值并将其作为G部分来进行存储即可:
对于带有遮挡的Diffuse情形,此时的V(x,x')分部同样需要考虑。这里就需要从当前顶点处向着光线的方向与场景进行相交性测试,通过相交测试的结果(0或1)来计算最后的结果即可。
上述的两种模型下的预处理计算均需要对大量的顶点进行操作,单纯的直接处理耗时着实很多,需要多方面分析并进行加速。首先对于所有采样点对应的球谐函数值,可以采用table的方式进行静态存储而不是每次计算系数时动态计算。这样可以减少不小的时间耗费,但整体处理时间下降得不多。由于预处理操作是逐顶点进行,而每个顶点之间相互独立,鉴于此特征,最容易想到的一种方法即是用GPU进行加速。其实此处的计算模型与光线跟踪的模型非常类似,特别是对于含有遮挡的情形。此时也必须对场景建立一棵划分树,并作相应的射线跟踪。
这里就直接使用了之前的基于CUDA的光线跟踪代码,并稍作修改就将GPGPU加速用在了此处,最后得到的效率加速比与光线跟踪相差无几(含有遮挡,若无遮挡加速比会较高),如下表所示,其中顶点的数量为5148,采样点的数量为10000:
球谐光照最早出现应该是在2002年的Siggraph上,距今还是有些时间了,而且关于其的研究也还有不少学者在做。 最近高调发布的BattleField3所使用的Frostbite2引擎中使用了Enlighten实时GI解决方案,其效果令人印象深刻,其中若干部分就用到了球谐光照的技术。但是观察其它的主流引擎却较少使用该技术(这里是指直接对全部场景做SH来代替LM的模式,不过在生成Light Probe等操作时SH的应用却是必需的),应该说其还是有不少局限的:
效果图
Diffuse without Shadow :
Diffuse with Shadow :
1. Robin Green, Spherical Harmonic Lighting: The Gritty Details. 2003
2. Matt Pharr and Greg Humphreys, Physically Based Rendering: From Theory to Implementatiaon. 2004
简单Demo: http://dl.dbank.com/c098u3exzk