转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=3072

上一篇完成了specular的环境光渲染。当然,在实际效果中,diffuse也是不可缺少的。在这套基于物理的环境光渲染中,也必须要有diffuse才完整。

Irradiance map

GPU Gems 2第10章详细描述了如何通过卷积cube map,得到irradiance map,并用于diffuse的环境光渲染。其基本原理就是,可以把cube map当作一个拥有无数方向光源的物体。场景中的任何一个点,都会受到cube map里所有方向光源的照射,累积起来得到最终结果。

从最基本的光照原理可以得出,对于一个点,只有normal方向的那个半球面会对这个点有影响。而且影响程度按照n dot l的大小来分布。各向同性的纯diffuse情况下,shading和视点方向无关。所以,这里可以用Spherical Harmonic(SH)来表达这个irradiance map,或者用importance sampling来进行卷积。为了保证框架的一致性,下文只考虑importance sampling的做法。

Lambert的importance sampling

KlayGE中diffuse的BRDF用的是Lambert,也就是个常量

$\rho_{lambert}(\mathbf{l},\mathbf{v})=\frac{\mathbf{c}_{diff}}{\pi}$

所以,可以认为Lambert的D是

$D_{Lambert}(\mathbf{l})=\frac{1}{\pi}$

前面说了每个点受影响的程度和n dot l成正比,就可以得出Lambert对应的概率密度函数pdf是

$pdf(\theta, \phi)=D \cos\theta \sin \theta=\frac{1}{\pi}\cos\theta \sin \theta$

注意这个pdf已经是关于光源方向的描述,而不是关于halfway的,所以不再需要像specular的pdf那样/(4*LoH)。

按照第二篇的推导,可以得到

$s_{\theta}=\arccos(\sqrt{1-\xi_{\theta}})$
$s_{\phi}=2\pi \xi_{\phi}$

这其实就是conine分布。用这个$\theta$和$\phi$,就可以去采样cube map了。

接下来,照样用这个importance sampling的公式

$L_0(\mathbf{v})=\int_{\Omega} \rho(\mathbf{l},\mathbf{v}) \otimes {L}_{i}(\mathbf{l}) (\mathbf{n} \cdot \mathbf{l}) d \omega_{i}$
$\approx \frac{1}{N}\sum_{k=1}^N\frac{L_i(\mathbf{l_k})\rho(\mathbf{l_k}, \mathbf{v})(\mathbf{n} \cdot \mathbf{l_k})}{pdf(\mathbf{l_k}, \mathbf{v})}$

把前面的D和pdf带入,就得到

$L_0(\mathbf{v})\approx \frac{1}{N}\sum_{k=1}^N\frac{L_i(\mathbf{l_k})D(\mathbf{n} \cdot \mathbf{l_k})}{D(\mathbf{n}) \cdot \mathbf{l_k}}$
$=\frac{1}{N}\sum_{k=1}^N L_i(\mathbf{l_k})$

没错,就是把cube map按照cosine分布采样,直接累加就行了。这样prefilter过的cube map只需要很小的分辨率,所以可以存在之前用于specular的cube map中mipmap的底层。在使用的时候,只需要用点的normal去采样这个prefilter过的cube map,乘上物体本身的diffuse颜色,就是diffuse光照的结果。

只有diffuse的时候是这样的,材质是黄色
Env BRDF Lambert Prefiltered

加上specular是这样
Env BRDF Lambert Blinn-Phong Prefiltered

总结

现在diffuse和specular都可以用同样的框架来表示,都只要采样一次prefiltered cube map。在开销很低的情况下就可以做到基于物理的环境光渲染。