计算机图形学:凹凸贴图、法线贴图、切线空间、TBN矩阵
凹凸映射
凹凸映射(bump mapping)是一種常見的紋理應用。凹凸映射通過“擾動”(perturb)模型表面的法線方向來改變光照結果,從而為模型提供更多細節,但并不會真正改變模型的頂點位置,因此一般在Fragment Shader中進行。若將一個高精度的法線信息套用在低精度模型上,可以增加低精度模型的渲染細節。
如何實現凹凸映射,也就是如何保存法線信息到紋理上,如何從紋理上獲得法線信息。需要解決的問題有兩個:
方向是相對于坐標空間來說的。涉及到方向信息,那必然涉及到方向定義在哪個坐標空間中,涉及到坐標系轉換。
一般紋理存儲的是代表顏色值的三維/四維向量,保存的法線信息和顏色值應該通過什么樣的計算/映射相互轉化。
對于第二個問題,主要實現方法有兩種:一種方法是使用凹凸貼圖(bump map)存儲一系列相對于表面的高度信息,再通過計算得到法線信息;另一種方法是使用法線貼圖(normal map)來直接存儲表面法線,經過簡單映射即可從顏色信息轉換為法線信息。
凹凸貼圖
凹凸貼圖(bump map)相較于普通的紋理,其存儲的不是顏色值,一般是使用一張灰度圖來存儲一系列模型頂點相對于表面的高度信息,并以該高度信息來“擾動”表面法線方向,因此也叫高度貼圖(height map)。灰度值越小表示該位置的表面相對于原表面越向外凸起,灰度值越大表示該位置的表面相對于原表面越向內凹陷。但時刻記住,凹凸映射是通過改變表面法線方向來改變光照結果,表面幾何信息沒有任何變化。
我們可以從凹凸貼圖中明確知道一個模型表面的凹凸情況,但使用凹凸貼圖的缺點是計算更加復雜,在實時計算時不能直接得到表面法線,而是需要根據紋理UV坐標采樣到的灰度值以及鄰近的灰度值通過差分法(有限差分近似導數)先得到切線,再計算獲得法線。具體計算方法如下:
注意:計算得到的結果位于局部坐標系中,若法線信息存儲在模型頂點的切線空間中,則得到的法線為切線空間中的法線方向,要想將這個法線方向應用到光照中還需要經過坐標轉換,TBN矩陣就是用來做這一轉換的。
法線貼圖
法線貼圖直接存儲表面法線方向,相較于凹凸貼圖,從法線貼圖上采樣顏色值到獲取法線方向只需要一個簡單映射。由于法線方向的分量范圍在([-1,1]),而紋理顏色值分量范圍為([0,1]),因此映射如下:
[pixel = frac{normal+1}{2} \
normal = pixel imes2-1
]
那么回到最開始提到的第一個問題,法線貼圖中存儲的法線在哪個坐標空間中?比較直接的想法就是像表面法線一樣,把修改后的模型空間中的表面法線經過上述映射存儲在一張紋理中,這種紋理被稱為是模型空間(object-space)的法線貼圖。由于存儲在模型空間中,法線方向可能向各個方向散開,映射到顏色值上使法線貼圖看起來效果是五顏六色的,如法線方向(0,1,0)映射到顏色值上對應RGB(0.5,1,0.5)為淺綠色。因此模型空間下的法線貼圖看起來如下圖:
然而存儲在模型空間中的法線信息是絕對法線信息,當我們嘗試將這樣的法線信息應用于UV動畫或其它模型上時就會出錯。因此在實際中我們常常會存儲在另一種坐標空間,即模型頂點的切線空間中,這樣存儲的紋理被稱為是切線空間(tangent-space)的法線貼圖。
切線空間的法線貼圖存儲的是相對法線信息,即各個點在各自切線空間中的法線擾動方向,切線空間的z軸方向由頂點法線方向定義,因此若頂點法線沒有擾動,則存儲的相對法線信息為(0,0,1),映射到顏色值上對應(0.5,0.5,1)淺藍色。頂點法線一般不會被大幅度擾動,因此擾動后的法線方向總是靠近z軸方向,法線貼圖總是如下圖一樣呈現大片藍紫色:
而且由于存儲的是切線空間下的相對法線信息,這樣的信息應用于UV動畫或其它模型上也不會出錯。
切線空間與TBN矩陣
任何坐標空間都由三個互相正交的基向量構成,切線空間也是同理。切線空間由三個互相正交的基向量t,b,n組成。首先,切線空間定義在模型的每一個頂點上,切線空間的原點就是頂點本身,z軸是頂點的法線方向,也稱為n軸(normal);x軸是頂點的切線方向,也稱為t軸(tangent);y軸由法線和切線叉乘得到,也叫副切線,稱為b軸(bitangent)。如下圖:
n軸可由頂點法線直接確定,而切線有無數條,如何確定t軸和b軸方向呢?法線貼圖的切線T與副切線B定義一般與紋理坐標的U,V對齊,因此也利用這個特性來確定每個表面頂點切線空間的t,b軸方向。
首先取當前頂點所在三角面的三個頂點(P_1,P_2,P_3)的模型空間坐標與對應的UV坐標,如圖:
為了建立與u,v軸對齊的t,b軸,計算三角面三個頂點在紋理坐標上的差值(Delta U_1,Delta U_2),我們可以建立如下關于切線向量(T)和副切線向量(B)的線性組合:
[P_2-P_1=Delta {U_1}T+ Delta {V_1}B \
P_3-P_2=Delta {U_2}T+ Delta {V_2}B
]
將向量展開,并將兩條邊的表示寫作(E_1,E_2):
[(E_{1x},E_{1y},E_{1z})=Delta{U_1}(T_x,T_y,T_z)+ Delta{V_1}(B_x,B_y,B_z) \
(E_{2x},E_{2y},E_{2z})=Delta{U_2}(T_x,T_y,T_z)+ Delta{V_2}(B_x,B_y,B_z)
]
寫成矩陣形式:
[egin{bmatrix} E_{1x}&E_{1y}&E_{1z} \ E_{2x}&E_{2y}&E_{2z}end{bmatrix}=
egin{bmatrix} Delta{U_1} & Delta{V_1} \ Delta{U_2} & Delta{V_2} end{bmatrix}
egin{bmatrix} T_x & T_y & T_z \ B_x & B_y & B_zend{bmatrix}
]
兩邊同乘逆矩陣將差值部分左移,得到關于(T,B)的等式:
[egin{bmatrix} T_x & T_y & T_z \ B_x & B_y & B_zend{bmatrix} =
egin{bmatrix} Delta{U_1} & Delta{V_1} \ Delta{U_2} & Delta{V_2} end{bmatrix}^{-1}
egin{bmatrix} E_{1x}&E_{1y}&E_{1z} \ E_{2x}&E_{2y}&E_{2z}end{bmatrix}
]
使用伴隨矩陣法求解逆矩陣:(A^{-1}=frac{A^*}{det(A)}),最終得到如下等式:
[egin{bmatrix} T_x & T_y & T_z \ B_x & B_y & B_zend{bmatrix} =
frac{1}{Delta{U_1}Delta{V_2}-Delta{U_2}Delta{V_1}}
egin{bmatrix} Delta{V_2} & -Delta{U_1} \ -Delta{U_2} & Delta{U_1} end{bmatrix}
egin{bmatrix} E_{1x}&E_{1y}&E_{1z} \ E_{2x}&E_{2y}&E_{2z}end{bmatrix}
]
至此,我們可以根據三角形三個頂點和UV坐標來得到對齊u,v軸的t,b軸方向了,實際中只需根據公式求出(T),再由(N)和(T)叉乘得到(B)。
建立起切線空間后,根據基向量變換,不難得到從模型空間向切線空間轉換的話只需左乘如下矩陣(其中(N)為頂點法線向量):
[egin{bmatrix}x_{tangent} \ y_{tangent} \ z_{tangent}end{bmatrix}=
egin{bmatrix}T_x & T_y & T_z \ B_x & B_y & B_z \ N_x & N_y & N_zend{bmatrix}
egin{bmatrix}x_{object} \ y_{object} \ z_{object}end{bmatrix}
]
那么將凹凸貼圖或法線貼圖上的法線信息從切線空間向模型空間轉換的話,只需左乘該矩陣的逆矩陣后作歸一化。已知該矩陣定義了一個正交的坐標空間,那么該矩陣為正交矩陣,正交矩陣的逆等于轉置,這就得到了TBN矩陣:
[egin{bmatrix}x_{object} \ y_{object} \ z_{object}end{bmatrix}=
egin{bmatrix}T_x & B_x & N_x \ T_y & B_y & N_y \ T_z & B_z & N_zend{bmatrix}
egin{bmatrix}x_{tangent} \ y_{tangent} \ z_{tangent}end{bmatrix}
]
補充
應用上述方法雖然t軸和b軸可以與紋理坐標u軸v軸對齊,但uv不一定是相互垂直的,這就使得求得的(T)不一定正確,有時候在求得(T)后還需要做一步操作——施密特正交化:
[T_⊥=normalize(T-(T cdot N)N) \
B_⊥=normalize(B-(B cdot N)N - (B cdot T_⊥)T_⊥)
]
施密特正交化的幾何意義就是將“任意坐標系”轉換成“直角坐標系”。(N)已知,求得(T)后對其進行施密特正交化,再叉乘得到(B),即可構造出正確的切線空間。
參考
GAMES101-現代計算機圖形學入門-閆令琪
計算機圖形學八:紋理映射的應用(法線貼圖,凹凸貼圖與陰影貼圖等相關應用的原理詳解)
切線空間(Tangent Space)完全解析
法線貼圖 - LearnOpenGL
《Unity Shader 入門精要》
總結
以上是生活随笔為你收集整理的计算机图形学:凹凸贴图、法线贴图、切线空间、TBN矩阵的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三个字古风网名104个
- 下一篇: 康威生命游戏(Conway's