已經知道不能直接用模型變換矩陣來變換Normal,好比使用某含有非一致性縮放(在x,y,z方向上進行不程度的拉伸)的變換矩陣來變換一球體,則可能獲得以下列圖示的結果: 安全
左圖爲原始球體及其表面上的法向分佈(2D投影后);中間爲直接使用變換矩陣操做後的法向分佈,但注意其明顯與表面不垂直;右圖爲正確變換後的法向分佈。
爲何直接變換不正確呢?網上有多種說明版本,可是對比了一下感受仍是PBRT上的解釋比較好一些。這裏假設某一點處的法向量爲n,切向量爲t,由二者在曲面上的垂直關係可知: 工具
若是對於模型進行空間變換的矩陣爲M,變換後在該點獲得的新的切向量爲,那麼可得
(這裏假設切向量並非由變換矩陣計算獲得的,而是直接經過對模型表面進行幾何分析計算獲得的);變換後在該點獲得新的法向量爲
,如果獲得的正確法向量,則其一定仍然與切向量垂直。假設正確變換獲得的法向量是在變換矩陣S下進行的,那麼有
,由法、切的垂直關係得: spa
在上式的最後階段中能夠看出,若是要知足成立條件則有,直接變換便可得
,因此也就有:
.net
這裏就獲得了一般咱們所說的採用逆的轉置矩陣來代替原始變換矩陣來對法向量進行操做。
上述推導中使用的一個依據是切向量與法向量之間的垂直關係,其實這是創建在另一個基礎上,那就是:切向量的計算通常是直接使用頂點與UV來進行,這樣的話它就是直接與頂點相關,於是只要直接使用變換矩陣獲得的頂點正確那麼在此基礎上計算而來的切向量也就正確,可是法向量卻不是直接經過頂點計算、而是經過變換獲得的(固然,若是Normal 也在網格頂點變換以後直接計算,而不是對原始的法向量用變換矩陣做空間變換的話就不會存在這一問題了) orm
另外,在實際操做中對於變換矩陣(通常爲4x4的)並不必定可逆(好比一個由3D到2D的投影矩陣),於是上述S就無法計算,這種狀況下更安全的一種方法是隻使用原始4x4變換矩陣的左上角3x3矩陣,即不考慮平移部分,其實這也理所固然,平移操做本就不影響法向量。這一部分在Realtime Rendering中也有稍詳細的說明。 get
固然,使用逆的轉置來進行Normal變換隻是正確方法的一種,不過也有其它的方法,好比從一個變換矩陣中只抽取出Rotation的部分來施加到Normal上,這樣就免去了Translation和Scale的影響。矩陣的R, T, S分解也有不少經典的方法,能夠參考一個這個帖子:http://www.gamedev.net/topic/441695-transform-matrix-decomposition/(雖然這種方法的效率與複雜度須要另外討論,但畢竟也是一個途徑) it
不過通常狀況下,咱們對於場景中三維模型的變換基本上都是進行三向一致的縮放操做,這樣的話M就是一個正交的矩陣,如此一來就有S等於M,於是直接使用M對法向量做變換也不會有什麼問題出現(或者有差異也被忽略了^_*)。不過任意的縮放變換是建模工具的一個基本需求,於是在作工具時須要重視這一問題。 io