[OpenGL]使用OpenGL实现基于物理的渲染模型PBR(下)
一、简介
在[OpenGL]使用OpenGL实现基于物理的渲染模型PBR(中)中介绍了基于物理的渲染(Physically Based Rendering, PBR) 的基本概念,并且实现了基于图像光源(IBL)的PBR中的漫反射部分。本文中将继续介绍IBL中的镜面反射部分。
按照本文代码实现后,可以实现以下效果:
二、基于IBL的PBR
1. 什么是IBL
IBL(Image-Based Lighting,基于图像的光照) 是一种使用环境贴图(Environment Map)提供间接光照的渲染技术,广泛应用于物理渲染(PBR)、电影特效 和 实时渲染(如游戏、VR等)。它通过 预计算的光照信息 让物体在复杂环境中表现出更加真实的全局光照(Global Illumination, GI) 效果。
简单来讲,IBL是一种存储环境光照信息的方法。在 IBL 中默认待渲染的模型接受来自环境中四面八方的光照,环境光使用一个 环境贴图 将各个方向的 irrdiance 存储到一张 texture 中(类似于 skybox),那么在渲染时就可以根据该 环境贴图 得到不同方向环境光对目标着色点的光照贡献。
根据渲染方程:
L o ( p , w o ) = ∫ Ω n p f r ( p , w i , w o ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i L_o\left(p,wo\right)=\int_{\mathrm{\Omega_{np}}}{fr\left(p,wi,wo\right)\ast L i\left(p,wi\right)}\ast n\cdot wi\ dwi Lo(p,wo)=∫Ωnpfr(p,wi,wo)∗Li(p,wi)∗n⋅wi dwi
在渲染时,对于目标点 p p p、当前的视线向量 w o wo wo,我们可以根据 w i wi wi 采样环境贴图对应方向的值,而环境贴图 w i wi wi方向的采样值即为 L i ( p , w i ) Li(p,wi) Li(p,wi)。因此我们可以使用数值积分方法求解上述渲染方程,即可得到目标值 L o L_o Lo。
2. IBL中的漫反射部分
如[OpenGL]使用OpenGL实现基于物理的渲染模型PBR(上)中我们讲的那样,在 pbr 中 f r ( p , w i , w o ) fr(p,wi,wo) fr(p,wi,wo)可以分为 漫反射 和 镜面反射 两部分,如以下公式所示:
f r ( p , w i , w o ) = k d ∗ f l a m b e r t + f s ∗ f C o o k − T o r r a n c e fr\left(p,wi,wo\right)\ =kd\ast f_{lambert}+fs\ast f_{Cook-Torrance} fr(p,wi,wo) =kd∗flambert+fs∗fCook−Torrance
因此渲染方程可以写为:
L o ( p , w o ) = ∫ Ω ( k d ∗ f l a m b e r t + f s ∗ f C o o k − T o r r a n c e ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i L_o\left(p,wo\right)=\int_{\mathrm{\Omega}}{(kd\ast f_{lambert}+fs\ast f_{Cook-Torrance})\ast L i\left(p,wi\right)}\ast n\cdot wi\ dwi Lo(p,wo)=∫Ω(kd∗flambert+fs∗fCook−Torrance)∗Li(p,wi)∗n⋅wi dwi
其中
f l a m b e r t = c π f_{lambert} = \frac{c}{\pi} flambert=πc
如果我们只考虑 漫反射 部分,那么可以得到:
L o , l a m b e r t ( p , w o ) = ∫ Ω n p ( k d ∗ f l a m b e r t ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i = ∫ Ω n p ( k d ∗ c π ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i = k d ∗ c π ∫ Ω n p L i ( p , w i ) ∗ n ⋅ w i d w i L_{o,lambert}\left(p,wo\right)=\int_{\mathrm{\Omega_{np}}}{(kd\ast f_{lambert})\ast L i\left(p,wi\right)}\ast n\cdot wi\ dwi \\ =\int_{\mathrm{\Omega_{np}}}{(kd\ast \frac{c}{\pi})\ast L i\left(p,wi\right)}\ast n\cdot wi\ dwi \\ =kd\ast \frac{c}{\pi}\int_{\mathrm{\Omega_{np}}}{L i\left(p,wi\right)}\ast n\cdot wi\ dwi Lo,lambert(p,wo)=∫Ωnp(kd∗flambert)∗Li(p,wi)∗n⋅wi dwi=∫Ωnp(kd∗πc)∗Li(p,wi)∗n⋅wi dwi=kd∗πc∫ΩnpLi(p,wi)∗n⋅wi dwi
因此,假如只考虑漫反射部分,任意的目标着色点 p p p 对应的积分值只与点 p p p 法向 n p n_p np 所在的半球 Ω n p \Omega_{np} Ωnp 有关,跟当前的视线向量 w o wo wo 、点 p p p 的材质属性都没关系。
那么,我们可以根据环境贴图预先计算得到法向为 n p n_p np 对应的半球 Ω n p \Omega_{np} Ωnp 范围内的积分值:
1 π ∫ Ω n p L i ( p , w i ) ∗ n ⋅ w i d w i \frac{1}{\pi}\int_{\mathrm{\Omega_{np}}}{L i\left(p,wi\right)}\ast n\cdot wi\ dwi π1∫ΩnpLi(p,wi)∗n⋅wi dwi
即,预计算得到一个查找表(look up table),该查找表的仅仅包含一个维度的自变量,即目标着色点的法向 n p n_p np,因变量为目标积分值(离线预计算得到) 1 π ∫ Ω n p L i ( p , w i ) ∗ n ⋅ w i d w i \frac{1}{\pi}\int_{\mathrm{\Omega_{np}}}{L i\left(p,wi\right)}\ast n\cdot wi\ dwi π1∫ΩnpLi(p,wi)∗n⋅wi dwi。
如下所示:
L o , l a m b e r t ( n p ) = l o o k u p t a b l e ( n p ) = 1 π ∫ Ω n p L i ( w i ) ∗ n ⋅ w i d w i L_{o,lambert}(n_{p}) = look\ up\ table (n_{p}) = \frac{1}{\pi}\int_{\mathrm{\Omega_{np}}}{L i\left(wi\right)}\ast n\cdot wi\ dwi Lo,lambert(np)=look up table(np)=π1∫ΩnpLi(wi)∗n⋅wi dwi
然后根据目标着色点的 漫反射系数 k d kd kd 和 颜色 c c c,即可得到 L o , l a m b e r t = k d ∗ c ∗ L o , l a m b e r t ( n p ) L_{o,lambert}=kd * c * L_{o,lambert}(n_{p}) Lo,lambert=kd∗c∗Lo,lambert(np)。
3. IBL中的镜面反射部分
对于渲染方程中的 镜面反射 部分:
L o , C o o k − T o r r a n c e ( p , w o ) = ∫ Ω n p ( f s ∗ f C o o k − T o r r a n c e ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i = k s ∗ ∫ Ω n p D ∗ F ∗ G 4 ∗ ( w o ⋅ n ) ( w i ⋅ n ) L i ( p , w i ) ∗ n ⋅ w i d w i L_{o,Cook-Torrance}\left(p,wo\right)=\int_{\mathrm{\Omega_{np}}}{(fs\ast f_{Cook-Torrance})\ast L i\left(p,wi\right)}\ast n\cdot wi\ dwi \\ =ks\ast \int_{\mathrm{\Omega_{np}}}{\frac{D\ast F\ast G}{4\ast\left(wo\cdot n\right)\left(wi\cdot n\right)} L i\left(p,wi\right)}\ast n\cdot wi\ dwi Lo,Cook−Torrance(p,wo)=∫Ωnp(fs∗fCook−Torrance)∗Li(p,wi)∗n⋅wi dwi=ks∗∫Ωnp4∗(wo⋅n)(wi⋅n)D∗F∗GLi(p,wi)∗n⋅wi dwi
可以看到,对于镜面部分任意点 p p p 受到环境光的影响不仅仅跟 p p p 对应的半球 Ω n p \Omega_{np} Ωnp 相关,还受到视角方向 w o wo wo、 p p p 的材质属性的影响,如果如处理漫反射一样构建一个查找表,其输入维度不仅需要包含法向 n p n_p np,还需要包含 w o wo wo,着色点材质属性 α \alpha α(粗糙度)等,维度太大。因此不能简单地如处理漫反射一样构建一个look up table 表示任意点 p p p 在任意视角方向 w o wo wo 下的环境光镜面反射。因此我们需要对渲染方程进行简化近似,以达到可以实时计算,或者可以预计算一个look up table 的程度。
3.1 镜面反射渲染方程
渲染方程中镜面反射的部分公式如下:
L o , C o o k − T o r r a n c e ( p , w o ) = ∫ Ω n p ( f s ∗ f C o o k − T o r r a n c e ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i = k s ∗ ∫ Ω n p D ∗ F ∗ G 4 ∗ ( w o ⋅ n ) ( w i ⋅ n ) L i ( p , w i ) ∗ n ⋅ w i d w i = ∫ Ω n p D ∗ F ∗ G 4 ∗ ( w o ⋅ n ) ( w i ⋅ n ) L i ( p , w i ) ∗ n ⋅ w i d w i (1) L_{o,Cook-Torrance}\left(p,wo\right)=\int_{\mathrm{\Omega_{np}}}{(fs\ast f_{Cook-Torrance})\ast L i\left(p,wi\right)}\ast n\cdot wi\ dwi \\ =ks\ast \int_{\mathrm{\Omega_{np}}}{\frac{D\ast F\ast G}{4\ast\left(wo\cdot n\right)\left(wi\cdot n\right)} L i\left(p,wi\right)}\ast n\cdot wi\ dwi \\ =\int_{\mathrm{\Omega_{np}}}{\frac{D\ast F\ast G}{4\ast\left(wo\cdot n\right)\left(wi\cdot n\right)} L i\left(p,wi\right)}\ast n\cdot wi\ dwi \tag{1} Lo,Cook−Torrance(p,wo)=∫Ωnp(fs∗fCook−Torrance)∗Li(p,wi)∗n⋅wi dwi=ks∗∫Ωnp4∗(wo⋅n)(wi⋅n)D∗F∗GLi(p,wi)∗n⋅wi dwi=∫Ωnp4∗(wo⋅n)(wi⋅n)D∗F∗GLi(p,wi)∗n⋅wi dwi(1)
其中 k s ks ks 即 F F F,因此在公式中省略了积分前的 k s ks ks。镜面反射项主要 分为 D,F,G三项。其中:
- D 为法向分布函数,Normal Distribution Function,微表面中法线朝向半程向量 ℎ 的表面片段所占的比例。使用以下公式计算:
D = N D F G G X − T R ( n , h , α ) = α 2 π ( ( n ⋅ h ) 2 ( α 2 − 1 ) + 1 ) 2 D=NDF_{GGX-TR}\left(n,h,\alpha\right)=\frac{\alpha^2}{\pi\left(\left(n\cdot h\right)^2\left(\alpha^2-1\right)+1\right)^2} D=NDFGGX−TR(n,h,α)=π((n⋅h)2(α2−1)+1)2α2
其中 α \alpha α为着色点粗糙度, n n n为着色点法向, h h h为半程向量。 - F 为菲涅尔项,Fresnel Rquation,描述了光在表面上的反射率随视角变化的情况,即上面的 k s ks ks。可以使用以下公式近似表示:
F = F S c h l i c k ( h , v , F 0 ) = F 0 + ( 1 − F 0 ) ( 1 − ( h ⋅ v ) ) 5 F=F_{Schlick}\left(h,v,F_0\right)=F_0+\left(1-F_0\right)\left(1-\left(h\cdot v\right)\right)^5 F=FSchlick(h,v,F0)=F0+(1−F0)(1−(h⋅v))5
其中 F 0 F_{0} F0 为着色点的基础反射率, h h h为半程向量, v v v为视线向量。 - G 为几何函数,Geometry Function,计算微表面之间的遮挡效应。G 项比价复杂,计算公式如下:
G = G S c h l i c k − G X X ( n , v , l , k ) = G s u b ( n , v , k ) ∗ G s u b ( n , l , k ) G=G_{Schlick-GXX}\left(n,v,l,k\right)=G_{sub}\left(n,v,k\right)\ast G_{sub}\left(n,l,k\right) G=GSchlick−GXX(n,v,l,k)=Gsub(n,v,k)∗Gsub(n,l,k)
其中:
k = ( α + 1 ) 2 / 8 ,针对直接光照 k = α 2 / 2 ,针对 I B L 光照 k= (α+1)^2/8,针对直接光照 \\ k= α^2/2,针对IBL光照 k=(α+1)2/8,针对直接光照k=α2/2,针对IBL光照
G s u b ( n , v , k ) = G S c h l i c k − G G X ( n , v , k ) = n ⋅ v ( n ∗ v ) ( 1 − k ) + k G s u b ( n , l , k ) = G S c h l i c k − G G X ( n , l , k ) = n ⋅ l ( n ∗ l ) ( 1 − k ) + k G_{sub}\left(n,v,k\right)=G_{Schlick-GGX}\left(n,v,k\right)=\frac{n\cdot v}{\left(n\ast v\right)\left(1-k\right)+k} \\ G_{sub}\left(n,l,k\right)=G_{Schlick-GGX}\left(n,l,k\right)=\frac{n\cdot l}{\left(n\ast l\right)\left(1-k\right)+k} Gsub(n,v,k)=GSchlick−GGX(n,v,k)=(n∗v)(1−k)+kn⋅vGsub(n,l,k)=GSchlick−GGX(n,l,k)=(n∗l)(1−k)+kn⋅l
α \alpha α为着色点粗糙度, n n n为着色点法向, l l l为光线向量, v v v为视线向量。
3.2 渲染方程简化
首先明确我们的目标,即如何快速的计算公式:
L o ( n p , w o , α ) = ∫ Ω n p f r ( w i , n , w o , α ) L i ( p , w i ) ∗ n ⋅ w i d w i (2) L_{o}\left(n_p,wo, \alpha \right) = \int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha) L i\left(p,wi\right)}\ast n\cdot wi\ dwi \tag{2} Lo(np,wo,α)=∫Ωnpfr(wi,n,wo,α)Li(p,wi)∗n⋅wi dwi(2)
其中 n p n_p np 为目标着色点的法向, α \alpha α为目标着色点的粗糙度, w o wo wo 为视线向量。
我们将渲染场景分为 待渲染的模型
和 光照贴图
两部分。
使用公式 (3) 近似表示 目标公式(2):
L o ( n p , w o , α ) = p r e _ f i l t e r e d ( n p , w o , α ) ∗ B R D F ( n p , w o , α ) (3) L_{o}\left(n_p,wo, \alpha \right) = pre\_filtered(n_p, wo, \alpha) * BRDF(n_p, wo, \alpha)\tag{3} Lo(np,wo,α)=pre_filtered(np,wo,α)∗BRDF(np,wo,α)(3)
其中 pre_filtered项(又称LD项) 是一个跟光照贴图相关的函数, BRDF 项(又称 DFG项)为只与 待渲染场景相关的函数。
接下来我们将会详细介绍如何定义、求解 BRDF 项 和 pre_filtered 项。
3.3 BRDF 项
3.3.1 BRDF 项的定义
我们假设渲染场景中存在一个待渲染的模型,并且光照贴图各个位置的值都为 1,即 L i ( w i ) ≡ 1 Li(wi)\equiv1 Li(wi)≡1。
那么此时的渲染结果为:
L o ( n p , w o , α ) ‾ = ∫ Ω n p f r ( w i , n , w o , α ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i = ∫ Ω n p f r ( w i , n , w o , α ) ∗ 1 ∗ n ⋅ w i d w i (4) \overline{L_{o}\left(n_p,wo, \alpha \right)} = \int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)*L i\left(p,wi\right)}\ast n\cdot wi\ dwi \\ = \int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)*1}\ast n\cdot wi\ dwi \tag{4} Lo(np,wo,α)=∫Ωnpfr(wi,n,wo,α)∗Li(p,wi)∗n⋅wi dwi=∫Ωnpfr(wi,n,wo,α)∗1∗n⋅wi dwi(4)
可以看出 公式(4) 是一个只与待渲染模型自身属性相关的函数,与外界的光照贴图无关。因此可以将公式(4) 视作 BRDF 项。那么就有:
B R D F ( n p , w o , α ) = ∫ Ω n p f r ( w i , n , w o , α ) ∗ n ⋅ w i d w i (5) BRDF(n_p, wo, \alpha) = \int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)} * n\cdot wi\ dwi \tag{5} BRDF(np,wo,α)=∫Ωnpfr(wi,n,wo,α)∗n⋅wi dwi(5)
3.3.2 BRDF 项的数值求解
根据 基于重要性采样的蒙特卡洛数值积分 可以得到:
B R D F ( n p , w o , α ) = ∫ Ω n p f r ( w i , n , w o , α ) ∗ n ⋅ w i d w i = 1 N ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ ( n ⋅ w i j ) p d f ( w i j ) (6) BRDF(n_p, wo, \alpha) = \int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)} * n\cdot wi\ dwi \\ = \frac{1}{N}\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*(n\cdot wi_j)}{pdf(wi_j)} \tag{6} BRDF(np,wo,α)=∫Ωnpfr(wi,n,wo,α)∗n⋅wi dwi=N1j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗(n⋅wij)(6)
其中 w i j wi_j wij 为我们根据概率密度分布函数 p d f ( w i j ) pdf(wi_j) pdf(wij) 采样得到的 w i wi wi 向量。
我们将 f r ( w i , n , w o , α ) fr(wi,n,wo,\alpha) fr(wi,n,wo,α) 函数展开可以得到:
B R D F ( n p , w o , α ) = 1 N ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ ( n ⋅ w i j ) p d f ( w i j ) = 1 N ∑ j = 1 j = N D ( n p , w h j , α ) ∗ F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ ( n ⋅ w i j ) 4 ∗ ( w o ⋅ n p ) ( w i j ⋅ n ) ∗ p d f ( w i j ) (7) BRDF(n_p,wo,\alpha) = \frac{1}{N}\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*(n\cdot wi_j)}{pdf(wi_j)} \\ = \frac{1}{N}\sum_{j=1}^{j=N}{\frac{D(n_p,wh_j,\alpha)*F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*(n\cdot wi_j)}{4*(wo\cdot n_p)(wi_j\cdot n)*pdf(wi_j)}} \tag{7} BRDF(np,wo,α)=N1j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗(n⋅wij)=N1j=1∑j=N4∗(wo⋅np)(wij⋅n)∗pdf(wij)D(np,whj,α)∗F(whj,wo,F0)∗G(np,wo,wij,α)∗(n⋅wij)(7)
其中 w h j wh_j whj为半程向量,可以根据 w i j wi_j wij和 w o wo wo计算得到:
w h j = ( w i j + w o ) ∣ w i j + w o ∣ (8) wh_j = \frac{(wi_j+wo)}{|wi_j+wo|} \tag{8} whj=∣wij+wo∣(wij+wo)(8)
由于 公式(7) 中的 微表面法向分布函数 D ( n p , w h j , α ) D(n_p,wh_j,\alpha) D(np,whj,α) 是以 w h j wh_j whj为自变量,因此我们需要根据 w h wh wh的概率密度分布函数 p d f ( w h ) pdf(wh) pdf(wh)采样 w h j wh_j whj,而不是根据 p d f ( w i ) pdf(wi) pdf(wi)。
根据公式
p d f ( w h ) = D ( n p , w h , α ) ∗ ( n ∗ w h ) p d f ( w i ) = p d f ( w h ) ∗ ∣ d w h d w i ∣ = p d f ( w h ) ∗ 1 4 ( w h ⋅ w o ) = D ( n p , w h , α ) ∗ ( n ∗ w h ) ∗ 1 4 ( w h ⋅ w o ) pdf(wh) = D(n_p,wh,\alpha)*(n*wh) \\ pdf(wi) = pdf(wh) * |\frac{dwh}{dwi}| = pdf(wh)*\frac{1}{4(wh \cdot wo)} = D(n_p,wh,\alpha)*(n*wh) *\frac{1}{4(wh \cdot wo)} pdf(wh)=D(np,wh,α)∗(n∗wh)pdf(wi)=pdf(wh)∗∣dwidwh∣=pdf(wh)∗4(wh⋅wo)1=D(np,wh,α)∗(n∗wh)∗4(wh⋅wo)1
可以得到:
p d f ( w i ) = D ( n p , w h , α ) ∗ ( n ⋅ w h ) ∗ 1 4 ( w h ⋅ w o ) (9) pdf(wi) = D(n_p,wh,\alpha)*(n\cdot wh) *\frac{1}{4(wh \cdot wo)} \tag{9} pdf(wi)=D(np,wh,α)∗(n⋅wh)∗4(wh⋅wo)1(9)
将公式(9)代入公式(7) 可以得到:
B R D F ( n p , w o , α ) = 1 N ∑ j = 1 j = N D ( n p , w h j , α ) ∗ F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ ( n ⋅ w i j ) 4 ∗ ( w o ⋅ n p ) ( w i j ⋅ n ) ∗ p d f ( w i j ) = 1 N ∑ j = 1 j = N D ( n p , w h j , α ) ∗ F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ ( n p ⋅ w i j ) 4 ∗ ( w o ⋅ n p ) ( w i j ⋅ n ) ∗ D ( n p , w h j , α ) ∗ ( n p ⋅ w h j ) ∗ 1 4 ∗ ( w h j ⋅ w o ) = 1 N ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ ( w h j ⋅ w o ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) (10) BRDF(n_p,wo,\alpha) = \frac{1}{N}\sum_{j=1}^{j=N}{\frac{D(n_p,wh_j,\alpha)*F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*(n\cdot wi_j)}{4*(wo\cdot n_p)(wi_j\cdot n)*pdf(wi_j)}} \\ = \frac{1}{N}\sum_{j=1}^{j=N}{\frac{\sout{D(n_p,wh_j,\alpha)}*F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*\sout{(n_p\cdot wi_j)}}{\bcancel{4}*(wo\cdot n_p)\sout{(wi_j\cdot n)*D(n_p,wh_j,\alpha)}*(n_p\cdot wh_j) *\frac{1}{\bcancel{4}*(wh_j \cdot wo)}}} \\ = \frac{1}{N}\sum_{j=1}^{j=N}{\frac{F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*(wh_j \cdot wo)}{(wo\cdot n_p)*(n_p\cdot wh_j)}} \tag{10} BRDF(np,wo,α)=N1j=1∑j=N4∗(wo⋅np)(wij⋅n)∗pdf(wij)D(np,whj,α)∗F(whj,wo,F0)∗G(np,wo,wij,α)∗(n⋅wij)=N1j=1∑j=N4 ∗(wo⋅np)(wij⋅n)∗D(np,whj,α)∗(np⋅whj)∗4 ∗(whj⋅wo)1D(np,whj,α)∗F(whj,wo,F0)∗G(np,wo,wij,α)∗(np⋅wij)=N1j=1∑j=N(wo⋅np)∗(np⋅whj)F(whj,wo,F0)∗G(np,wo,wij,α)∗(whj⋅wo)(10)
3.3.3 F(wh,wo,F0) 函数的简化
因为
F ( w h , w o , F 0 ) = F 0 + ( 1 − F 0 ) ( 1 − ( w h ∗ w o ) ) 5 F(wh,wo,F_0)=F_0+\left(1-F_0\right)\left(1-\left(wh\ast wo\right)\right)^5 F(wh,wo,F0)=F0+(1−F0)(1−(wh∗wo))5
整理得到:
F ( w h , w o , F 0 ) = F 0 + ( 1 − F 0 ) ( 1 − ( w h ∗ w o ) ) 5 = F 0 ∗ ( 1 − ( 1 − ( w h ⋅ w o ) ) 5 ) + ( 1 − ( w h ⋅ w o ) ) 5 (11) F(wh,wo,F_0)=F_0+\left(1-F_0\right)\left(1-\left(wh\ast wo\right)\right)^5 \\ = F_0*(1-(1-(wh\cdot wo))^5)+(1-(wh\cdot wo))^5 \tag{11} F(wh,wo,F0)=F0+(1−F0)(1−(wh∗wo))5=F0∗(1−(1−(wh⋅wo))5)+(1−(wh⋅wo))5(11)
我们仔细观察下公式(11),其自变量为 w h , w o wh,wo wh,wo 和 F 0 F_0 F0,其中 F 0 F_0 F0 为一个系数,我们可以暂时不管它。主要关注于自变量 w h wh wh 和 w o wo wo 。
从公式(11) 可以看出,函数 F ( ) F() F() 的自变量有三个分别是 w h , w o wh, wo wh,wo 和 F 0 F_0 F0。但是根据公式(10),我们仅仅需要根据 p d f ( w h ) pdf(wh) pdf(wh) 采样得到 N N N 个 w h j wh_j whj,然后计算 N N N 个 w h j wh_j whj 对应的 1 N ∑ j = 1 j = N ⋯ ∗ ( 1 − ( w h j ∗ w o ) ) 5 ∗ … \frac{1}{N}\sum_{j=1}^{j=N}{\dots* (1-(wh_j*wo))^5*\dots} N1∑j=1j=N⋯∗(1−(whj∗wo))5∗… ,而在采样 w h wh wh 时, w h wh wh 在径向满足概率分布函数 p d f ( w h ) = D ( w h ) ∗ ( w h ⋅ n ) pdf(wh) = D(wh)*(wh\cdot n) pdf(wh)=D(wh)∗(wh⋅n),但是在周向是对称的,如下图所示:
那么说明,只要保证 n ⋅ w o n\cdot wo n⋅wo(即下图中的 θ \theta θ) 为定值,不管我们选择下图中 w o 1 wo1 wo1还是 w o 2 wo2 wo2进行计算,采样 N N N个 w h j wh_j whj得到的期望 1 N ∑ j = 1 j = N ⋯ ∗ ( 1 − ( w h j ⋅ w o ) ) 5 ∗ … \frac{1}{N}\sum_{j=1}^{j=N}{\dots* (1-(wh_j\cdot wo))^5*\dots} N1∑j=1j=N⋯∗(1−(whj⋅wo))5∗… 就相等。
这说明,对于函数 F ( w h , w o , α ) F(wh,wo,\alpha) F(wh,wo,α),我们无需知道 w o wo wo 的真实值是多少,只需要知道 n ⋅ w o n\cdot wo n⋅wo,然后根据 n n n(在采样 w h wh wh时 n n n为 ( 0 , 1 , 0 ) (0,1,0) (0,1,0)或者 ( 0 , 0 , 1 ) (0,0,1) (0,0,1)等单位向量)任取一个 w o ′ wo' wo′,使得 n ⋅ w o ′ = n ⋅ w o n\cdot wo'=n \cdot wo n⋅wo′=n⋅wo,那么根据 w o ′ wo' wo′计算得到的 B R D F ( n p , w o ′ , α ) BRDF(n_p,wo',\alpha) BRDF(np,wo′,α)与目标值 B R D F ( n p , w o ′ , α ) BRDF(n_p,wo',\alpha) BRDF(np,wo′,α) 就相等。
因此,我们可以将 函数 F ( w h , w o , α ) F(wh,wo,\alpha) F(wh,wo,α),写成
F ( w h , w o , F 0 ) = F ( w h , w o ′ , F 0 ) , 其中 w o ′ 满足 n ⋅ w o ′ = n ⋅ w o (12) F(wh,wo,F0) = F(wh,wo',F0), 其中\ wo' 满足 n\cdot wo' = n\cdot wo \tag{12} F(wh,wo,F0)=F(wh,wo′,F0),其中 wo′满足n⋅wo′=n⋅wo(12)
那么根据公式(12),函数 F ( w h , w o , F 0 ) F(wh,wo,F0) F(wh,wo,F0) 的自变量就变为 w h wh wh, n ⋅ w o n\cdot wo n⋅wo(因为可以根据 n ⋅ w o n\cdot wo n⋅wo得到 w o ′ wo' wo′) 和 F 0 F_0 F0 了。
我们令:
F c ( w h , w o ) = ( 1 − ( w h ⋅ w o ) ) 5 F_{c}(wh,wo) = (1-(wh\cdot wo))^5 Fc(wh,wo)=(1−(wh⋅wo))5
那么:
F ( w h , n ⋅ w o , F 0 ) = F ( w h , n ⋅ w o , F 0 ) = F 0 ∗ ( 1.0 − F c ( w h , n ⋅ w o ) ) + F c ( w h , n ⋅ w o ) F(wh,n\cdot wo,F_0) = F(wh,n\cdot wo,F_0) = F_0 * (1.0-Fc(wh,n\cdot wo))+F_{c}(wh,n\cdot wo) F(wh,n⋅wo,F0)=F(wh,n⋅wo,F0)=F0∗(1.0−Fc(wh,n⋅wo))+Fc(wh,n⋅wo)
3.3.4 BRDF 项的简化
将 F ( w h , n ⋅ w o , F 0 ) F(wh,n\cdot wo,F_0) F(wh,n⋅wo,F0) 带入公式(10)中得到:
B R D F ( n p , w o , α ) = 1 N ∑ j = 1 j = N ( F 0 ∗ ( 1.0 − F c ( w h , n ⋅ w o ) ) + F c ( w h j , n ⋅ w o ) ) ∗ G ( n p , w o , w i j , α ) ∗ ( w h j ⋅ w o ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) = F 0 ∗ 1 N ∗ ∑ j = 1 j = N ( 1.0 − F c ( w h , n ⋅ w o ) ) ∗ G ( n p , w o , w i j , α ) ∗ ( w h j ⋅ w o ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) + 1 N ∗ ∑ j = 1 j = N F c ( w h j , n ⋅ w o ) ∗ G ( n p , w o , w i j , α ) ∗ ( w h j ⋅ w o ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) (13) BRDF(n_p,wo,\alpha) = \frac{1}{N}\sum_{j=1}^{j=N}{\frac{ \left (F_0 * (1.0-Fc(wh,n\cdot wo))+F_{c}(wh_j,n\cdot wo)\right )*G(n_p,wo,wi_j,\alpha)*(wh_j \cdot wo)}{(wo\cdot n_p)*(n_p\cdot wh_j)}} \\ = F_{0} * \frac{1}{N}*\sum_{j=1}^{j=N}{\frac{ (1.0-Fc(wh,n\cdot wo))*G(n_p,wo,wi_j,\alpha)*(wh_j \cdot wo)}{(wo\cdot n_p)*(n_p\cdot wh_j)}} + \frac{1}{N}*\sum_{j=1}^{j=N}{\frac{ F_{c}(wh_j,n\cdot wo)*G(n_p,wo,wi_j,\alpha)*(wh_j \cdot wo)}{(wo\cdot n_p)*(n_p\cdot wh_j)}} \tag{13} BRDF(np,wo,α)=N1j=1∑j=N(wo⋅np)∗(np⋅whj)(F0∗(1.0−Fc(wh,n⋅wo))+Fc(whj,n⋅wo))∗G(np,wo,wij,α)∗(whj⋅wo)=F0∗N1∗j=1∑j=N(wo⋅np)∗(np⋅whj)(1.0−Fc(wh,n⋅wo))∗G(np,wo,wij,α)∗(whj⋅wo)+N1∗j=1∑j=N(wo⋅np)∗(np⋅whj)Fc(whj,n⋅wo)∗G(np,wo,wij,α)∗(whj⋅wo)(13)
同样的根据前面的分析,由于我们是根据 p d f ( w h ) pdf(wh) pdf(wh)采样得到大量的 w h j wh_j whj,来计算上式,而且 p d f ( w h ) pdf(wh) pdf(wh) 函数在周向上是对称的,因此我们只要根据 n ⋅ w o n\cdot wo n⋅wo 确定任意一个 w o ′ wo' wo′,使得 n ⋅ w o ′ = n ⋅ w o n\cdot wo'=n\cdot wo n⋅wo′=n⋅wo 即可,无需使用 w o wo wo 计算上式。同时由于函数 G s u b ( n , w o , k ) = n ∗ w o ( n ∗ w o ) ( 1 − k ) + k G_{sub}\left(n,wo,k\right)=\frac{n\ast wo}{\left(n\ast wo\right)\left(1-k\right)+k} Gsub(n,wo,k)=(n∗wo)(1−k)+kn∗wo
因此函数 G ( n , w o , k ) = G ( n ⋅ w o , α ) G(n,wo,k)=G(n\cdot wo, \alpha) G(n,wo,k)=G(n⋅wo,α),
那么公式(13) 可以写成:
B R D F ( n p , w o , α ) = B R D F ( n p ⋅ w o , α ) = F 0 ∗ 1 N ∗ ∑ j = 1 j = N F s c a l e ( w h j , n ⋅ w o ) ∗ G ( n ⋅ w o , w i j , α ) ∗ ( w h j ⋅ w o ′ ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) ⏟ s c a l e + 1 N ∗ ∑ j = 1 j = N F b i a s ( w h j , n ⋅ w o ) ∗ G ( n p ⋅ w o , w i j , α ) ∗ ( w h j ⋅ w o ′ ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) ⏟ b i a s , 其中 w o ′ 可以根据 n p ⋅ w o 确定 (14) BRDF(n_p,wo,\alpha)= BRDF(n_p\cdot wo,\alpha) = F_{0} * \underbrace{\frac{1}{N}*\sum_{j=1}^{j=N}{\frac{ F_{scale}(wh_j,n\cdot wo)*G(n\cdot wo,wi_j,\alpha)*(wh_j \cdot wo')}{(wo\cdot n_p)*(n_p\cdot wh_j)}}}_{scale} + \underbrace{\frac{1}{N}*\sum_{j=1}^{j=N}{\frac{ F_{bias}(wh_j,n\cdot wo)*G(n_p\cdot wo,wi_j,\alpha)*(wh_j \cdot wo')}{(wo\cdot n_p)*(n_p\cdot wh_j)}}}_{bias}, 其中wo'可以根据n_p\cdot wo确定\tag{14} BRDF(np,wo,α)=BRDF(np⋅wo,α)=F0∗scale N1∗j=1∑j=N(wo⋅np)∗(np⋅whj)Fscale(whj,n⋅wo)∗G(n⋅wo,wij,α)∗(whj⋅wo′)+bias N1∗j=1∑j=N(wo⋅np)∗(np⋅whj)Fbias(whj,n⋅wo)∗G(np⋅wo,wij,α)∗(whj⋅wo′),其中wo′可以根据np⋅wo确定(14)
从公式(13) 可以看出,目标函数 BRDF 项是可以看作:
B R D F ( n p ⋅ w o , α ) = F 0 ∗ s c a l e ( n p ⋅ w o , α ) + b a i s ( n p ⋅ w o , α ) (15) BRDF(n_p\cdot wo,\alpha) = F_0 *scale(n_p\cdot wo,\alpha) + bais(n_p\cdot wo,\alpha) \tag{15} BRDF(np⋅wo,α)=F0∗scale(np⋅wo,α)+bais(np⋅wo,α)(15)
我们只要预计算得到 s c a l e ( n p ⋅ w o , α ) scale(n_p\cdot wo,\alpha) scale(np⋅wo,α) 和 b a i s ( n p ⋅ w o , α ) bais(n_p\cdot wo,\alpha) bais(np⋅wo,α) 两个二维的查找表,然后根据 目标着色点的 F 0 F_0 F0 即可得到 BRDF项。
其中:
s c a l e ( n p ⋅ w o , α ) = 1 N ∗ ∑ j = 1 j = N ( 1.0 − F c ( w h , n ⋅ w o ) ) ∗ G ( n ⋅ w o , w i j , α ) ∗ ( w h j ⋅ w o ′ ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) b a i s ( n p ⋅ w o , α ) = 1 N ∗ ∑ j = 1 j = N F c ( w h j , n ⋅ w o ) ∗ G ( n p ⋅ w o , w i j , α ) ∗ ( w h j ⋅ w o ′ ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) (16) scale(n_p\cdot wo,\alpha) = \frac{1}{N}*\sum_{j=1}^{j=N}{\frac{ (1.0-Fc(wh,n\cdot wo))*G(n\cdot wo,wi_j,\alpha)*(wh_j \cdot wo')}{(wo\cdot n_p)*(n_p\cdot wh_j)}} \\ bais(n_p\cdot wo,\alpha) = \frac{1}{N}*\sum_{j=1}^{j=N}{\frac{ F_{c}(wh_j,n\cdot wo)*G(n_p\cdot wo,wi_j,\alpha)*(wh_j \cdot wo')}{(wo\cdot n_p)*(n_p\cdot wh_j)}} \tag{16} scale(np⋅wo,α)=N1∗j=1∑j=N(wo⋅np)∗(np⋅whj)(1.0−Fc(wh,n⋅wo))∗G(n⋅wo,wij,α)∗(whj⋅wo′)bais(np⋅wo,α)=N1∗j=1∑j=N(wo⋅np)∗(np⋅whj)Fc(whj,n⋅wo)∗G(np⋅wo,wij,α)∗(whj⋅wo′)(16)
3.3.5 预计算 BRDF 项的代码实现
根据公式(16),计算 BRDF 项的代码如下,在代码中 F c ( w h , n ⋅ w o ) → F c Fc(wh,n\cdot wo)\rightarrow Fc Fc(wh,n⋅wo)→Fc, n p → N n_p\rightarrow N np→N, w o ′ → V wo'\rightarrow V wo′→V, w h → H wh\rightarrow H wh→H, w i → L wi\rightarrow L wi→L:
// ----------------------------------------------------------------------------
/**
input: n dot wo (NdotV), alpha (roughness)
output: scale(n dot wo,alpha), bias(n dot wo, roughness)
*/
vec2 IntegrateBRDF(float NdotV, float roughness)
{// 假设 N = (0,0,1)// 根据 N dot V,选择 V' = (sqrt(1.0 - NdotV*NdotV), 0, NdotV),// 可以保证 N dot V = N dot V'vec3 N = vec3(0.0, 0.0, 1.0);vec3 V;V.x = sqrt(1.0 - NdotV*NdotV);V.y = 0.0;V.z = NdotV;float scale = 0.0;float bias = 0.0; const uint SAMPLE_COUNT = 1024u;for(uint i = 0u; i < SAMPLE_COUNT; ++i){// generates a sample vector that's biased towards the// preferred alignment direction (importance sampling).vec2 Xi = Hammersley(i, SAMPLE_COUNT); // 生成一个 [0.0,1.0] 范围内的随机数vec3 H = ImportanceSampleGGX(Xi, N, roughness); // 根据重要性采样 pdf(wh) = D(wh)*(wh dot n) 采样 whvec3 L = normalize(2.0 * dot(V, H) * H - V); // 采样得到的 wh 对应的 wifloat NdotL = max(L.z, 0.0); // n dot wifloat NdotH = max(H.z, 0.0); // n dot whfloat VdotH = max(dot(V, H), 0.0); // wo dot whif(NdotL > 0.0){float G = GeometrySmith(N, V, L, roughness);float G_Vis = (G * VdotH) / (NdotH * NdotV);float Fc = pow(1.0 - VdotH, 5.0);scale += (1.0 - Fc) * G_Vis;bias += Fc * G_Vis;}}scale /= float(SAMPLE_COUNT);bias /= float(SAMPLE_COUNT);return vec2(scale, bias);
}
最终我们可以预计算不同 ( n p ⋅ w o , α ) (n_p\cdot wo,\alpha) (np⋅wo,α)输入时对应的 s c a l e ( n p ⋅ w o , α ) scale(n_p\cdot wo,\alpha) scale(np⋅wo,α) 和 b a i s ( n p ⋅ w o , α ) bais(n_p\cdot wo,\alpha) bais(np⋅wo,α),得到这两个 二维查找表后 根据公式(15) 得到 BRDF 项对应的值。
在代码实现时,往往将 s c a l e scale scale 和 b i a s bias bias 两个分量作为 ( r , g ) (r,g) (r,g) 分量,存储到一个 二维纹理中,得到的最终纹理结果如下所示:
3.4 pre_filtered项
3.4.1 pre_fileterd 项的定义
接下来介绍如何快速计算 公式 (3) 中 pre_filtered 项。根据公式(3)和公式(5)我们可以得到:
p r e _ f i l t e r e d ( n p , w o , α ) = L o ( n p , w o , α ) B R D F ( n p , w o , α ) = ∫ Ω n p f r ( w i , n , w o , α ) L i ( p , w i ) ∗ n ⋅ w i d w i ∫ Ω n p f r ( w i , n , w o , α ) ∗ n ⋅ w i d w i (17) pre\_filtered(n_p, wo, \alpha) = \frac{L_{o}\left(n_p,wo, \alpha \right)}{BRDF(n_p, wo, \alpha)} = \frac{\int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha) L i\left(p,wi\right)}\ast n\cdot wi\ dwi}{\int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)} * n\cdot wi\ dwi} \tag{17} pre_filtered(np,wo,α)=BRDF(np,wo,α)Lo(np,wo,α)=∫Ωnpfr(wi,n,wo,α)∗n⋅wi dwi∫Ωnpfr(wi,n,wo,α)Li(p,wi)∗n⋅wi dwi(17)
3.4.2 pre_fileterd 项的数值求解
根据 基于重要性采样的蒙特卡洛数值积分 可以得到:
p r e _ f i l t e r e d ( n p , w o , α ) = ∫ Ω n p f r ( w i , n , w o , α ) ∗ L i ( p , w i ) ∗ n ⋅ w i d w i ∫ Ω n p f r ( w i , n , w o , α ) ∗ n ⋅ w i d w i = ( 1 N ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ L i ( p , w i ) ∗ ( n ⋅ w i j ) p d f ( w i j ) ) / ( 1 N ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ ( n ⋅ w i j ) p d f ( w i j ) ) = ( ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ L i ( p , w i ) ∗ ( n ⋅ w i j ) p d f ( w i j ) ) / ( ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ ( n ⋅ w i j ) p d f ( w i j ) ) (17) pre\_filtered(n_p, wo, \alpha) = \frac{\int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)*L i\left(p,wi\right)}\ast n\cdot wi\ dwi}{\int_{\mathrm{\Omega_{np}}}{ fr(wi, n, wo, \alpha)} * n\cdot wi\ dwi} \\ = \left( \frac{1}{N}\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*L i\left(p,wi\right)*(n\cdot wi_j)}{pdf(wi_j)} \right) / \left( \frac{1}{N}\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*(n\cdot wi_j)}{pdf(wi_j)} \right) \\ = \left(\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*L i\left(p,wi\right)*(n\cdot wi_j)}{pdf(wi_j)} \right) / \left(\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*(n\cdot wi_j)}{pdf(wi_j)} \right) \tag{17} pre_filtered(np,wo,α)=∫Ωnpfr(wi,n,wo,α)∗n⋅wi dwi∫Ωnpfr(wi,n,wo,α)∗Li(p,wi)∗n⋅wi dwi=(N1j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗Li(p,wi)∗(n⋅wij))/(N1j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗(n⋅wij))=(j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗Li(p,wi)∗(n⋅wij))/(j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗(n⋅wij))(17)
其中 w i j wi_j wij 为我们根据概率密度分布函数 p d f ( w i j ) pdf(wi_j) pdf(wij) 采样得到的 w i wi wi 向量。与 求解 BRDF 项时类似,我们将
p d f ( w i ) = p d f ( w h ) ∗ 1 4 ( w h ⋅ w o ) = D ( n p , w h , α ) ∗ ( n ∗ w h ) ∗ 1 4 ( w h ⋅ w o ) pdf(wi) = pdf(wh)*\frac{1}{4(wh \cdot wo)} = D(n_p,wh,\alpha)*(n*wh) *\frac{1}{4(wh \cdot wo)} pdf(wi)=pdf(wh)∗4(wh⋅wo)1=D(np,wh,α)∗(n∗wh)∗4(wh⋅wo)1
代入公式(17)可以得到:
p r e _ f i l t e r e d ( n p , w o , α ) = ( ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ L i ( w i ) ∗ ( n ⋅ w i j ) p d f ( w i j ) ) / ( ∑ j = 1 j = N f r ( w i j , n , w o , α ) ∗ ( n ⋅ w i j ) p d f ( w i j ) ) = ( ∑ j = 1 j = N D ( n p , w h j , α ) ∗ F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ L i ( w i ) ∗ ( n ⋅ w i j ) 4 ∗ ( w o ⋅ n p ) ( w i j ⋅ n ) ∗ D ( n p , w h j , α ) ∗ ( n p ⋅ w h j ) ∗ 1 4 ( w h j ⋅ w o ) ) / ( ∑ j = 1 j = N D ( n p , w h j , α ) ∗ F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ ( n ⋅ w i j ) 4 ∗ ( w o ⋅ n p ) ( w i j ⋅ n ) ∗ D ( n p , w h j , α ) ∗ ( n p ⋅ w h j ) ∗ 1 4 ( w h j ⋅ w o ) ) = ( ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ L i ( w i ) ∗ ( w h j ⋅ w o ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) ) / ( ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( n p , w o , w i j , α ) ∗ ( w h j ⋅ w o ) ( w o ⋅ n p ) ∗ ( n p ⋅ w h j ) ) (18) pre\_filtered(n_p, wo, \alpha) = \left(\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*L i\left(wi\right)*(n\cdot wi_j)}{pdf(wi_j)} \right) / \left(\sum_{j=1}^{j=N}\frac{fr(wi_j,n,wo,\alpha)*(n\cdot wi_j)}{pdf(wi_j)} \right) \\ = \left(\sum_{j=1}^{j=N}\frac{\sout{D(n_p,wh_j,\alpha)}*F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*L i\left(wi\right)*\sout{(n\cdot wi_j)}}{\bcancel{4}*(wo\cdot n_p)\sout{(wi_j\cdot n)*D(n_p,wh_j,\alpha)}*(n_p\cdot wh_j) *\frac{1}{\bcancel{4}(wh_j \cdot wo)}} \right) / \left(\sum_{j=1}^{j=N}\frac{\sout{D(n_p,wh_j,\alpha)}*F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*\sout{(n\cdot wi_j)}}{\bcancel{4}*(wo\cdot n_p)\sout{(wi_j\cdot n)*D(n_p,wh_j,\alpha)}*(n_p\cdot wh_j) *\frac{1}{\bcancel{4}(wh_j \cdot wo)}} \right) \\ = \left(\sum_{j=1}^{j=N}\frac{F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*L i\left(wi\right)*(wh_j \cdot wo)}{(wo\cdot n_p)*(n_p\cdot wh_j)} \right) / \left(\sum_{j=1}^{j=N}\frac{F(wh_j,wo,F_0)*G(n_p,wo,wi_j,\alpha)*(wh_j \cdot wo)}{(wo\cdot n_p)*(n_p\cdot wh_j)} \right) \tag{18} pre_filtered(np,wo,α)=(j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗Li(wi)∗(n⋅wij))/(j=1∑j=Npdf(wij)fr(wij,n,wo,α)∗(n⋅wij))=(j=1∑j=N4 ∗(wo⋅np)(wij⋅n)∗D(np,whj,α)∗(np⋅whj)∗4 (whj⋅wo)1D(np,whj,α)∗F(whj,wo,F0)∗G(np,wo,wij,α)∗Li(wi)∗(n⋅wij))/(j=1∑j=N4 ∗(wo⋅np)(wij⋅n)∗D(np,whj,α)∗(np⋅whj)∗4 (whj⋅wo)1D(np,whj,α)∗F(whj,wo,F0)∗G(np,wo,wij,α)∗(n⋅wij))=(j=1∑j=N(wo⋅np)∗(np⋅whj)F(whj,wo,F0)∗G(np,wo,wij,α)∗Li(wi)∗(whj⋅wo))/(j=1∑j=N(wo⋅np)∗(np⋅whj)F(whj,wo,F0)∗G(np,wo,wij,α)∗(whj⋅wo))(18)
公式(18)依旧是一个比较复杂的公式,并且其输入自变量包含 n p , w o , α n_p, wo, \alpha np,wo,α 和 F 0 F0 F0,依旧不能满足建立一个预计算表达到快速计算的目的。
3.4.3 pre_filtered 项的简化
接下来将介绍一系列假设,以简化公式(18)。
首先,公式(18)中,除了 L i ( w i ) Li(wi) Li(wi)中的 w i wi wi根据实际的 n p n_p np和采样得到的 w h wh wh计算得到。假设其他部分的 n p n_p np 与 w o wo wo 相同,注意,这里是假设 n p n_p np等于wo(改变 n p n_p np),而不是假设wo等于n_p。
因为我们使用真实的 n p n_p np和 w h wh wh计算 w i wi wi,那么在pre_filetred 公式中 n p n_p np 的变化只影响函数 f r ( w i , w o , n p , α ) fr(wi,wo,n_p,\alpha) fr(wi,wo,np,α)。假设 n p = w o n_p=wo np=wo,即假设不同 n n n 时,着色点表面的 lobe形状不会发生变化(只是发生旋转)。(然而实际上 n p n_p np 的变化会影响 lobe 的形状)。如下图所示:
其中 l o b e ‾ \overline{lobe} lobe 可以理解为使用 L i ( w i ) = 1 Li(wi)=1 Li(wi)=1 时计算得到的绝对值, l o b e lobe lobe 为使用 IBL L i ( w i ) Li(wi) Li(wi) 计算得到的绝对值。
在假设 w o wo wo 与 n p n_p np 相同的条件下,公式(18) 可以写成:
p r e _ f i l t e r e d ( n p , w o , α ) = = ( ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( w o , w o , w i j , α ) ∗ L i ( w i j ) ∗ ( w h j ⋅ w o ) ( w o ⋅ w o ) ∗ ( w o ∗ w h j ) ) / ( ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( w o , w o , w i j , α ) ∗ ( w h j ⋅ w o ) ( w o ⋅ w o ) ∗ ( w o ∗ w h j ) ) = ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( w o , w o , w i j , α ) ∗ L i ( w i j ) ∑ j = 1 j = N F ( w h j , w o , F 0 ) ∗ G ( w o , w o , w i j , α ) (19) pre\_filtered(n_p, wo, \alpha) = = \left(\sum_{j=1}^{j=N}\frac{F(wh_j,wo,F_0)*G(wo,wo,wi_j,\alpha)*L i\left(wi_j\right)*(wh_j \cdot wo)}{(wo\cdot wo)*(wo*wh_j)} \right) / \left(\sum_{j=1}^{j=N}\frac{F(wh_j,wo,F_0)*G(wo,wo,wi_j,\alpha)*(wh_j \cdot wo)}{(wo\cdot wo)*(wo*wh_j)} \right) \\ = \frac{\sum_{j=1}^{j=N}{F(wh_j,wo,F_0)*G(wo,wo,wi_j,\alpha)*L i\left(wi_j\right)}}{ \sum_{j=1}^{j=N}{F(wh_j,wo,F_0)*G(wo,wo,wi_j,\alpha)}} \tag{19} pre_filtered(np,wo,α)==(j=1∑j=N(wo⋅wo)∗(wo∗whj)F(whj,wo,F0)∗G(wo,wo,wij,α)∗Li(wij)∗(whj⋅wo))/(j=1∑j=N(wo⋅wo)∗(wo∗whj)F(whj,wo,F0)∗G(wo,wo,wij,α)∗(whj⋅wo))=∑j=1j=NF(whj,wo,F0)∗G(wo,wo,wij,α)∑j=1j=NF(whj,wo,F0)∗G(wo,wo,wij,α)∗Li(wij)(19)
然后,由于 F ( ) F() F() 函数对结果的影响不大(此处只给出结论,不给出推导证明,读者可以参考深入理解 PBR/基于图像照明 (IBL)-3.2 speular。
可以将 F ( ) F() F()函数省略,那么公式(19)简化为:
p r e _ f i l t e r e d ( n p , w o , α ) = ∑ j = 1 j = N G ( w o , w o , w i j , α ) ∗ L i ( w i j ) ∑ j = 1 j = N G ( w o , w o , w i j , α ) (19) pre\_filtered(n_p, wo, \alpha) = \frac{\sum_{j=1}^{j=N}{G(wo,wo,wi_j,\alpha)*L i\left(wi_j\right)}}{ \sum_{j=1}^{j=N}{G(wo,wo,wi_j,\alpha)}} \tag{19} pre_filtered(np,wo,α)=∑j=1j=NG(wo,wo,wij,α)∑j=1j=NG(wo,wo,wij,α)∗Li(wij)(19)
最后,使用 ( n p ⋅ w i ) (n_p\cdot wi) (np⋅wi) 近似表示函数 G ( w o , w o , w i j , α ) G(wo,wo,wi_j,\alpha) G(wo,wo,wij,α),就得到的 pre_filtered 项的最终计算公式:
p r e _ f i l t e r e d ( n p , w o , α ) = ∑ j = 1 j = N ( n p ⋅ w i j ) ∗ L i ( w i j ) ∑ j = 1 j = N ( n p ⋅ w i j ) (20) pre\_filtered(n_p, wo, \alpha) = \frac{\sum_{j=1}^{j=N}{(n_p\cdot wi_j)*L i\left(wi_j\right)}}{ \sum_{j=1}^{j=N}{(n_p\cdot wi_j)}} \tag{20} pre_filtered(np,wo,α)=∑j=1j=N(np⋅wij)∑j=1j=N(np⋅wij)∗Li(wij)(20)
需要注意的是,上式中的 w i wi wi 是我们根据 n p n_p np、 w o wo wo和使用重要性采样中的 p d f ( w h ) pdf(wh) pdf(wh) 采样得到的 w h wh wh,计算得到的 w i wi wi,也就是说 { n p , w o , w h j } → { w i j } \{n_p, wo, wh_j\} \rightarrow{\{wi_j\}} {np,wo,whj}→{wij}。而 w o wo wo和 w h j wh_j whj是相对于 n p = ( 0 , 1 , 0 ) n_p=(0,1,0) np=(0,1,0)(或者 n p = ( 0 , 0 , 1 ) n_p=(0,0,1) np=(0,0,1))的局部坐标系的。
从下图中可以看出,只要 w r = r e f l e c t ( n p , w o ) wr=reflect(n_p,wo) wr=reflect(np,wo) 相同,那么在全局坐标系中根据 p d f ( w i ) pdf(wi) pdf(wi)采样得到的 w i wi wi 就相同。
上图中,黑色虚线的向量为采样得到的 w h j wh_j whj,绿色虚线的向量为对应的 w i j wi_j wij。
因此公式(20)可以写为:
p r e _ f i l t e r e d ( w r , α ) = ∑ j = 1 j = N ( n p ⋅ w i j ) ∗ L i ( w i j ) ∑ j = 1 j = N ( n p ⋅ w i j ) (21) pre\_filtered(wr, \alpha) = \frac{\sum_{j=1}^{j=N}{(n_p\cdot wi_j)*L i\left(wi_j\right)}}{ \sum_{j=1}^{j=N}{(n_p\cdot wi_j)}}\tag{21} pre_filtered(wr,α)=∑j=1j=N(np⋅wij)∑j=1j=N(np⋅wij)∗Li(wij)(21)
其中 w i j wi_j wij 为将 w r wr wr 视作 n p n_p np,基于 p d f ( w h ) pdf(wh) pdf(wh)采样得到 w h j wh_j whj,然后计算得到的 w i j wi_j wij。
我们可以预计算不同 ( w r , α ) (wr,\alpha) (wr,α)输入时对应的 p r e _ f i l t e r e d ( w r , α ) pre\_filtered(wr, \alpha) pre_filtered(wr,α),得到这二维查找表后 根据公式(21) 得到 pre_filtered 项对应的值。
3.4.4 预计算 pre_filtered 项的代码实现
根据公式(21),计算 pre_filtered 项的代码如下,在代码中 n p → N n_p\rightarrow N np→N, w r → R wr\rightarrow R wr→R, w o → V wo\rightarrow V wo→V, w h → H wh\rightarrow H wh→H, w i → L wi\rightarrow L wi→L:
/**
input: wr (WorldPos), alpha (roughness)
output: prefiltered(wr, roughness)
*/
void main()
{vec3 N = normalize(WorldPos); // 预计算时, wr = n// make the simplifying assumption that V equals R equals the normal vec3 R = N; // wr = nvec3 V = R; // wo = n = wrconst uint SAMPLE_COUNT = 1024u;vec3 prefilteredColor = vec3(0.0);float totalWeight = 0.0;for(uint i = 0u; i < SAMPLE_COUNT; ++i){// generates a sample vector that's biased towards the preferred alignment direction (importance sampling).vec2 Xi = Hammersley(i, SAMPLE_COUNT); // Xi 是一个 [0.0,1.0] 范围内部的随机数vec3 H = ImportanceSampleGGX(Xi, N, roughness); // H 是根据 pdf(wh) 采样得到的 wh_jvec3 L = normalize(2.0 * dot(V, H) * H - V); // 采样得到的 wh_j 对应的 wi_jfloat NdotL = max(dot(N, L), 0.0); // n_p * wi_jif(NdotL > 0.0){// sample from the environment's mip level based on roughness/pdf// 根据 roughness 从 environmentMap 不同的 mipmap 中采样,仅仅用于加速计算// 即使 environmentMap 不使用 mipmap, 如果采样数目足够大,也可以保证最终的 prefilteredColor 值收敛float D = DistributionGGX(N, H, roughness);float NdotH = max(dot(N, H), 0.0);float HdotV = max(dot(H, V), 0.0);float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; // pdf(wi_j)float resolution = 512.0; // resolution of source cubemap (per face)float saTexel = 4.0 * PI / (6.0 * resolution * resolution);float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL;totalWeight += NdotL;}}prefilteredColor = prefilteredColor / totalWeight;FragColor = vec4(prefilteredColor, 1.0);
}
3.5 总结
根据上面的分析,我们可以预计算得到两个查找表 p r e _ f i l t e r e d ( w r , α ) pre\_filtered(wr,\alpha) pre_filtered(wr,α), B R D F ( n ⋅ w o , α ) BRDF(n\cdot wo, \alpha) BRDF(n⋅wo,α)。前者只与 渲染场景中的光照贴图
有关,后者只与待渲染的模型
有关。在得到这两个查找表后,在渲染时对于目标点 n p n_p np的最终着色,可以根据公式(3)计算得到:
L o ( n p , w o , α ) = p r e _ f i l t e r e d ( w o , α ) ∗ B R D F ( n p ⋅ w o , α ) (3) L_{o}\left(n_p, wo, \alpha \right) = pre\_filtered(wo, \alpha) * BRDF(n_p\cdot wo, \alpha)\tag{3} Lo(np,wo,α)=pre_filtered(wo,α)∗BRDF(np⋅wo,α)(3)
三、全部代码及模型文件
使用OpenGL实现IBL漫反射+镜面反射 PBR的全部代码以及模型文件可以在OpenGL使用OpenGL实现基于物理的渲染模型PBR(下) 中下载。
下载源代码后使用以下命令编译运行:
mkdir build
cd build
cmake ..
make
./OpenGL_PBR
渲染结果如下:
四、参考
[1].LearnOpenGL-PBR-IBL-漫反射辐照
[2].深入理解 PBR/基于图像照明 (IBL)
[3].漫谈split sum approximate
[4].Alternative Take on the Split Sum Approximation for Cubemap Pre-filtering