1. 程式人生 > >OpenGL光照計算中法線矩陣原理及推到過程

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

# 問題起源 在計算漫反射關照時,需要用到法線,通過法線和光線的點乘值,計算漫反射的產生的光線強度,所以需要從頂點著色器中將法線資料傳遞到片源著色器中,但是片源著色器中的頂點座標是經過了模型矩陣變化過的世界座標.所以二者很可能已經不匹配了,當然模型矩陣是單位矩陣的特殊情況下,就沒有影響. # 對法線進行mv變換 因此,需要對法線也應用mv矩陣變換.這樣,模型的在旋轉和縮放後,法線才能也與之匹配,如下圖這樣: ![image](https://img2020.cnblogs.com/blog/2136291/202103/2136291-20210317193537851-2007749184.png) # 去掉對法線的偏移效果 但有個問題,就是偏移,如果法線跟著一起偏移,方向就會出問題了,加入模型矩陣沿x方向偏移一點,法線的x也相應的增加一點,就會出現下面這樣的情況: ![image](https://img2020.cnblogs.com/blog/2136291/202103/2136291-20210317200452821-644935675.png) 這種情況可以通過將法線的齊次座標設定為0,來解決,因為偏移的原理就是矩陣最後一列的值乘以其次座標產生的影響: ![image](https://img2020.cnblogs.com/blog/2136291/202103/2136291-20210317200804236-1937928916.png) # 不等比縮放 大部分情況下,上面的處理就可以得到想要的效果了,但是,如果mv矩陣中存在不等比縮放,那麼會出現法線與原來的面不垂直的問題,雖然在很多情況下這個效果可能不會太明顯,因為法線偏差一點點,關照計算並不會有特別明顯的區別: ![image](https://img2020.cnblogs.com/blog/2136291/202103/2136291-20210317202043520-827601615.png) 但是當不等比縮放的不同軸之間的差距很大時,這個效果就會更明顯了.像下面這樣: ![image](https://img2020.cnblogs.com/blog/2136291/202103/2136291-20210317202203550-2098249339.png) 這個時候計算出來的光照就會和預期的有很明顯的區別,給人很怪異的感覺了. # 法線矩陣 這個時候,需要使用發現矩陣,其實就是模型矩陣逆矩陣的轉置矩陣,用上效果立馬就對了. ![image](https://img2020.cnblogs.com/blog/2136291/202103/2136291-20210317202750284-239487274.png) # 模型矩陣逆矩陣的轉置矩陣作用原理 用法很簡單,原理還是需要點時間來理解的. 首先我們的目標是法線最終需要與頂點的切線垂直. 定義:原法線為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)