微面理论
PBR(Physically Based Rendering)让我们的渲染不再依赖经验模型,而是真正具有物理意义。其中的原因正是因为PBR的核心:微面理论(Microfacet theory)。微面理论已经是 CG 渲染以及BRDF的中心理论,SIGGRAPH也连续很多年有针对微面理论专门的学习课程。
Unreal4 引擎中,PBR渲染的地精银行Goblin,图片来自baolong zhang
不过微面理论的推导十分麻烦,在Real Time Rendering 4th上描述的篇幅也很有限1。初次接触很容易就被搞得一脸懵逼,但作为偏执狂的作者怎么能放过这一次疯狂挑战的机会!
PBR 可以通过2个参数均匀的模拟材质属性的变化
所以这一篇是:
- 微面理论介绍和证明推导
- 理解基于PBR的BRDF函数
- 推导阴影遮挡函数 G 2 G_2 G2
- 推导法向面分布NDF函数
- PBR为什么能真实的渲染光照
- 需要一些微积分和概率知识
我们先例行公事,做一些符号的定义:
- : = := := 强调这是一个定义
- ⟨ a ⋅ b ⟩ : = cos ( θ a b ) \left\langle\mathbf{a}\cdot\mathbf{b}\right\rangle :=\cos{(\theta_{ab})} ⟨a⋅b⟩:=cos(θab) ,其中 θ a b \theta_{ab} θab是 a \mathbf{a} a和 b \mathbf{b} b的夹角
- ⟨ a ⋅ b ⟩ + : = max ( 0 , cos ( θ a b ) ) \langle\mathbf{a} \cdot \mathbf{b}\rangle^+:=\max{(0,\cos{(\theta_{ab})})} ⟨a⋅b⟩+:=max(0,cos(θab)) ,其中 θ a b \theta_{ab} θab是 a \mathbf{a} a和 b \mathbf{b} b的夹角
定义
角度和向量定义
我们在上一篇里学到BRDF渲染函数公式,在对于任一个渲染片元(Rendering Patch)2:
(1) L o ( v ) = ∫ l ∈ Ω f ( l , v ) L i ( l ) ⟨ n ⋅ l ⟩ + d l L_{o}(\mathbf{v}) =\int_{\mathbf{l} \in \Omega} f(\mathbf{l}, \mathbf{v}) L_{i}(\mathbf{l})\langle\mathbf{n} \cdot \mathbf{l}\rangle^+ d \mathbf{l} \tag{1} Lo(v)=∫l∈Ωf(l,v)Li(l)⟨n⋅l⟩+dl(1)
其中 L o L_{o} Lo是光线传出的辉度(radiance)3, L i L_{i} Li光线传入的辉度, f f f是BRDF函数。
对于某一个具体的入射光线(也就是说,无论是场景中的点光源,平行光源,还是聚光灯或平面灯),对入射方向 l \mathbf{l} l进行微分:
(2) d L o ( v ) = f ( l , v ) L i ( l ) ⟨ n ⋅ l ⟩ + d l dL_{o}(\mathbf{v})= f(\mathbf{l}, \mathbf{v}) L_{i}(\mathbf{l})\langle\mathbf{n} \cdot \mathbf{l}\rangle^+ d \mathbf{l} \tag{2} dLo(v)=f(l,v)Li(l)⟨n⋅l⟩+dl(2)
接下来我们分离了漫反射 diffuse \text{diffuse} diffuse项和高光 specular \text{specular} specular项,对于漫反射项我们把渲染材质(Material)用兰伯特表面(Lambertian Surface)近似就能得到很好的效果。然而对于高光项,我们却无法直接通过单个菲涅尔表面(Fresnel Surface)近似,具体原因不言而喻,因为菲涅尔表面仅能在 l \mathbf{l} l的反射方向上传递光线。
单个菲涅尔表面无法模拟真实的高光情况,图中红色理想菲涅尔镜面反射的光,蓝色为想要模拟出来的高光反光
先来看看最终的高光项的BRDF:
(3) f spec ( l , v ) = F ( h , l ) G 2 ( l , v , h ) D ( h ) 4   ∣ n ⋅ l ∣   ∣ n ⋅ v ∣ f_{\text { spec }}(\mathbf{l}, \mathbf{v})=\frac{F(\mathbf{h}, \mathbf{l}) G_{2}(\mathbf{l}, \mathbf{v}, \mathbf{h}) D(\mathbf{h})}{4\,|\mathbf{n} \cdot \mathbf{l}|\,| \mathbf{n} \cdot \mathbf{v}| } \tag{3} f spec (l,v)=4∣n⋅l∣∣n⋅v∣F(h,l)G2(l,v,h)D(h)(3)
其中:
- G 2 G_2 G2是遮挡阴影函数(masking shadowing function)
- D D D是法向面分布函数(normal distribution function),我们后面简称为NDF
- F F F是菲涅尔反射函数(fresnel reflectance function)在上一篇定义过
PBR的BRDF用一个兰伯特表面和多个菲涅尔表面去模拟真实情况
看到这里千万不要慌,保持镇定!虽然我知道你满脑子的问号:遮挡阴影函数是什么?法向面分布函数是什么?分母的那个 4 4 4是干啥?但只要记住了,我们的本质想法是用多个微小的菲涅尔镜面去近似真实世界的材质,这就是微面理论的核心概念,剩下的我们再一一解决!
对于真实世界的物体在显微镜下观察确实是有很多微小平面组成
左图为抛光塑料表面,右图为不锈钢表面
高光项
微面化渲染片元:
微面和渲染片元的角度向量定义
先放下高光项的公式 ( 3 ) \left(\mathrm{3}\right) (3)。首先考虑某个渲染片元(比如是材料表面的一小块且刚好投影到屏幕上的一个像素那么大)这个渲染片元法向量是 n \mathbf{n} n 。和经典的BRDF模型4不同的是,也是微面理论的第一个假设:片元中包含了多个微平面。因此对于渲染片元来说,最后向观察者 v \mathbf{v} v方向传递的光,即辉度(辐射度,radiance)3则是其微面辉度的加和:
对于一个渲染片元来说,观察者方向的辉度可认为是各微面的辉度和
所以在微面理论中我们按各个微面在 v \mathbf{v} v方向投影所占的比例来计算辉度:
(4) L o ( v ) = ∫ projected area ( x ) L ( v , x ) d x ∫ projected area ( x ) d x L_\mathbf{o}(\mathbf{v})=\frac{\int \text { projected area }(x) L\left(\mathbf{v}, x\right) d x}{\int \text { projected area }(x) d x} \tag{4} Lo(v)=∫ projected area (x)dx∫ projected area (x)L(v,x)dx(4)
同时对于这个单位面积的渲染片元,在观察方向 v \mathbf{v} v的投影面积等于:
(5) projected area = v ⋅ n = cos θ o \text { projected area }=\mathbf{v} \cdot \mathbf{n}=\cos \theta_{o} \tag{5} projected area =v⋅n=cosθo(5)
法向面分布函数:
我们需要考虑对于一个单位面积上的渲染片元,朝向 m \mathbf{m} m方向上的微面面积,以便我们最后来统计这样的微面所占的比例。于是法向分布函数NDF就是这样定义的:
D ( m ) : = { 朝向   m   的微面面积 } D(\mathbf{m}) :=\{\text{朝向}\,\mathbf{m}\,\text{的微面面积}\} D(m):={ 朝向m的微面面积}
对于NDF有这些属性:
- 不是概率密度函数,也不是正态分布函数(要特别指出这点,被很多文稿弄错),而是一个面积的密度函数
- 0 ≤ D ( m ) ≤ ∞ 0 \leq D(\mathbf{m}) \leq \infty 0≤D(m)≤∞
- ∫ D ( m ) \int D(\mathbf{m}) ∫D(m)是所有微平面在渲染单元上的面积
- 所以 ∫ D ( m ) d m ≥ 1 \int D(\mathbf{m}) d \mathbf{m}\geq 1 ∫D(m)dm≥1 ,因此等号成立当且仅当渲染片元是一个纯平的面。
以及对于渲染片元法向方向 n \mathbf{n} n有:
∫ m ∈ Ω ⟨ m ⋅ n ⟩ D ( m ) d m = 1 \int_{\mathbf{m} \in\Omega}\left\langle\mathbf{m}\cdot\mathbf{n}\right\rangle D(\mathbf{m}) d \mathbf{m}=1 ∫m∈Ω⟨m⋅n⟩D(m)dm=1
遮挡函数:
投影的面积不仅和NDF成正比以外,还要考虑微平面被遮挡的情况。如果一个微面是背向观察者或者被其他微面遮挡时,那就不会考虑在 ( 4 ) \left(\mathrm{4}\right) (4)式中贡献辉度了。因此我们要定义其被遮挡的概率函数 G 1 G_1 G1
G 1 ( m , v ) : = { 在观察者是 v 方向时 , m 方 向 面的可见概率 } G_1(\mathbf{m},\mathbf{v}):=\{\text{在观察者是}\mathbf{v} \text{方向时},\mathbf{m}方向\text{面的可见概率}\} G1(m,v):={ 在观察者是v方向时,m方向面的可见概率}
现在就能计算式中的投影面积了:
(6) projected area = ∫ m ∈ Ω G 1 ( v , m ) < v , m > D ( m ) d m \text { projected area }=\int_{\mathbf{m}\in\Omega} G_{1}\left(\mathbf{v}, \mathbf{m}\right)\left<\mathbf{v}, \mathbf{m}\right> D\left(\mathbf{m}\right) d \mathbf{m} \tag{6} projected area =∫m∈ΩG1(v,m)⟨v,m⟩D(m)dm(6)
结合 ( 5 ) \left(\mathrm{5}\right) (5)式就有了我们的第一个微面理论的等式:
cos θ o = ∫ Ω G 1 ( v , m ) ⟨ v ⋅ m ⟩ D ( m ) d m \cos \theta_{o}=\int_{\Omega} G_{1}\left(\mathbf{v}, \mathbf{m}\right)\left\langle\mathbf{v}\cdot \mathbf{m}\right\rangle D\left(\mathbf{m}\right) d \mathbf{m} cosθo=∫ΩG1(v,m)⟨v⋅m⟩D(m)dm
代回 ( 4 ) \left(\mathrm{4}\right) (4)式,得到:
(7) L o ( v ) = 1 cos θ o ∫ Ω L ( v , m ) G 1 ( v , m ) ⟨ v ⋅ m ⟩ D ( m ) d m L_{\mathbf{o}}\left(\mathbf{v}\right)=\frac{1}{\cos \theta_{o}} \int_{\Omega} L\left(\mathbf{v}, \mathbf{m}\right) G_{1}\left(\mathbf{v}, \mathbf{m}\right)\left\langle\mathbf{v}\cdot \mathbf{m}\right\rangle D\left(\mathbf{m}\right) d \mathbf{m} \tag{7} Lo(v)=cosθo1∫ΩL(v,m)G1(v,m)⟨v⋅m⟩D(m)dm(7)
其中分母的 1 cos θ o \frac{1}{\cos \theta_{o}} cosθo1则是 ( 4 ) \left(\mathrm{4}\right) (4)式中单位面积渲染片元在观察方向 v \mathbf{v} v的投影面积。而积分号下则是对各微面辉度的加和。
此时我们可以定义对于观察方向 o \mathbf{o} o的权重函数,以方便后面计算:
(8) D m ( m ) : = G 1 ( v , m ) ⟨ v ⋅ m ⟩ D ( m ) cos θ o D_{\mathbf{m}}\left(\mathbf{m}\right):=\frac{G_{1}\left(\mathbf{v}, \mathbf{m}\right)\left\langle\mathbf{v}\cdot \mathbf{m}\right\rangle D\left(\mathbf{m}\right)}{\cos \theta_{o}} \tag{8} Dm(m):=cosθoG1(v,m)⟨v⋅m⟩D(m)(8)
请留意 D m D_{\mathbf{m}} Dm确实是概率密度函数,因为 ∫ D m ( m ) d m = 1 \int D_{\mathbf{m}}(\mathbf{m})d\mathbf{m}=1 ∫Dm(m)dm=1,所以 ( 7 ) \left(\mathrm{7}\right) (7)式可以写成:
(9) L o ( v ) = ∫ Ω L ( v , m ) D m ( m ) d m L_\mathbf{o}\left(\mathbf{v}\right)=\int_{\Omega} L\left(\mathbf{v}, \mathbf{m}\right) D_{\mathbf{m}}\left(\mathbf{m}\right) d \mathbf{m} \tag{9} Lo(v)=∫ΩL(v,m)Dm(m)dm(9)
激活面:
对于 ( 9 ) \left(\mathrm{9}\right) (9)式,我们想知道最后的渲染结果 L o ( v ) L_\mathbf{o}\left(\mathbf{v}\right) Lo(v),可以对每个积分号下的微面应用BRDF渲染函数:
L o ( v ) = ∫ m ∈ Ω ∫ l ∈ Ω ρ μ ( v , l , m ) L i ( l ) ⟨ l ⋅ m ⟩ D m ( m ) d l   d m L_\mathbf{o}(\mathbf{v})=\int_{\mathbf{m}\in\Omega}\int_{\mathbf{l}\in\Omega} \rho_{\mu}(\mathbf{v}, \mathbf{l}, \mathbf{m}) L_\mathbf{i}(\mathbf{l}) \left\langle\mathbf{l}\cdot \mathbf{m}\right\rangle D_{\mathbf{m}}(\mathbf{m}) d \mathbf{l} \,d \mathbf{m} Lo(v)=