在没有将辐射度量学引入计算机图形学中用于渲染之前程序员或者美术师们都是通过凭感觉或者经验调整Phong或者Blinn-Phong模型的参数,想做出非常精美的效果非常困难。
而且Phong和Blinn-Phong模型都是经验模型,它们都没办法表示真实的物理效果。因此我们引入了辐射度量学来以科学的角度定量地、物理正确地描述光。
辐射度量学# 辐射能(Radiant Energy)# 光本质上是电磁波,而只要是波就能携带能量。我们将光所携带的能量称为辐射能。
符号:Q Q Q , 单位:焦耳 J J J
辐射通量 (Radiant Flux)# 在图形学中我们通常不会使用辐射能 来计算光照,因为如果一个光源一直发光那么它释放的能量是无限变大的。
而在图形学中,我们更关注一帧画面中的能量。即辐射通量(Radiant Flux)
定义:单位时间内 Radiant Energy 的变化量
符号:Φ \Phi Φ
单位:瓦特 W W W ,或者焦耳每秒 J / s J/s J / s
公式:
Φ = d Q d t \Phi = \frac{dQ}{dt} Φ = d t d Q 立体角 (Solid Angle)# 在介绍其他的物理量之前先介绍一下立体角 ,因为这些物理量需要使用到立体角。
立体角是一个数学中的概念,类似于二维平面上,我们使用弧度表示来表示一个二维角度 θ = s r \theta = \frac{s}{r} θ = r s 。
类似的,在三维空间中,我们使用类似的定义来表示立体角。
(除以半径的平方对应了物理中的平方反比定律)
Ω = A r 2 \Omega = \frac{A}{r^2} Ω = r 2 A
单位: 球面度 (Steradian, sr)
例1:
计算整个球体和半球的立体角:
根据球体面积公式: A = 4 π r 2 A = 4\pi r^2 A = 4 π r 2
Ω 1 = A r 2 = 4 π r 2 r 2 = 4 π \Omega_1 = \frac{A}{r^2} = \frac{4\pi r^2}{r^2} = 4\pi Ω 1 = r 2 A = r 2 4 π r 2 = 4 π Ω 2 = Ω 1 2 = 2 π \Omega_2 = \frac{\Omega_1}{2}= 2\pi Ω 2 = 2 Ω 1 = 2 π 微分立体角# 在球体上我们通常使用经纬度来表示一个点的位置
极角 θ \theta θ :与 z z z 轴的夹角 [ 0 , π ] [0, \pi] [ 0 , π ]
方位角 ϕ \phi ϕ :在 x y xy x y 平面上的投影与 x x x 轴的夹角,范围 [ 0 , 2 π ] [0, 2\pi] [ 0 , 2 π ] 。
定义
d ω = d A r 2 d\omega = \frac{dA}{r^2} d ω = r 2 d A 其中
d A = ( r d θ ) ( r s i n θ d ϕ ) = r 2 s i n θ d θ d ϕ dA = (rd\theta)(rsin\theta d\phi) = r^2sin\theta d\theta d\phi d A = ( r d θ ) ( r s in θ d ϕ ) = r 2 s in θ d θ d ϕ
所以原公式可以化简为
d ω = s i n θ d θ d ϕ d\omega = sin\theta d\theta d\phi d ω = s in θ d θ d ϕ 例2
使用微分立体角计算半个球体的立体角:
Ω = ∫ S 2 d ω = ∫ 0 2 π ∫ 0 π 2 s i n θ d θ d ϕ = ∫ 0 π 2 s i n θ d θ ∫ 0 2 π d ϕ = [ − c o s θ ] 0 π 2 π = 2 π \Omega = \int_{S^2} d\omega=\int_{0}^{2\pi} \int_{0}^{\frac{\pi}{2}} sin\theta d\theta d\phi = \int_{0}^{\frac{\pi}{2}}sin\theta d\theta \int_{0}^{2\pi} d\phi = \left [ -cos\theta \right ] ^{\pi}_{0}2\pi = 2\pi Ω = ∫ S 2 d ω = ∫ 0 2 π ∫ 0 2 π s in θ d θ d ϕ = ∫ 0 2 π s in θ d θ ∫ 0 2 π d ϕ = [ − cos θ ] 0 π 2 π = 2 π (积分区域是矩形且被积函数是可分离的,所以可以化为两个独立定积分)
辐射强度(Radiant Intensity)# Radiant Flux描述的是光源向所有方向发射的总功率,但光源在不同方向发出的能量是不同的。辐射强度用于描述光源在特定方向上的发光能力。
定义:单位立体角内的 Radiant Flux 的变化率
符号:I I I
单位:瓦特每立体角 W / s r W/sr W / sr
公式:
I ( ω ) = lim Δ ω → 0 Δ Φ Δ ω = d Φ d ω I(\omega) =\lim_{\Delta\omega \to 0}\frac{\Delta \Phi}{\Delta \omega}= \frac{d\Phi}{d\omega} I ( ω ) = Δ ω → 0 lim Δ ω ΔΦ = d ω d Φ 如果一个光源是各项同性的,那么它的 Radiant Intensity 是 I = Φ 4 π I = \frac{\Phi}{4\pi} I = 4 π Φ (4 π 4\pi 4 π 是整个球的立体角)
辐照度(irradiance)# Irradiance 描述了某一个表面上接受的 Radiant Flux。
定义: 单位面积内的接受的 Radiant Flux 的变化率
符号:E E E
单位:瓦特每平方米 W / m 2 W/m^2 W / m 2
公式:
E ( p ) = lim Δ A → 0 Δ Φ ( p ) Δ A = d Φ ( p ) d A E(p) =\lim_{\Delta A \to 0}\frac{\Delta \Phi(p)}{\Delta A}= \frac{d\Phi(p)}{ dA} E ( p ) = Δ A → 0 lim Δ A ΔΦ ( p ) = d A d Φ ( p ) 辐射亮度 (Radiance)# 它结合了方向和面积,描述了光线在空间中沿一条射线的强度
定义: 单位立体角、单位投影面积上的辐射通量。
符号:L L L
单位:W s r ⋅ m 2 \frac{W}{sr\cdot m^2} sr ⋅ m 2 W
公式:
L ( p , ω ) = lim Δ ω → 0 Δ E ω ( p ) Δ ω = d E ω ( p ) d ω = d 2 Φ d ω d A L(p, \omega)= \lim_{\Delta\omega \to 0}\frac{\Delta E_{\omega}(p)}{\Delta \omega}=\frac{d E_{\omega}(p)}{d\omega}= \frac{d^2\Phi}{d\omega dA } L ( p , ω ) = Δ ω → 0 lim Δ ω Δ E ω ( p ) = d ω d E ω ( p ) = d ω d A d 2 Φ (其中 p p p 是表面上的点,ω \omega ω 是光线方向,θ \theta θ 是光线方向与表面法线的夹角)。
实际上 d A c o s θ dA cos\theta d A cos θ 才是radiance中所定义的面积
所以原方程为
L ( p , ω ) = d E ω ( p ) d ω c o s θ = d 2 Φ d ω d A c o s θ L(p, \omega)= \frac{d E_{\omega}(p)}{d\omega cos\theta}=\frac{d^2\Phi}{d\omega dA cos\theta} L ( p , ω ) = d ω cos θ d E ω ( p ) = d ω d A cos θ d 2 Φ
BRDF 双向反射分布函数# BRDF(双向反射分布函数,Bidirectional Reflectance Distribution Function)是计算机图形学和光学中用于描述光线在不透明表面如何反射的核心概念。它定义的物体的材质,描述了入射光是如何被反射到其他方向上去的。它的定义是:“在某个点上,在某个给定方向上反射出去的辐射能(Radiance),与 从某个给定方向入射的辐射照度(Irradiance) 之间的比例关系”。
根据其定义:
f r ( ω i , ω o ) = d L r ( ω o ) d E i ( ω i ) = d L r ( ω o ) L i ( ω i ) cos θ i d ω i f_r(\omega_i, \omega_o) = \frac{dL_r(\omega_o)}{dE_i(\omega_i)} = \frac{dL_r(\omega_o)}{L_i(\omega_i) \cos\theta_i d\omega_i} f r ( ω i , ω o ) = d E i ( ω i ) d L r ( ω o ) = L i ( ω i ) cos θ i d ω i d L r ( ω o )
ω i \omega_i ω i :入射光方向
ω o \omega_o ω o :反射光方向
d L r ( ω o ) dL_r(\omega_o) d L r ( ω o ) :表面在 ω o \omega_o ω o 方向反射出去的radiance
d E i ( ω i ) dE_i(\omega_i) d E i ( ω i ) :来自 ω i \omega_i ω i 方向的微分入射irradiance
θ i \theta_i θ i :入射光与表面法线的夹角
为什么要这么定义呢?我个人是这么理解的:物体所表现出来的材质是一种固有属性(从某个方向接受到的光能有多少反射到另外一个方向所以是比值,当irradiance增大2倍,那么反射出来的光也是原来的2倍,BRDF是不会变的),所表现出来的颜色是没有被物体所吸收出来的光,我们从不同角度观察物体所表现出来的“颜色”是不同的(radiance),并且与表面上接受入射光的角度、强度都有关(irradiance)。
反射方程# 有了 BRDF 那么我们就可以定义出反射方程了。很显然观察者接受到的物体的反射光是由不同方向上照射到物体表面经过材质反射的入射光贡献而来的。对 BRDF 方程两边同时乘以分子再对整个半球做积分就得到了:
L r ( ω o ) = ∫ S 2 f r ( ω i , ω o ) L i ( ω i ) cos θ i d ω i L_r( \omega_o) = \int_{S^2} f_r(\omega_i, \omega_o) L_i(\omega_i) \cos\theta_i d\omega_i L r ( ω o ) = ∫ S 2 f r ( ω i , ω o ) L i ( ω i ) cos θ i d ω i 由此我们可以根据这个方程计算出出射光了。
渲染方程# 渲染方程知识在反射方程的基础之上添加了一个自发光项(Emission term)
L o ( ω o ) = L e ( ω o ) + ∫ S 2 f r ( ω i , ω o ) L i ( ω i ) cos θ i d ω i L_o( \omega_o) = L_e( \omega_o) + \int_{S^2} f_r(\omega_i, \omega_o) L_i(\omega_i) \cos\theta_i d\omega_i L o ( ω o ) = L e ( ω o ) + ∫ S 2 f r ( ω i , ω o ) L i ( ω i ) cos θ i d ω i Cook-Torrance BRDF# 然而上面给出的是 BRDF 的定义式,我们不能使用它来计算,在工程上如果你非得使用上面那个式子进行计算的话那么你得对所有的像素进行预计算,将所有预计算的存入一个4维数组然后进行查表,这是绝对不可接受的。
所以我们需要一个解析模型从而便于我们的计算而 Cook-Torrance BRDF 就是最成功的一个,他是基于 微表面模型 的
微表面模型# 这是 Cook-Torrance 最核心的物理假设。它假设物体的表面在微观层面上都是由无数个以随机方向(实际上与材质有关)的镜面反射平面构成的。
当这些微小的镜面的法线方向较为集中一致的时候,从宏观角度来看,物体的镜面反射会比较明显。
当这些微小镜面的法线方向较为杂乱,分布均匀的时候,物体表面则会相对粗糙。
其中只有法线刚好指向入射光与观察者中间位置的微表面,才能把光线反射到你的眼睛里。这个中间位置的方向被称为半程向量 h = v + l ∥ v + l ∥ h = \frac{v + l}{\|v + l\|} h = ∥ v + l ∥ v + l
但是上面只解释了镜面反射现象,对于漫反射则是在镜面反射的基础上加上了折射。
当光照射到漫反射物体时,一部分会与微表面镜面进行反射,而一部分会发生折射进入物体内部与物体内部的原子不断发生碰撞并散射到随机方同时消耗光的能量。
Cook-Torrance BRDF正是考虑了这两种情形的BRDF,它的定义如下:
f r = k d f l a m b e r t + k s f c o o k − t o r r a n c e f_r = k_d f_{lambert} + k_s f_{cook-torrance} f r = k d f l amb er t + k s f coo k − t or r an ce
k d k_d k d 有多少比例发生了漫反射
k s k_s k s 有多少比例发生了镜面反射
并且由能量守恒 k d + k s ≤ 1.0 k_d + k_s \leq 1.0 k d + k s ≤ 1.0
f l a m b e r t f_{lambert} f l amb er t :漫反射 BRDF
f c o o k − t o r r a n c e f_{cook-torrance} f coo k − t or r an ce :镜面反射 BRDF
既然我们说 Cook-Torrance BRDF 便于计算,那么f l a m b e r t f_{lambert} f l amb er t ,f c o o k − t o r r a n c e f_{cook-torrance} f coo k − t or r an ce 是怎么计算的呢?
漫反射项推导# 漫反射会均匀的向每个方向反射,一个理想漫反射表面,在任何观察方向 ω o \omega_o ω o 看到的 radiance 都是相同的,所以 BRDF 将会是一个常数,
根据反射方程:
L r ( ω o ) = ∫ S 2 f r ( ω i , ω o ) L i ( ω i ) cos θ i d ω i L_r( \omega_o) = \int_{S^2} f_r(\omega_i, \omega_o) L_i(\omega_i) \cos\theta_i d\omega_i L r ( ω o ) = ∫ S 2 f r ( ω i , ω o ) L i ( ω i ) cos θ i d ω i L r = f r L i ∫ 0 2 π ∫ 0 π 2 c o s θ i d ω i = f r L i π L_r = f_rL_i\int_{0}^{2\pi}\int_{0}^{\frac{\pi}{2}}cos\theta_i d\omega_i = f_rL_i\pi L r = f r L i ∫ 0 2 π ∫ 0 2 π cos θ i d ω i = f r L i π 设反射率为 ρ \rho ρ 有 L r = ρ L i L_r = \rho L_i L r = ρ L i
则
f r = ρ π f_r = \frac{\rho}{\pi} f r = π ρ 镜面反射项推导# 我们先给出镜面反射项的 BRDF 的公式:
f s p e c u l a r = D ⋅ F ⋅ G 4 ( n ⋅ l ) ( n ⋅ v ) f_{specular} = \frac{D \cdot F \cdot G}{4(\mathbf{n} \cdot \mathbf{l})(\mathbf{n} \cdot \mathbf{v})} f s p ec u l a r = 4 ( n ⋅ l ) ( n ⋅ v ) D ⋅ F ⋅ G 法线分布函数 D D D (Normal Distribution Function, NDF)# 法线分布函数 D D D 的物理意义是描述微面元法线的统计分布,它表示在微观表面上,有多少比例的微面元的法线 m m m 是与半程向量 h h h 一致的。
如果表面很光滑:绝大多数微面元的法线都集中在宏观表面法线 n n n 的附近。这会导致 NDF 在 h h h 接近 n n n 时给出一个极高的值,从而产生非常小且非常明亮的高光。
如果表面很粗糙:微面元的法线分布非常杂乱、广泛。这意味着在任何给定的 h h h 方向上,都有一定数量的微面元。这会导致 NDF 的值比较平缓,从而产生面积大且相对暗淡的高光。
D ( m ) D(m) D ( m ) 的严格定义是:单位立体角内、单位宏观面积上,法线朝向 m m m 的微面元的真实面积
即
D ( m ) = d A m d A d ω m D(m) = \frac{dA_m}{dAd\omega_m} D ( m ) = d A d ω m d A m
A m A_m A m : 微面元微观面积
A A A :微面元宏观面积
ω m \omega_m ω m :立体角
然而这个是 NDF 的定义式,我们无法直接计算。
为了保证物理上的能量守恒,任何合格的 NDF 都必须满足微面元投影面积等于宏观表面投影面积的条件
即
∫ Ω D ( m ) ( n ⋅ m ) d ω m = 1 \int_{\Omega} D(m) (n \cdot m) d\omega_m = 1 ∫ Ω D ( m ) ( n ⋅ m ) d ω m = 1 如果不满足这个条件,例如:如果微面元投影面积大于宏面投影面积,意味着微面元无中生有地多出了一部分面积去接收和反射光线。这会导致表面反射出的光线数量,多于光源打在宏观表面上的光线数量——这就如同表面自带了发电机,违反了能量守恒定律。
推导:
一个微元的投影面积 = d A m ⋅ ( n ⋅ m ) = D ( m ) ⋅ d A ⋅ ( n ⋅ m ) ⋅ d ω m 一个微元的投影面积 = dA_m \cdot (n \cdot m) = D(m) \cdot dA \cdot (n \cdot m) \cdot d\omega_m 一个微元的投影面积 = d A m ⋅ ( n ⋅ m ) = D ( m ) ⋅ d A ⋅ ( n ⋅ m ) ⋅ d ω m 这是一个微元的投影面积,我们对它在半球上积分
所有微元的投影面积 = ∫ Ω D ( m ) ⋅ d A ⋅ ( n ⋅ m ) d ω m 所有微元的投影面积 = \int_{\Omega} D(m) \cdot dA \cdot (n \cdot m) d\omega_m 所有微元的投影面积 = ∫ Ω D ( m ) ⋅ d A ⋅ ( n ⋅ m ) d ω m 我们让它等于宏观面积
∫ Ω D ( m ) ⋅ d A ⋅ ( n ⋅ m ) d ω m = d A \int_{\Omega} D(m) \cdot dA \cdot (n \cdot m) d\omega_m = dA ∫ Ω D ( m ) ⋅ d A ⋅ ( n ⋅ m ) d ω m = d A d A dA d A 约去得到
∫ Ω D ( m ) ( n ⋅ m ) d ω m = 1 \int_{\Omega} D(m) (n \cdot m) d\omega_m = 1 ∫ Ω D ( m ) ( n ⋅ m ) d ω m = 1 这里给出一个 NDF 的计算式: GGX (Trowbridge-Reitz) 分布 这是目前游戏引擎和影视特效界绝对的工业标准
D G G X ( m ) = α 2 π ( ( n ⋅ m ) 2 ( α 2 − 1 ) + 1 ) 2 D_{GGX}(m) = \frac{\alpha^2}{\pi \left( (n \cdot m)^2 (\alpha^2 - 1) + 1 \right)^2} D GGX ( m ) = π ( ( n ⋅ m ) 2 ( α 2 − 1 ) + 1 ) 2 α 2
其中α \alpha α 为 粗糙度(Roughness)
n n n 为宏观法线方向
m m m 为微面元法线方向
我们可以通过能量守恒式子验证一下(保姆式)
I = ∫ Ω D G G X ( m ) c o s θ d ω I = \int_{\Omega}D_{GGX}\left(m\right)cos\theta d\omega I = ∫ Ω D GGX ( m ) cos θ d ω 代入
I = ∫ Ω α 2 π ( ( n ⋅ m ) 2 ( α 2 − 1 ) + 1 ) 2 c o s θ d ω I=\int_{\Omega}\frac{\alpha^2}{\pi\left ( \left( n\cdot m\right)^{2} \left( \alpha^2-1\right)+1\right )^2 }cos\theta d\omega I = ∫ Ω π ( ( n ⋅ m ) 2 ( α 2 − 1 ) + 1 ) 2 α 2 cos θ d ω 展开
I = ∫ 0 2 π ∫ 0 π 2 α 2 c o s θ s i n θ π ( ( α 2 − 1 ) c o s 2 θ + 1 ) 2 d θ d ϕ I=\int_{0}^{2\pi}\int_{0}^{\frac{\pi}{2}}\frac{\alpha^2cos\theta sin\theta}{\pi\left ( \left( \alpha^2-1\right)cos^2\theta+1\right )^2 } d\theta d\phi I = ∫ 0 2 π ∫ 0 2 π π ( ( α 2 − 1 ) co s 2 θ + 1 ) 2 α 2 cos θ s in θ d θ d ϕ 积分区域是矩形且被积函数是可分离的,拆分积分,并将常数项提出
I = α 2 π ∫ 0 2 π d ϕ ∫ 0 π 2 c o s θ s i n θ ( ( α 2 − 1 ) c o s 2 θ + 1 ) 2 d θ I=\frac{\alpha^2}{\pi}\int_{0}^{2\pi}d\phi\int_{0}^{\frac{\pi}{2}}\frac{ cos\theta sin\theta}{\left ( \left( \alpha^2-1\right)cos^2\theta+1\right )^2 } d\theta I = π α 2 ∫ 0 2 π d ϕ ∫ 0 2 π ( ( α 2 − 1 ) co s 2 θ + 1 ) 2 cos θ s in θ d θ 对 d ϕ d\phi d ϕ 的积分为2 π 2\pi 2 π 我们将 2 在放入积分中π \pi π 约掉
I = α 2 ∫ 0 π 2 2 c o s θ s i n θ ( ( α 2 − 1 ) c o s 2 θ + 1 ) 2 d θ I=\alpha^2\int_{0}^{\frac{\pi}{2}}\frac{2 cos\theta sin\theta}{\left ( \left( \alpha^2-1\right)cos^2\theta+1\right )^2 } d\theta I = α 2 ∫ 0 2 π ( ( α 2 − 1 ) co s 2 θ + 1 ) 2 2 cos θ s in θ d θ 分母有一个 c o s 2 θ cos^2\theta co s 2 θ ,注意到 c o s 2 θ cos^2\theta co s 2 θ 的导数是 − 2 c o s θ s i n θ -2cos\theta sin\theta − 2 cos θ s in θ ,所以我们可以凑微分
I = − α 2 ∫ 0 π 2 1 ( ( α 2 − 1 ) c o s 2 θ + 1 ) 2 d c o s 2 θ I=-\alpha^2\int_{0}^{\frac{\pi}{2}}\frac{1}{\left ( \left( \alpha^2-1\right)cos^2\theta+1\right )^2 } dcos^2\theta I = − α 2 ∫ 0 2 π ( ( α 2 − 1 ) co s 2 θ + 1 ) 2 1 d co s 2 θ 现在的积分变得非常简单了,继续凑微分
I = − α 2 α 2 − 1 ∫ 0 π 2 1 ( ( α 2 − 1 ) c o s 2 θ + 1 ) 2 d ( ( α 2 − 1 ) c o s 2 θ + 1 ) I=-\frac{\alpha^2}{ \alpha^2-1}\int_{0}^{\frac{\pi}{2}}\frac{1}{\left ( \left( \alpha^2-1\right)cos^2\theta+1\right )^2 } d\left(\left( \alpha^2-1\right)cos^2\theta+1\right) I = − α 2 − 1 α 2 ∫ 0 2 π ( ( α 2 − 1 ) co s 2 θ + 1 ) 2 1 d ( ( α 2 − 1 ) co s 2 θ + 1 ) 最后得到
I = α 2 α 2 − 1 [ 1 ( α 2 − 1 ) c o s 2 θ + 1 ] 0 π 2 = α 2 α 2 − 1 [ 1 − 1 α 2 ] = 1 I=\frac{\alpha^2}{ \alpha^2-1}\left [ \frac{1}{\left ( \alpha^2-1 \right )cos^2\theta +1} \right ]_{0}^{\frac{\pi}{2}}=\frac{\alpha^2}{ \alpha^2-1}\left [ 1-\frac{1}{\alpha^2} \right ] =1 I = α 2 − 1 α 2 [ ( α 2 − 1 ) co s 2 θ + 1 1 ] 0 2 π = α 2 − 1 α 2 [ 1 − α 2 1 ] = 1 菲涅尔方程(Fresnel Equation,F F F )# 菲涅尔反射:你可以做个实验感受一下这个现象,如果你垂直于一块玻璃看向外面,那么你可以很轻松地看到外面的景色,如果你接近于平行的角度去看,则大概率你能看到你那张帅气/美丽的脸,这种反射强度随观察角度(入射角)变化的现象,就是菲涅尔效应。
从物理学上讲,菲涅尔方程描述了光在两种不同折射率(n 1 , n 2 n_1, n_2 n 1 , n 2 )的介质交界面上的反射比例。完整的物理公式非常复杂,涉及光的横电波和横磁波等非常复杂的概念,这里只做简单的介绍,不需要掌握。
横电波
R s = ∣ n 1 cos θ i − n 2 cos θ t n 1 cos θ i + n 2 cos θ t ∣ 2 R_s = \left| \frac{n_1\cos\theta_i - n_2\cos\theta_t}{n_1\cos\theta_i + n_2\cos\theta_t} \right|^2 R s = n 1 cos θ i + n 2 cos θ t n 1 cos θ i − n 2 cos θ t 2 横磁波
R p = ∣ n 1 cos θ t − n 2 cos θ i n 1 cos θ t + n 2 cos θ i ∣ 2 R_p = \left| \frac{n_1\cos\theta_t - n_2\cos\theta_i}{n_1\cos\theta_t + n_2\cos\theta_i} \right|^2 R p = n 1 cos θ t + n 2 cos θ i n 1 cos θ t − n 2 cos θ i 2 菲涅尔方程
F = R s + R p 2 F = \frac{R_s + R_p}{2} F = 2 R s + R p
这个式子太复杂了不适合在计算机图形学中用于实时计算(也许离线渲染中可以使用,暂未了解)。
所以在实时渲染中,我们一般使用 Schlick 近似 公式来计算菲涅尔项
1994 年,Christophe Schlick 提出了一个极其经典的近似公式,它用一个简单的插值函数取代了复杂的三角函数和折射率计算
F S c h l i c k ( v , h ) = F 0 + ( 1 − F 0 ) ( 1 − ( v ⋅ h ) ) 5 F_{Schlick}(v, h) = F_0 + (1 - F_0)(1 - (v \cdot h))^5 F S c h l i c k ( v , h ) = F 0 + ( 1 − F 0 ) ( 1 − ( v ⋅ h ) ) 5
F 0 F_0 F 0 基础反射率,当观察方向垂直于表面时的反射能量。这是材质的固有属性
v v v 观察方向
h h h 半程向量
几何函数(Geometry Function,G G G )# 微表面模型假设表面是由无数的微小高低分布不同的微元镜面组成的。当光线以很斜的角度射入,或者你以很斜的角度观察时,就会发生两种几何现象
Shadowing :光线还没打到某个微面元,就被它前面的微元面挡住了,形成微观阴影
Masking : 微面元反射了光线,但在飞向你眼睛的途中,被旁边其他的微面元挡住了
如果没有几何函数,那么在物体的边缘会变得异常明亮,因为没有处理Shadowing和Masking现象。而 G G G 项的作用就是通过一个 0 ∼ 1 0 \sim 1 0 ∼ 1 之间的系数,把那些被挡住的光“扣掉”。
G G G 项本质上是一个概率:它表示在给定入射方向 l l l 和出射方向 v v v 的情况下,法线为 m m m 的微面元既不被遮蔽也不被掩盖的比例。
G ( l , v , h ) = G 1 ( l ) ⋅ G 1 ( v ) G(l, v, h) = G_1(l) \cdot G_1(v) G ( l , v , h ) = G 1 ( l ) ⋅ G 1 ( v )
G 1 ( l ) G_1(l) G 1 ( l ) :由于入射光被Shadowing而损失的能量
G 1 ( v ) G_1(v) G 1 ( v ) :由于视线被Masking而看不到的能量
我们工业中通常使用Schlick-GGX 几何函数 来计算:
G 1 ( v ) = n ⋅ v ( n ⋅ v ) ( 1 − k ) + k G_1(v) = \frac{n \cdot v}{(n \cdot v)(1 - k) + k} G 1 ( v ) = ( n ⋅ v ) ( 1 − k ) + k n ⋅ v G 1 ( l ) = n ⋅ l ( n ⋅ l ) ( 1 − k ) + k G_1(l) = \frac{n \cdot l}{(n \cdot l)(1 - k) + k} G 1 ( l ) = ( n ⋅ l ) ( 1 − k ) + k n ⋅ l 其中k k k 为:
k = ( R o u g h n e s s + 1 ) 2 8 k = \frac{(Roughness + 1)^2}{8} k = 8 ( R o ug hn ess + 1 ) 2 G 项会与BRDF的分母产生非常奇妙的反应,分母中当观察角度和光照角度趋近 90 度的时候 ( n ⋅ l ) (n \cdot l) ( n ⋅ l ) 或 ( n ⋅ v ) (n \cdot v) ( n ⋅ v ) 会趋近于 0 0 0 会导致BRDF的高光项非常的大,导致边缘处亮度爆炸亮,而 G 项的的两个分母刚好可以与分子约去从而防止这个现象。
再看 BRDF# f r = k d f l a m b e r t + k s f c o o k − t o r r a n c e f_r = k_d f_{lambert} + k_s f_{cook-torrance} f r = k d f l amb er t + k s f coo k − t or r an ce 这个形式是理论教科书式这种写法为了强调“能量守恒”的概念,手动指定 k s k_s k s 和 k d k_d k d 。
但是在工程实践中我们通常使用下面这种形式
f r = ( 1 − F ) ⋅ ( 1 − m e t a l l i c ) ⋅ f l a m b e r t + f s p e c u l a r f_r = (1 - F) \cdot (1 - metallic)\cdot f_{lambert} + f_{specular} f r = ( 1 − F ) ⋅ ( 1 − m e t a l l i c ) ⋅ f l amb er t + f s p ec u l a r f s p e c u l a r f_{specular} f s p ec u l a r 中的 F F F 直接充当了 k s k_s k s 的角色。如果你在 f s f_s f s 前面再乘一个 k s k_s k s ,就相当于“收了两遍税”,会导致高光能量过暗。