OpenGL光照計算中法線矩陣原理及推到過程

ideryi發表於2021-03-17

問題起源

在計算漫反射關照時,需要用到法線,通過法線和光線的點乘值,計算漫反射的產生的光線強度,所以需要從頂點著色器中將法線資料傳遞到片源著色器中,但是片源著色器中的頂點座標是經過了模型矩陣變化過的世界座標.所以二者很可能已經不匹配了,當然模型矩陣是單位矩陣的特殊情況下,就沒有影響.

對法線進行mv變換

因此,需要對法線也應用mv矩陣變換.這樣,模型的在旋轉和縮放後,法線才能也與之匹配,如下圖這樣:
image

去掉對法線的偏移效果

但有個問題,就是偏移,如果法線跟著一起偏移,方向就會出問題了,加入模型矩陣沿x方向偏移一點,法線的x也相應的增加一點,就會出現下面這樣的情況:
image
這種情況可以通過將法線的齊次座標設定為0,來解決,因為偏移的原理就是矩陣最後一列的值乘以其次座標產生的影響:
image

不等比縮放

大部分情況下,上面的處理就可以得到想要的效果了,但是,如果mv矩陣中存在不等比縮放,那麼會出現法線與原來的面不垂直的問題,雖然在很多情況下這個效果可能不會太明顯,因為法線偏差一點點,關照計算並不會有特別明顯的區別:
image
但是當不等比縮放的不同軸之間的差距很大時,這個效果就會更明顯了.像下面這樣:
image
這個時候計算出來的光照就會和預期的有很明顯的區別,給人很怪異的感覺了.

法線矩陣

這個時候,需要使用發現矩陣,其實就是模型矩陣逆矩陣的轉置矩陣,用上效果立馬就對了.
image

模型矩陣逆矩陣的轉置矩陣作用原理

用法很簡單,原理還是需要點時間來理解的.
首先我們的目標是法線最終需要與頂點的切線垂直.
定義:原法線為n,變換後法線為N,原來頂點處切線為t,變換後切線為T,模型矩陣為M,要計算的結果法線矩陣為X.
.表示點乘,表示矩陣乘以向量(也可以省略),或者向量間叉乘,`代表:
n . t = 0; //法線與切線垂直,所以點乘為0
N . T = 0; //最終結果亦垂直
N = X * n
T = M * t
將第三,四個方程帶入第二個方程:
(X * n) . (M * t) = 0
點乘變換成叉乘
(X * n) . (M * t) => (X * n)T * (M * t) => 省略* => (Xn)T * Mt
=> nTXT * Mt
由於n . t = 0
XTM = I
n . t = N . T = 0
XTM = I => X = (M-1)T

相關文章