渲染中的光照:从直接光照到全局光照

304 阅读6分钟

Phong 光照模型

\cdot 设观察方向 VV ,光源方向 LL ,法线方向 NN 。三者都是归一化后的单位向量,则可以计算出反射方向。

R=Reflect(L,N)R = Reflect(-L,N)

Phong 模型在分为环境光、漫反射项和高光项。其中环境光可以视为平行光,只需要计算一定比例的光照强度即可。

L=La+Ld+LsL = L_a+L_d+L_s
Lambient=kaIaL_{ambient} = k_aI_a

漫反射项则跟着色点与光源的距离 DD 的平方,即衰减项,以及光源方向和法线方向的夹角余弦相关。

Fatt=1D2F_{att} = \frac{1}{D^2}
Ldiffuse=kdFattmax(0,NL)L_{diffuse} = k_d F_{att} \max{(0,N \cdot L)}

高光项同样跟着色点与光源的距离 DD 的平方相关,且越靠近光源方向则反射的高光越强、越集中,即高光项和光源方向和法线方向的夹角余弦相关,同时为了模拟距离越远越快速衰减,需要给夹角余弦加上指数 pp 作为反光度。

Lspecular=ksFattmax(0,LR)pL_{specular} = k_s F_{att}\max{(0,L \cdot R)}^{p}

实际上使用距离的平方作为衰减项也不符合人眼的实际感受,为了模拟人的视觉效果,可以对衰减项引入常数项和线性项。至于各项系数的取值,这属于经验数值,可以查表得到。

Fatt=1Kc+KlD+KqD2F_{att}=\frac{1}{K_{c}+K_{l} * D+K_{q} * D^{2}}

此外,如果采用不同的着色法,最终取得的光照效果是不同的,显然更好的效果需要更多的性能进行计算。如 Flat 着色法只使用面法线进行计算光照的 Phong 光照模型,导致每个面之间非常分明。而 Gouraud 着色法在顶点着色器中进行计算光照的 Phong 光照模型,相对 Flat 着色法效果好了一些。而 Phong 着色法则是经过插值后,在片元着色器中计算三角形内每一个片元的光照,其光照效果自然更加的平滑。

Blinn-Phong 光照模型

Phong 模型在计算高光项时,使用反射方向和观察方向的夹角余弦,而 Blinn-Phong 模型在计算高光项时,先计算出入射方向和观察方向的半程向量(单位化的二者之和向量),然后计算半程向量和法向量的夹角余弦。

H=V+LV+LH = \frac{V+L}{\left\| V+L \right\|}

半程向量与表面法线的夹角通常会小于观察方向和反射方向的夹角,如果要使两个模型呈现类似的效果,就需要在 Blinn-Phong 模型设置反光度为 Phong 模型的 2244 倍。

Lspecular=ksID2max(0,NH)pL_{specular} = k_s \frac{I}{D^2}\max{(0,N \cdot H)}^{p}

对于在 GPU 中进行计算的 shader 程序,计算反射方向是一个耗费性能的行为,半程向量则只需要计算一次向量加法和一次向量单位化。

当出现观察方向与反射方向夹角大于 9090 度,此时高光项分量为 00 ,对于漫反射这是合理的,入射角和法线夹角超过 9090 度说明入射光在物体表面之下,而对于镜面反射,Phong 光照模型测量的是观察方向和反射方向的夹角,当出现物体反光度很小(粗糙)的时候,产生的高光半径就很大,就不能忽略这种角度下的高光项的贡献了。

Cook-Torrance 微表面模型

以物体表面上的微小面积 dAdA 为中心,设单位半球作用域 Ω\Omega ,设该面积在出射方向 wow_o 上反射出去的 Radiance 为 Lo(ωo)L_o(\omega_o),设半球作用域范围内接收的 Irradiance 为 E=LicosθiE = L_i cos\theta_i

双向反射分布函数就是二者的比例。因此我们可以推出入射 Irradiance 在 ωi\omega_i 方向的微分与出射 Radiance 在 ωo\omega_o 方向上的微分之比和积分结果为:

fr(ωi,ωo)=dLo(ωo)Li(ωi)cosθidωif_r(\omega_i,\omega_o) = \frac{dL_o(\omega_o)}{L_i(\omega_i){cos\theta_i}d\omega_i}
Lo(ωo)=H2fr(ωi,ωo)Li(ωi)cosθidωiL_o(\omega_o)=\int_{H^{2}} f_r(\omega_i,\omega_o){L_i(\omega_i){cos\theta_i}d\omega_i}

在 Cook-Torrance BRDF 中考虑到了光线被镜面反射和折射的比例,而折射的部分后除了被吸收,剩下的被反弹出物体表面,可视为漫反射项。因此可以再将渲染方程中的 BRDF 分为两项:

fr(ωi,ωo)=kdflambert+ksfcooktorrancef_r(\omega_i,\omega_o)=k_df_{lambert}+k_sf_{cook-torrance}

漫反射项

漫反射项采用 Lambertian 光照模型计算,在该模型中假设入射光时均匀分布整个半球体,因此其入射 Irradiance 转换到出射 Radiance 的过程与入射方向无关,即 BRDF 和 LiL_i 都是一个常数项:

Lo(ωo)=frLiH2cosθidωiL_o(\omega_o)= f_rL_i\int_{H^{2}}{{cos\theta_i}d\omega_i}

球体上的微分面积定义为 dA=rsinθdθrdϕdA = rsin\theta d\theta r d\phi。而微分面积除以 r2r^2 可得微分立体角定义 dω=dA/r2=sinθdθdϕd\omega = dA/r^2 = sin\theta d\theta d\phi

将所有的微分立体角积分起来得到完整的球体,球体积分公式转为二重积分形式,则可以计算 cosθcos\theta 在半球作用域内的积分结果为:

Θdω=02π0πsinθdθdϕ\int_{\Theta}d\omega = \int_{0}^{2\pi}\int_{0}^{\pi}{sin\theta} {d\theta} {d\phi}
Ω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

将以上带入原式可得 Lo=πfrLiL_o = \pi f_rL_i ,假设入射光在半球面范围内是均匀入射的,则 LiL_i 与入射角是无关的,但考虑到折射的损失,LiL_iLoL_o 应当有个损失的比例 cc,最终可得漫反射项的 BRDF 为 fr=c/πf_r = {c}/{\pi}

镜面反射项

Cook-Torrance 光照模型中,微表面上发生的镜面反射需要考虑决定镜面发射和折射发生比例的菲涅尔项 Fr(ωo,ωi)F_r(\omega_o,\omega_i) 、表示每单位面积、每单位立体角中,所有法线方向为 hh 的微表面的面积的法线分布函数 D(ωh)D(\omega_h) 和表达光线路径中的阴影遮挡比例的的几何项 G(ωo,ωi)G(\omega_o,\omega_i)

D(ωh)D(\omega_h) 的定义是每单位面积、每单位立体角上所有法线方向为 hh 的微表面的面积。类比 Radiance 的定义 L=d2Φ/(dωdA)L={d^2\Phi}/({d\omega dA^{\perp})},可知所有法线方向为 hh 的微表面面积 A(ωh)A(\omega_h) 是与 Φ\Phi 类似的,因此可得公式:

d2A(ωh)=D(ωh)dωhdAd^2A(\omega_h) = D(\omega_h)d\omega_hdA

由 Irradiance 的定义 E=dΦ/dAE = {d\Phi}/{dA},可得入射光在微分面积 dAdA 上的辐射通量。所有法线方向为 hh 的镜面反射,其入射方向和出射方向都是确定的,因此对微表面入射 Irradiance 的辐射通量 dΦd\Phi ,在入射方向单位立体角上微分、在法线方向为 hh 的单位立体角上再次微分。

dΦ=LicosθidAd\Phi = L_icos\theta_idA
d3Φi=Li(ωi)dωid2A(ωh)d^3\Phi_i = L_i(\omega_i)d\omega_i d^2A^{\perp}(\omega_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

暂时不考虑菲涅尔项和阴影遮挡项,则可以视入射和出射的辐通量没有变化。由 Radiance 的定义可知其为辐射通量 Φ\Phi 在单位面积、单位立体角上的微分的两次微分后的辐射通量,对 Radiance 在所有法线方向为 hh 的单位立体角上再次微分,由 BRDF 的定义可得

d3Φo=d3Φid^3\Phi_o = d^3\Phi_i
dLo(ωo)=d3ΦodωodA=Li(ωi)dωicosθhD(ωh)dωhdAdωocosθodAdLo(\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 }
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θof_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}

已知出射方向的角度是半程向量方向的角度的二倍 θo=2θh\theta_o=2\theta_h,由微分立体角的定义 dω=sinθdθdϕd\omega = sin\theta d\theta d\phi 可推出二者的比值为:

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ωhdωo=14cosθh\frac{d\omega_h}{d\omega_o} = \frac{1}{4cos\theta_h}

将比值结果带入 BRDF 后化简可得:

fr(ωo,ωi)=D(ωh)4cosθicosθof_r(\omega_o,\omega_i)=\frac{ D(\omega_h)}{4cos\theta_i cos\theta_o}

此时加入菲涅尔项 Fr(ωo)F_r(\omega_o),几何可见项 G(ωo,ωi)G(\omega_o,\omega_i) 和可得 BRDF 为:

fr(ωo,ωi)=D(ωh)Fr(ωo)G(ωo,ωi)4cosθocosθif_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}

考虑到物体的自发光,将漫反射项和镜面反射项的 BRDF 线性混合后,乘上对应的漫反射系数、镜面反射系数 kd,ksk_d,k_s 后可得完整的渲染方程为:

Lo(p,ωo)=Le(p,ωr)+Ω(kdcπ+ksD(ωh)Fr(ωo)G(ωo,ωi)4cosθocosθi)Li(p,ωi)cosθidωiL_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)=Ω+Li(p,ωi)fr(p,ωo,ωi)cosθiL_o(p,\omega_o) = \int_{\Omega^+}{ L_i(p, \omega_i)f_r(p, \omega_o,\omega_i) \cos \theta_i}

蒙特卡洛积分方法

采用蒙特卡洛积分方法解渲染方程,在半球面上随机采样入射方向。

Lo(p,ωo)1Ni=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)}

俄罗斯轮盘赌

采用俄罗斯轮盘赌的方法终止递归,只需要在结果除以轮盘赌概率即可。

对光源采样

通过对光源采样,避免因为打不到光源的情况的发生,加快收敛。

未完待续......