【基于物理的渲染(2)】Cook-Torrance

本文最后更新于 2025年5月8日 晚上

【基于物理的渲染(2)】Cook-Torrance

BRDF

BRDF 直译为双向散射分布函数,是一种解释光反射强度的模型。双向散射是指其将反射光描述为由镜射光和漫射光两种。基于物理的 BRDF 说明该公式不能是传统的经验模型,而是遵循各种物理现象而设计的模型。

漫射光

漫射光是指光线射入物体内部,在内部多次反弹后返回的光,这类光容易被物体吸收,且反射的方向无序,因此反光将均匀的分布在照射区域。

镜射光

镜射光是指光线仅触碰表面一次就反射的光,这种光与多种系数有关,例如表面的光滑度,观察的角度等,故光斑可变,且有可能发生一定的全反射(光未被表面吸收)。

Cook-Torrance

CookTorrance 是最常用的基于物理的 BDRF,相比过去的一些经验模型,它的效果更加真实,符合物理规律。CookTorrance 中有很多过去 Lambert 和 Phong 的影子,可以说就是由它们为基础慢慢发展出的新时代光照模型,也是目前主流的光照模型。

微表面属性

从Phong开始就有了考虑不同表面光泽度而显示不同高光的效果,Cook-Torrance也不例外,用其计算光照,需先提供一些微表面属性信息。

  • albedo(反射率):决定了物体表面对不同波段光的反射率(不被吸收率,也可简单理解为物体表面颜色)。
  • metallic(金属度):控制漫射光和镜射光之间的比例,以及镜射光颜色。金属度越高,漫射越少,镜射越多,镜射颜色越接近物体表面颜色。
  • smoothness(光滑度):物体表面的光滑程度,用于控制镜射光的形状特征。

基本公式结构

基本的 CookTorrrance 光照模型结构如下:

CookTorrance=kd+ksfsCookTorrance = k_d + k_s * f_s

  • kdk_d:表面对每单位漫射光的反射率。
  • ksk_s:表面对每单位镜射光的反射率。
  • fsf_s:镜射系数,表示有多少光会被直接反射进眼睛。

反射率计算

根据能量守恒 kd+ks=1k_d+k_s=1,而两者之间的权重分配则采用金属度系数决定:

kd=lerp(1,0,metallic)ks=lerp(0,1,metallic)k_d = lerp(1,0,metallic) \\ k_s = lerp(0,1,metallic)

但现实中的一般物体是不可能全漫射的,即使是黑色表面,遇到强光也会反射出镜射光,因此需要提供一定的保底全反射,该全反射的系数一般为 0.04(标准介电镜面反射):

kd=lerp(0.96,0,metallic)ks=lerp(0.04,1,metallic)k_d = lerp(0.96,0,metallic) \\ k_s = lerp(0.04,1,metallic)

反射光的光不一定和入射光颜色一样,因为很多物体的表面也会吸收部分波段的光,因此计算时还需要考虑表面的基础反照率(表面颜色):

kd=lerp(0.96albedo,0,metallic)ks=lerp(0.04,1albedo,metallic)k_d = lerp(0.96 * albedo,0,metallic) \\ k_s = lerp(0.04,1 * albedo,metallic)

镜射系数计算

镜射系数的计算公式如下:

fs=DGF4(NL)(NV)f_s = \frac{D*G*F}{4(N \cdot L)(N \cdot V)}

  • NN:法线方向
  • LL:光源方向
  • VV:相机方向

在部分资料中该公式的分母系数 (NLm)(NV)(N \cdot L_m)_(N \cdot V) 可能会被去除,因为这部分可以被 GG 中的分子约分。但如果不去除的话,可以确保 G[0,1]G \in [0,1],直观上看,这样会更能表现公式的物理效果。

其中 D、G、F 是三个可插拔的系数,用于反应 3 种物理现象。可插拔意味着它们是可以更换的,有多种计算方式可供选择,因此可以以此实现渲染效果的定制。

此外 D、G 的计算依赖一个新的系数叫粗糙度,粗糙度可以通过物体表面的光滑度计算得出:

a=(1smoothness)2a = (1-smoothness)^2

法线分布

D 描述表面法线分布情况,具体而言它决定了镜面高光的光斑形状。下述是使用 GGX 计算 D 的方法:

  • H=normalize(L+V)H=\operatorname{normalize}(L+V):半角向量的缩写。

DGGX=a2π((HN)2(a21)+1)2D_{GGX} = \frac{a^2}{\pi((H\cdot N)^2(a^2-1)+1)^2}

其中 π\pi 是为了归一化,使其光亮的总和符合能量守恒,但有些地方(如 Unity)会故意去掉该项。

几何遮蔽

G 用于表现微表面之间的遮挡导致的光线衰减现象,这在粗糙的表面尤为明显。下述是使用 Smith 计算 G 的方法:

GSmith=(NL)lerp(NL,1,k)(NV)lerp(NV,1,k)G_{Smith} = \frac{(N \cdot L)}{lerp(N \cdot L,1,k)} *\frac{(N \cdot V)}{lerp(N \cdot V,1,k)}

k=(a+1)28(直接光)或a22(间接光)k=\frac{(a+1)^2}{8}(直接光) 或 \frac{a^2}{2}(间接光)

从中可以观察到:

  • 光线入射角或观察角度与表面越垂直,光线被遮挡的概率越小。
  • 越光滑的表面,光线被遮挡的概率越小。
  • 对于直接光始终会被吸收一部分,而环境光可以全反射。

此外还有一种效果接近,但性能更好的方法:

GSKSm=(NL)(NV)lerp((LH)2,1,a)G_{SKSm}=\frac{(N \cdot L)(N \cdot V)}{lerp((L \cdot H)^2,1,a)}

菲涅尔效应

F 表示一个 0-1 的光线反射率,反应的是现实中的菲涅尔效应,描述了不同折射率的物体在不同观察角度下反射光线不同的特点。一般它的公式采用如下近似值:

F=lerp((1(VN))5,1,F0)F = lerp((1-(V \cdot N))^5,1,F_0)

F0=(r1)2(r+1)2F_0 = \frac{(r-1)^2}{(r+1)^2}

  • F0F_0:法向反射率。
  • rr:折射率。

从中可以观察到以下几种现象:

  • 折射率越高,菲涅尔效应越明显(如水面)。
  • 菲涅尔效应发生时,物体正面反射光线少(能透过湖面看到底),掠角反射光线多(湖面变不透明)。
  • 折射率为 0,没有菲涅尔效应,发生全反射。

不过上述菲涅尔公式只能用于透明物体,因为它会使物体表面反射为 0。对于不透明物体,可以需要采用另一种系数计算方法:

F0=ksF_0 = k_s

不过该方法将菲涅尔函数的输出由标量改为了向量,且携带了镜射光的反射率信息,因此要修改 CookTorrance 公式,使镜射光部分不要再乘 ksk_s 了(kd+ksfskd+fsk_d+k_sf_s \to k_d+f_s)。

Unity 中的镜射系数计算

https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_renaldas_2D00_notes.pdf

Unity 中对于镜射系数的计算公式如下:

D=a2((HN)2(a21)+1)2GF=1(LH)2(a+0.5)fs=DGF4\begin{aligned} D &= \frac{a^2}{((H \cdot N)^2(a^2-1)+1)^2} \\ \\ G*F &= \frac{1}{(L \cdot H)^2(a+0.5)}\\ \\ f_s &= \frac{D * G * F}{4} \end{aligned}

其中 DD 就是 DGGXD_{GGX} 方法,但去掉了用于归一化的 π\pi ,使画面更亮。

GFG*F 是拟合的近似公式。在原始公式中,GG 使用的是 GSKSmG_{SKSm},但 FF 的公式不清楚,因为原始公式和最终公式的效果并不相同。

(NL)(NV)(N \cdot L)(N \cdot V)被从分子分母中约分以加快速度。

参考资料


【基于物理的渲染(2)】Cook-Torrance
https://bdffzi-blog.pages.dev/posts/1881413206.html
作者
BDFFZI
发布于
2025年5月7日
许可协议