光源
一般的,一個場景中存在任意數量的點光及方向光(平行光)和單個環境光。
點光
如燈泡,點光具有位置和強度(光的亮度),假設從一個點向每個方向均勻的發射光,定義光向量(方向)\(L=Q - P\),其中\(Q\)為固定的光源發射位置,\(P\)為場景中任意點的位置。
方向光
如日光,太陽過於遙遠,以至於到達我們身邊的光線幾乎都是平行的,若按照點光源處理,則會帶來數值精度誤差的問題,假設方向光沒有位置,只有方向和強度。
環境光
光照射到一個物體後一部分被吸收,一部分被散射,這意味著光不僅可以來自光源,也可以來自場中物體的散射,如果把每一個物體當作光源,這將對於實時計算產生相當大的效能開銷,類似的情況一般會使用全域性光照技術渲染,所以假設環境光為場景中的每一個點貢獻一些光,環境光只有強度,任意數量的環境光可以簡單的組合成一個環境光。
傳統光照模型
漫反射
假設當光照射到粗糙物體表面時會被均勻的散射到各個方向,這個過程稱之為漫反射。
物體表面單位面積內所能接收到的光的能量與光線和物體表面之間的角度存在關係,如圖,相同強度的兩束光,分別以不同的角度照射到物體表面,顯然右側光線的能量分佈在了更大的區域上面,也就是說右側單位面積內所能接收到的能量比左側更小,同樣的所能反射的光線的量也更小。
做一個幾何類比,用光線的“寬度”表示光的強度,當方向為L且強度為I的光線照射到法線為\(N\)的表面時,它的能量分佈在了大小為\(A\)的表面上,若\(L\)與\(N\)方向相同,即光線垂直於表面時,此時\(I=A\),意味著單位面積反射的能量與入射的能量相同,即\(\frac{I}{A}=1\),當\(L\)與\(N\)的夾角接近\(90°\)時,\(A\)趨於\(∞\),因此單位面積內能量趨於0,即\(\lim_{A\to \infty}\frac{I}{A}=0\),\(\frac{I}{A}\)代表了反射光線的強度。
下圖中“寬度”為\(I\)的光線以角度\(β\)照射到物體表面法線為\(N\)的點\(P\)處分佈在了面積\(A\)上,從圖中可得出\(\angle QRP=\alpha\),進而得到\(\cos\alpha=\frac{I}{A}\),由點積的性質:\(\cos\alpha=\frac{N\cdot L}{\lVert N\rVert\lVert L\rVert}\)可得\(\frac{I}{A}=\frac{N\cdot L}{\lVert N\rVert\lVert L\rVert}\),由此建立了某點處反射光線的強度與法線向量和光向量的關係。
漫反射方程:
\(I_P=I_A+\sum_{i=1}^nI_i\frac{N\cdot L_i}{\lVert N\rVert\lVert L_i\rVert}\)
- \(I_P\)場景中點P所接受到的全部光線
- \(I_A\)環境光
- \(I_i\)點光或方向光的強度
- \(N\)P點的法線
- \(L_i\)光向量(方向光是已知的,點光源則需要為每個點單獨計算)
鏡面反射
高光反射補充了漫反射,當一束光照\(L\)射到一面“完美拋光”的鏡子上時,光線會按照同一個方向\(R\)反射,圖中\(L\)的方向僅為方便計算。
但並非所有的表面都是“完美拋光”的,一部分的光線沿著\(R\)方向被反射,一部分的光線沿著接近\(R\)的方向被反射。
下圖中,\(L_N\)是\(L\)的投影,\(N\)為單位法向量,其中\(L_P=L-L_N\),根據向量投影的性質,可知\(L_N=N(N\cdot L)\),R是反射方向,由圖可見\(R=L_N-L_P\),替換\(L_N\)與\(L_P\)可得\(R=N(N\cdot L)-L+N(N\cdot L)\),化簡得\(R=2N(N\cdot L)-L\),此時得到了反射方向向量。
高光反射的強度與反射方向\(R\)和視角方向\(V\)相關,當\(α=0°\)時,光線會在\(V\)方向和其附近反射,此時看到的高光強度最高,當\(α=90°\)時,沒有光被反射到\(V\)方向,與漫反射類似,可用\(R\)與\(V\)的點積來確定高光的強度:
\(I_S=I_L\frac{R\cdot V}{\lVert R\rVert\lVert V \rVert}\)
- \(I_S\)高光強度
- \(I_L\)入射光強度
- \(R\)反射方向
- \(V\)視角方向
但每種物體的“光澤度”並非一致,由上述可知\(\frac{R\cdot V}{\lVert R\rVert\lVert V \rVert}=\cos\alpha\),此時便可利用\(cos\)函式的特性,如圖\(\cos(\alpha)^s\)函式當\(s\)處於不同值的時候,呈現出不同的高光強度變化曲線,此時高光強度可表示為:
\(I_S=I_L\left(\frac{R\cdot V}{\lVert R\rVert\lVert V \rVert}\right)^s\)
\(s\)表示物體表面的光澤度,但這裡只是調整s值讓物體表面的高光反射看起來正確,並不符合現有的物理規律。
完整的光照模型
\(I_P=I_A+\sum_{i=1}^nI_i\cdot\left[\frac{N\cdot L_i}{\lVert N\rVert\lVert L_i\rVert}+\left(\frac{R_i\cdot V}{\lVert R_i\rVert\lVert V\rVert}\right)^s\right]\)
- \(I_P\)\(P\)點處的總光照度
- \(I_A\)環境光強度
- \(I_i\)光源\(i\)的強度
- \(N\)\(P\)點處法線
- \(L_i\)\(P\)點到光源\(i\)的光向量
- \(R_i\)光源\(i\)在\(P\)點處的反射向量
- \(V\)從\(P\)點到相機的視線向量
實際應用中的傳統光照模型
Lambert 光照模型
\(C_D=I\cdot C_L\cdot M_D\cdot\max(0,\hat N\cdot \hat L)\)
- \(C_D\)漫反射(Diffuse)最終顏色
- \(I\)光源強度
- \(C_L\)光源(Light)顏色
- \(M_D\)材質(Material)的漫反射顏色
- \(N\)表面法線
- \(L\)光向量
Half Lambert 光照模型
\(C_D=I\cdot C_L\cdot M_D(0.5\cdot\hat N\cdot \hat L+0.5)\)
相較於Lambert 光照模型,將\(\hat N\cdot \hat L\)的結果從\([-1,1]\)的區間對映到了\([0,1]\)的區間,意味著模型的背面也將有不同的明暗變化。
Phong 光照模型
\(C_S=I\cdot C_L\cdot M_S\cdot\max(0,\hat R\cdot \hat V)^s\)
- \(C_S\)高光反射(Specular)最終顏色
- \(I\)光源強度
- \(C_L\)光源(Light)顏色
- \(M_S\)材質(Material)的高光反射顏色
- \(R=2\hat N(\hat N\cdot L)-L\)反射方向
- \(V\)視角方向
Blinn-Phong 光照模型
\(C_S=I\cdot C_L\cdot M_S\cdot\max(0,\hat N\cdot \hat H)^s\)
相較於Phone 光照模型,避免計算反射方向\(R\),而是計算半程向量(Bisector)\(H\),將視向量\(V\)和光向量\(L\)相加然後歸一化,其中\(H=\frac{V+L}{\lVert V+L\rVert}\).
Blinn-Phong 光照模型相較於Phong 光照模型的高光反射部分看起來更大、更亮一些。
個人修改的Half Lambert 光照模型
\(C_D=I_F\cdot C_{LF}\cdot M_D\cdot H +I_B\cdot C_{LB}\cdot M_D\cdot(1-H)\)
- \(I_F\)物體正面光源強度
- \(C_{LF}\)物體正面光源(Light)顏色
- \(I_B\)物體背面光源強度
- \(C_{LB}\)物體背面光源(Light)顏色
- \(H=0.5\cdot\hat N\cdot \hat L+0.5\)
相較於Half Lambert 光照模型,加入背面光照強度的控制,由於在某些風格化的渲染中,背部表現過暗,故透過\(1-H\)反向控制背面亮度。
參考
《計算機圖形學入門:3D渲染指南》
《Unity Shader入門精要》