基于物理的BRDF

From KlayGE
Revision as of 02:09, 29 December 2010 by Gongminmin (Talk | contribs)

Jump to: navigation, search

引言

基于物理的渲染已经提出好多年了,但在游戏中使用的渲染模型仍然是拼凑出来的经验公式(比如Phong)。这些拼凑的模型如果要渲染高质量的图像, 就需要繁复地调参数。而基于物理的、保能量的渲染模型可以很容易地建立出在不同光照环境下都接近真实的材质来。

神奇的是,基于物理的模型并不会比传统上拼 凑的模型更难实现,计算量也差不多。

反射方程

游戏中最常使用的渲染模型描述的是反射,不考虑SSS等。反射方程可以表示成:

LaTeX: L_0(\mathbf{v})=\int_{\Omega} \rho(\mathbf{l},\mathbf{v}) \otimes L_i(\mathbf{l}) (\mathbf{n} \cdot \mathbf{l}) d\omega_i

其中,LaTeX: \rho(\mathbf{l},\mathbf{v})表示BRDF,LaTeX: L_i(\mathbf{l})表示光源给的贡献,LaTeX: (\mathbf{n} \cdot \mathbf{l})表示光源和表面法线的夹角。这个积分的结果就是所有光源对一个点的贡献之和。

Diffuse项

最简单的一个BRDF就是Lambert,在游戏中就是用LaTeX: (\mathbf{n} \cdot \mathbf{l})来表示。但实际上,LaTeX: (\mathbf{n} \cdot \mathbf{l})是属于反射方程的一项,而Lambert则是一个常量:

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

精确光源

游戏中经典的光源有point, directional和spot,这些局部光源都可以抽象成“精确光源”的概念,表示一个方向确定、大小为无穷小的光源。由于要计算的是到达表面点时的光照,所以不考虑从光源到表面之间的衰减。因此,精确光源都可以用颜色LaTeX: \mathbf{c}_{light}和光源方向向量LaTeX: \mathbf{l_c}这两个参数来表示。光源颜色LaTeX: \mathbf{c}_{light}的确切定义是,白色的Lambert表面被平行于表面法线(LaTeX: \mathbf{l_c}=\mathbf{n})的光照照亮的颜色。

如何计算这个光源对点的贡献呢?这里需要先引入一个叫做微面光源的概念。顾名思义,微面光源是一个非常小的面光源,中心是LaTeX: \mathbf{l_c},张角是LaTeX: \varepsilon。该微面光源照亮表面的一个点可以用LaTeX: L_{tiny}(\mathbf{l})来表示。它有两个性质:

LaTeX: \forall\mathbf{l}|\angle(\mathbf{l}, \mathbf{l_c})>\varepsilon, L_{tiny}(\mathbf{l})=0
LaTeX: if \mathbf{l_c}=\mathbf{n}, \mathbf{c}_{light}=\frac{1}{\pi}\int_{\Omega} L_{tiny}(\mathbf{l}) (\mathbf{n} \cdot \mathbf{l}) d\omega_i

第一个性质表示如果入射方向和LaTeX: \mathbf{l_c}的夹角大于LaTeX: \varepsilon, 那么亮度为0。第二个性质是从LaTeX: \mathbf{c}_{light}的定义而来,白色表面使得LaTeX: \mathbf{c}_{diff}=1,结合上文所说的反射方程和Lambert,就可以得出性质二。由于LaTeX: \mathbf{c}_{light}要求LaTeX: \mathbf{l_c}=\mathbf{n},所以LaTeX: \mathbf{c}_{light}也表示了当LaTeX: \varepsilon趋近 于0的时候的极限,也就是

LaTeX: if \mathbf{l_c}=\mathbf{n}, \mathbf{c}_{light}=\lim_{\varepsilon \to 0}(\frac{1}{\pi}\int_{\Omega} L_{tiny}(\mathbf{l}) (\mathbf{n} \cdot \mathbf{l}) d\omega_i)

因为LaTeX: \mathbf{l_c}=\mathbf{n}而且LaTeX: \varepsilon \to 0,我们可以认为LaTeX: \mathbf{n} \cdot \mathbf{l}=1,所以得到:

LaTeX: \mathbf{c}_{light}=\lim_{\varepsilon \to 0}(\frac{1}{\pi}\int_{\Omega} L_{tiny}(\mathbf{l}) d\omega_i)

也就是

LaTeX: \lim_{\varepsilon \to 0}(\int_{\Omega} L_{tiny}(\mathbf{l}) d\omega_i) = \pi \mathbf{c}_{light}

把微面光源带入一般的BRDF,得到的就是当趋近于0时的极限:

LaTeX: L_0(\mathbf{v})=\lim_{\varepsilon \to 0}(\int_{\Omega} \rho(\mathbf{l},\mathbf{v}) \otimes L_{tiny}(\mathbf{l}) (\mathbf{n} \cdot \mathbf{l}) d\omega_i)=\rho(\mathbf{l_c}, \mathbf{v}) \otimes \lim_{\varepsilon \to 0}(\int_{\Omega} L_{tiny}(\mathbf{l}) d\omega_i)(\mathbf{n} \cdot \mathbf{l_c})

所以

LaTeX: L_0(\mathbf{v})=\pi \rho(\mathbf{l_c}, \mathbf{v}) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})

入你所见,刚才引入的微面光源已经从公式中消失,剩下的部分又回到了熟悉的几个项。