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

上一篇“游戏中基于物理的渲染(三)”中详细讲解了microfacet BRDF,本篇将解释目前大部分游戏中所用的BRDF和基于物理的BRDF之间的区别。

这里先回顾一下第二篇中推导出来的公式:

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

对比

游戏中常用的的反射方程是这样的:

\(L_{o}(\mathbf{v})=(\mathbf{c}_{diff} (\mathbf{n} \cdot \mathbf{l_c}) + \mathbf{c}_{spec}(\mathbf{r_v} \cdot \mathbf{l_c})^{\alpha}) \otimes \mathbf{c}_{light} \)

根据第一篇文章所述,\((\mathbf{n} \cdot \mathbf{l_c})\)实际上是属于反射方程,而不是diffuse,所以应该改成:

\(L_{o}(\mathbf{v})=(\mathbf{c}_{diff} + \mathbf{c}_{spec}(\mathbf{r_v} \cdot \mathbf{l_c})^{\alpha}) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})\)

其中,\(\mathbf{r_v}\)是视线方向对法线的反射向量,来自Phong模型。但是上一篇文章所论述的microfacet BRDF中并没有这一项。Blinn-Phong模型的形式和它类似,但用的是更有物理意义的h,也就是microfacet的m。改用Blinn-Phong的话就得到:

\(L_{o}(\mathbf{v})=(\mathbf{c}_{diff} + \pi \mathbf{c}_{spec}(\mathbf{n} \cdot \mathbf{h})^{\alpha}) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})\)

第一篇文章提到的Lambert可以发现,diffuse项已经和基于物理的一样了:

\(\mathbf{c}_{diff} = \pi \frac {\mathbf{c}_{diff}} {\pi}\)

所以,现在我们专注于specular项,前面的公式如果只看specular是这样的

\(L_{o}(\mathbf{v})=\pi (\mathbf{n} \cdot \mathbf{h})^{\alpha} \mathbf{c}_{spec} \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})\)

比较microfacet specular:

\(L_{o}(\mathbf{v})=\pi \frac{D(\mathbf{h})G(\mathbf{l_c},\mathbf{v},\mathbf{h})}{4(\mathbf{n} \cdot \mathbf{l_c})(\mathbf{n} \cdot \mathbf{v})}F(\mathbf{c}_{spec}, \mathbf{l_c},\mathbf{h}) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})\)

首先,从公式可以看出,游戏中用的\(\mathbf{c}_{spec}\)应该用表示Fresnel的\(F(\mathbf{c}_{spec}, \mathbf{l_c}, \mathbf{h})\)替换。

第二,上篇文章说过,\(D(\mathbf{h})\)与粗糙度有关,所以可以认为\(D(\mathbf{h})\)和Blinn-Phong的\((\mathbf{n} \cdot \mathbf{h})^{\alpha}\)功能相似。但是,要把\((\mathbf{n} \cdot \mathbf{h})^{\alpha}\)替换成正确的microfacet分布函数,就必须做一个归一化。也就是说,对于任意的视线方向v,微表面投影的面积之和必须等于宏表面投影的面积,数学上就是:

\((\mathbf{v} \cdot \mathbf{n}) = \int_{\Theta} D(\mathbf{m})(\mathbf{v} \cdot \mathbf{m}) d\omega_m\)

既然这个方程是对任何视线方向都得成立,那么对于特殊情况v = n也得成立:

\(1 = \int_{\Theta} D(\mathbf{m})(\mathbf{n} \cdot \mathbf{m}) d\omega_m\)

Blinn-Phong的项如果也要满足这个方程,就得乘上一个归一化系数:

\(D_{BP}=\frac {\alpha + 2} {2\pi}(\mathbf{n} \cdot \mathbf{m})^{\alpha}\)

现在剩下的一项,就是:

\(\frac {G(\mathbf{l_c},\mathbf{v},\mathbf{h})}{(\mathbf{n} \cdot \mathbf{l_c})(\mathbf{n} \cdot \mathbf{v})}\)

这个项的物理意义是可见性(遮挡项除以校正因子)。我们修改过的specular模型并不打算包含可见性,所以简单地把这个项设成1就行了,也就是:

\(G_{implicit}(\mathbf{l_c},\mathbf{v},\mathbf{h}) = (\mathbf{n} \cdot \mathbf{l_c})(\mathbf{n} \cdot \mathbf{v})\)

实际上,这对于仅包含height field的微表面是成立的(Blinn-Phong的表面分布函数也对应于此,因为所有背面的microfacet都等于0)。当l = n而且v = n的时候\(G_{implicit}()\)等于1, 这对于height field也是正确的(在宏表面的法线方向没有任何遮挡)。对于很斜的视角或者很斜的光线角都趋向于0,这也是正确的(microfacet被其他microfacet遮挡的可能性随着视角的增加而增加)。

经过整理,来自microfacet specular BRDF的几个项都明朗了,于是得到下面的渲染模型:

\(L_{o}(\mathbf{v})=\frac {\alpha + 2} {8}(\mathbf{n} \cdot \mathbf{h})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_c},\mathbf{h}) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})\)

前面的系数是因为\(\frac {\alpha + 2} {2\pi} \frac{\pi} {4} = \frac {\alpha + 2} {8}\)。

把diffuse加回去,就得到:

\(L_{o}(\mathbf{v})=(\mathbf{c}_{diff} + \frac {\alpha + 2} {8}(\mathbf{n} \cdot \mathbf{h})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_c},\mathbf{h})) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})\)

这就是本系列文章最终推出的基于物理的渲染模型。对比原先游戏中使用的模型,计算量增加非常少,但不但保证了保能量,还能让美术更容易调整参数。

本系列最重要的方程已经呈现,下一篇文章将提一些未来的工作,并展示一些基于物理的渲染结果,作为本系列的完结篇。