Phong 光照模型
设观察方向 VVV ,光源方向 LLL ,法线方向 NNN 。三者都是归一化后的单位向量,则可以计算出反射方向。
R=Reflect(−L,N)
R = Reflect(-L,N)
R=Reflect(−L,N)
Phong 模型在分为环境光、漫反射项和高光项。其中环境光可以视为平行光,只需要计算一定比例的光照强度即可。
L=La+Ld+Ls
L = L_a+L_d+L_s
L=La+Ld+Ls
Lambient=kaIa L_{ambient} = k_aI_a Lambient=kaIa
漫反射项则跟着色点与光源的距离 DDD 的平方,即衰减项,以及光源方向和法线方向的夹角余弦相关。
Fatt=1D2
F_{att} = \frac{1}{D^2}
Fatt=D21
Ldiffuse=kdFattmax(0,N⋅L)
L_{diffuse} = k_d F_{att} \max{(0,N \cdot L)}
Ldiffuse=kdFattmax(0,N⋅L)
高光项同样跟着色点与光源的距离 DDD 的平方相关,且越靠近光源方向则反射的高光越强、越集中,即高光项和光源方向和法线方向的夹角余弦相关,同时为了模拟距离越远越快速衰减,需要给夹角余弦加上指数 ppp 作为反光度。
Lspecular=ksFattmax(0,L⋅R)p
L_{specular} = k_s F_{att}\max{(0,L \cdot R)}^{p}
Lspecular=ksFattmax(0,L⋅R)p
实际上使用距离的平方作为衰减项也不符合人眼的实际感受,为了模拟人的视觉效果,可以对衰减项引入常数项和线性项。至于各项系数的取值,这属于经验数值,可以查表得到。
Fatt=1Kc+Kl∗D+Kq∗D2
F_{att}=\frac{1}{K_{c}+K_{l} * D+K_{q} * D^{2}}
Fatt=Kc+Kl∗D+Kq∗D21
此外,如果采用不同的着色法,最终取得的光照效果是不同的,显然更好的效果需要更多的性能进行计算。如 Flat 着色法只使用面法线进行计算光照的 Phong 光照模型,导致每个面之间非常分明。而 Gouraud 着色法在顶点着色器中进行计算光照的 Phong 光照模型,相对 Flat 着色法效果好了一些。而 Phong 着色法则是经过插值后,在片元着色器中计算三角形内每一个片元的光照,其光照效果自然更加的平滑。
Blinn-Phong 光照模型
Phong 模型在计算高光项时,使用反射方向和观察方向的夹角余弦,而 Blinn-Phong 模型在计算高光项时,先计算出入射方向和观察方向的半程向量(单位化的二者之和向量),然后计算半程向量和法向量的夹角余弦。
H=V+L∥V+L∥
H = \frac{V+L}{\left\| V+L \right\|}
H=∥V+L∥V+L
半程向量与表面法线的夹角通常会小于观察方向和反射方向的夹角,如果要使两个模型呈现类似的效果,就需要在 Blinn-Phong 模型设置反光度为 Phong 模型的 222 到 444 倍。
Lspecular=ksID2max(0,N⋅H)p
L_{specular} = k_s \frac{I}{D^2}\max{(0,N \cdot H)}^{p}
Lspecular=ksD2Imax(0,N⋅H)p
对于在 GPU 中进行计算的 shader 程序,计算反射方向是一个耗费性能的行为,半程向量则只需要计算一次向量加法和一次向量单位化。
当出现观察方向与反射方向夹角大于 909090 度,此时高光项分量为 000 ,对于漫反射这是合理的,入射角和法线夹角超过 909090 度说明入射光在物体表面之下,而对于镜面反射,Phong 光照模型测量的是观察方向和反射方向的夹角,当出现物体反光度很小(粗糙)的时候,产生的高光半径就很大,就不能忽略这种角度下的高光项的贡献了。
Cook-Torrance 微表面模型
以物体表面上的微小面积 dAdAdA 为中心,设单位半球作用域 Ω\OmegaΩ ,设该面积在出射方向 wow_owo 上反射出去的 Radiance 为 Lo(ωo)L_o(\omega_o)Lo(ωo),设半球作用域范围内接收的 Irradiance 为 E=LicosθiE = L_i cos\theta_iE=Licosθi。
双向反射分布函数就是二者的比例。因此我们可以推出入射 Irradiance 在 ωi\omega_iωi 方向的微分与出射 Radiance 在 ωo\omega_oωo 方向上的微分之比和积分结果为:
fr(ωi,ωo)=dLo(ωo)Li(ωi)cosθidωi
f_r(\omega_i,\omega_o) = \frac{dL_o(\omega_o)}{L_i(\omega_i){cos\theta_i}d\omega_i}
fr(ωi,ωo)=Li(ωi)cosθidωidLo(ωo)
Lo(ωo)=∫H2fr(ωi,ωo)Li(ωi)cosθidωi L_o(\omega_o)=\int_{H^{2}} f_r(\omega_i,\omega_o){L_i(\omega_i){cos\theta_i}d\omega_i} Lo(ωo)=∫H2fr(ωi,ωo)Li(ωi)cosθidωi
在 Cook-Torrance BRDF 中考虑到了光线被镜面反射和折射的比例,而折射的部分后除了被吸收,剩下的被反弹出物体表面,可视为漫反射项。因此可以再将渲染方程中的 BRDF 分为两项:
fr(ωi,ωo)=kdflambert+ksfcook−torrance
f_r(\omega_i,\omega_o)=k_df_{lambert}+k_sf_{cook-torrance}
fr(ωi,ωo)=kdflambert+ksfcook−torrance
漫反射项
漫反射项采用 Lambertian 光照模型计算,在该模型中假设入射光时均匀分布整个半球体,因此其入射 Irradiance 转换到出射 Radiance 的过程与入射方向无关,即 BRDF 和 LiL_iLi 都是一个常数项:
Lo(ωo)=frLi∫H2cosθidωi
L_o(\omega_o)= f_rL_i\int_{H^{2}}{{cos\theta_i}d\omega_i}
Lo(ωo)=frLi∫H2cosθidωi
球体上的微分面积定义为 dA=rsinθdθrdϕdA = rsin\theta d\theta r d\phidA=rsinθdθrdϕ。而微分面积除以 r2r^2r2 可得微分立体角定义 dω=dA/r2=sinθdθdϕd\omega = dA/r^2 = sin\theta d\theta d\phidω=dA/r2=sinθdθdϕ。
将所有的微分立体角积分起来得到完整的球体,球体积分公式转为二重积分形式,则可以计算 cosθcos\thetacosθ 在半球作用域内的积分结果为:
∫Θdω=∫02π∫0πsinθdθdϕ
\int_{\Theta}d\omega = \int_{0}^{2\pi}\int_{0}^{\pi}{sin\theta} {d\theta} {d\phi}
∫Θdω=∫02π∫0πsinθdθdϕ
∫Ωcosθdω=∫02π∫0π2cosθsinθdθdϕ=π
\int_{\Omega}cos\theta d\omega = \int_{0}^{2\pi}\int_{0}^{\frac{\pi}{2}}{cos\theta sin\theta} {d\theta} {d\phi}=\pi
∫Ωcosθdω=∫02π∫02πcosθsinθdθdϕ=π
将以上带入原式可得 Lo=πfrLiL_o = \pi f_rL_iLo=πfrLi ,假设入射光在半球面范围内是均匀入射的,则 LiL_iLi 与入射角是无关的,但考虑到折射的损失,LiL_iLi 和 LoL_oLo 应当有个损失的比例 ccc,最终可得漫反射项的 BRDF 为 fr=c/πf_r = {c}/{\pi}fr=c/π。
镜面反射项
Cook-Torrance\text{Cook-Torrance}Cook-Torrance 光照模型中,微表面上发生的镜面反射需要考虑决定镜面发射和折射发生比例的菲涅尔项 Fr(ωo,ωi)F_r(\omega_o,\omega_i)Fr(ωo,ωi) 、表示每单位面积、每单位立体角中,所有法线方向为 hhh 的微表面的面积的法线分布函数 D(ωh)D(\omega_h)D(ωh) 和表达光线路径中的阴影遮挡比例的的几何项 G(ωo,ωi)G(\omega_o,\omega_i)G(ωo,ωi)。
D(ωh)D(\omega_h)D(ωh) 的定义是每单位面积、每单位立体角上所有法线方向为 hhh 的微表面的面积。类比 Radiance\text{Radiance}Radiance 的定义 L=d2Φ/(dωdA⊥)L={d^2\Phi}/({d\omega dA^{\perp})}L=d2Φ/(dωdA⊥),可知所有法线方向为 hhh 的微表面面积 A(ωh)A(\omega_h)A(ωh) 是与 Φ\PhiΦ 类似的,因此可得公式:
d2A(ωh)=D(ωh)dωhdA
d^2A(\omega_h) = D(\omega_h)d\omega_hdA
d2A(ωh)=D(ωh)dωhdA
由 Irradiance\text{Irradiance}Irradiance 的定义 E=dΦ/dAE = {d\Phi}/{dA}E=dΦ/dA,可得入射光在微分面积 dAdAdA 上的辐射通量。所有法线方向为 hhh 的镜面反射,其入射方向和出射方向都是确定的,因此对微表面入射 Irradiance\text{Irradiance}Irradiance 的辐射通量 dΦd\PhidΦ ,在入射方向单位立体角上微分、在法线方向为 hhh 的单位立体角上再次微分。
dΦ=LicosθidA
d\Phi = L_icos\theta_idA
dΦ=LicosθidA
d3Φi=Li(ωi)dωid2A⊥(ωh) d^3\Phi_i = L_i(\omega_i)d\omega_i d^2A^{\perp}(\omega_h) d3Φi=Li(ωi)dωid2A⊥(ωh)
=Li(ωi)dωicosθhD(ωh)dωhdA = L_i (\omega_i) d\omega_i cos\theta_h D(\omega_h) d\omega_h dA =Li(ωi)dωicosθhD(ωh)dωhdA
暂时不考虑菲涅尔项和阴影遮挡项,则可以视入射和出射的辐通量没有变化。由 Radiance\text{Radiance}Radiance的定义可知其为辐射通量 Φ\PhiΦ 在单位面积、单位立体角上的微分的两次微分后的辐射通量,对 Radiance\text{Radiance}Radiance在所有法线方向为 hhh 的单位立体角上再次微分,由 BRDF 的定义可得
d3Φo=d3Φi
d^3\Phi_o = d^3\Phi_i
d3Φo=d3Φi
dLo(ωo)=d3ΦodωodA⊥=Li(ωi)dωicosθhD(ωh)dωhdAdωocosθodA dLo(\omega_o) = \frac{d^3\Phi_o}{d\omega_o dA^{\perp}}=\frac{ L_i (\omega_i) d\omega_i cos\theta_h D(\omega_h) d\omega_h dA}{d\omega_o cos\theta_o dA } dLo(ωo)=dωodA⊥d3Φo=dωocosθodALi(ωi)dωicosθhD(ωh)dωhdA
fr(ωo,ωi)=dLo(ωo)dEi(ωi)=Li(ωi)dωicosθhD(ωh)dωhdALi(ωi)cosθidωidωocosθodA=cosθhD(ωh)dωhcosθidωocosθo f_r(\omega_o,\omega_i)= \frac{dL_o{(\omega_o)}}{dE_i(\omega_i)} =\frac{ L_i (\omega_i) d\omega_i cos\theta_h D(\omega_h) d\omega_h dA}{L_i(\omega_i){cos\theta_i}d\omega_id\omega_o cos\theta_o dA }= \frac{cos\theta_h D(\omega_h) d\omega_h}{cos\theta_id\omega_o cos\theta_o} fr(ωo,ωi)=dEi(ωi)dLo(ωo)=Li(ωi)cosθidωidωocosθodALi(ωi)dωicosθhD(ωh)dωhdA=cosθidωocosθocosθhD(ωh)dωh
已知出射方向的角度是半程向量方向的角度的二倍 θo=2θh\theta_o=2\theta_hθo=2θh,由微分立体角的定义 dω=sinθdθdϕd\omega = sin\theta d\theta d\phidω=sinθdθdϕ 可推出二者的比值为:
dωo=sin2θhd2θhdϕ=4sinθhcosθhdθhdϕ
d\omega_o = sin2\theta_h d2\theta_h d\phi = 4sin\theta_h cos\theta_h d\theta_h d\phi
dωo=sin2θhd2θhdϕ=4sinθhcosθhdθhdϕ
dωhdωo=14cosθh \frac{d\omega_h}{d\omega_o} = \frac{1}{4cos\theta_h} dωodωh=4cosθh1
将比值结果带入 BRDF\text{BRDF}BRDF 后化简可得:
fr(ωo,ωi)=D(ωh)4cosθicosθo
f_r(\omega_o,\omega_i)=\frac{ D(\omega_h)}{4cos\theta_i cos\theta_o}
fr(ωo,ωi)=4cosθicosθoD(ωh)
此时加入菲涅尔项 Fr(ωo)F_r(\omega_o)Fr(ωo),几何可见项 G(ωo,ωi)G(\omega_o,\omega_i)G(ωo,ωi) 和可得 BRDF\text{BRDF}BRDF为:
fr(ωo,ωi)=D(ωh)Fr(ωo)G(ωo,ωi)4cosθocosθi
f_r(\omega_o,\omega_i)=\frac{D(\omega_h)F_r(\omega_o)G(\omega_o,\omega_i)}{4 cos\theta_o cos\theta_i}
fr(ωo,ωi)=4cosθocosθiD(ωh)Fr(ωo)G(ωo,ωi)
考虑到物体的自发光,将漫反射项和镜面反射项的 BRDF\text{BRDF}BRDF线性混合后,乘上对应的漫反射系数、镜面反射系数 kd,ksk_d,k_skd,ks 后可得完整的渲染方程为:
Lo(p,ωo)=Le(p,ωr)+∫Ω(kdcπ+ksD(ωh)Fr(ωo)G(ωo,ωi)4cosθocosθi)Li(p,ωi)cosθidωi
L_o(p,\omega_o)=L_e(p,\omega_r)+\int_{\Omega} {(k_d \frac{c}{\pi}+k_s\frac{D(\omega_h)F_r(\omega_o)G(\omega_o,\omega_i)}{4 cos\theta_o cos\theta_i})} {L_i(p,\omega_i){cos\theta_i}d\omega_i}
Lo(p,ωo)=Le(p,ωr)+∫Ω(kdπc+ks4cosθocosθiD(ωh)Fr(ωo)G(ωo,ωi))Li(p,ωi)cosθidωi
路径追踪
Lo(p,ωo)=∫Ω+Li(p,ωi)fr(p,ωo,ωi)cosθi L_o(p,\omega_o) = \int_{\Omega^+}{ L_i(p, \omega_i)f_r(p, \omega_o,\omega_i) \cos \theta_i} Lo(p,ωo)=∫Ω+Li(p,ωi)fr(p,ωo,ωi)cosθi
蒙特卡洛积分方法
采用蒙特卡洛积分方法解渲染方程,在半球面上随机采样入射方向。
Lo(p,ωo)≈1N∑i=1NLi(p,ωi)fr(p,ωo,ωi)cosθipdf(ωi)
L_o(p,\omega_o) ≈ \frac{1}{N} \sum_{i=1}^{N}\frac{ L_i(p, \omega_i)f_r(p, \omega_o,\omega_i) \cos \theta_i}{pdf(\omega_i)}
Lo(p,ωo)≈N1i=1∑Npdf(ωi)Li(p,ωi)fr(p,ωo,ωi)cosθi
俄罗斯轮盘赌
采用俄罗斯轮盘赌的方法终止递归,只需要在结果除以轮盘赌概率即可。
对光源采样
通过对光源采样,避免因为打不到光源的情况的发生,加快收敛。
未完待续…