Part1 轉換流程之頂點轉換
物體頂點是相對於物體自身坐標系而言的數據,要進行一系列轉換才最后顯示在屏幕上:
1.物體坐標系到世界坐標系。
乘以World矩陣,包含了物體的平移旋轉和縮放。
2.世界坐標系到相機坐標系。
乘以View矩陣。
該矩陣實際上是相機相對於世界坐標系轉換的逆矩陣。
所以相機的世界坐標系位置可以用View矩陣的逆矩陣的平移向量表示出來。
3.相機坐標系到標准視體空間的變換。
乘以Projection矩陣。
根據Projection矩陣的不同,有正交和投影變換兩種結果。
這步操作的實際意義是將視錐空間內的點變換進入一個標准觀察體,從而方便剪裁。
不同API標准觀察體的設置不同:
DirectX的標准觀察體最小拐角(-1,-1,0)最大拐角(1,1,1),
OpenGL最小拐角(-1,-1,-1)最大拐角(1,1,1),二者區別在於Z的范圍不同。
注意透視變換是非線性變換,會使得w值變化,不再是1。
4.完成剪裁后接着對應到屏幕空間。
這步完成3D到2D的映射,對應成屏幕像素顯示。
說明:以上只是對頂點變換的簡單介紹,還有很多沒有詳細討論的地方。
因為關於3D流水線的很多地方感覺理解的不是很實在,所以以后有空的時候再總結吧。
Part2 轉換流程之法向量變換
光照計算常常需要用法向量,但是法向量的轉換和頂點轉換並不完全相同。
不同點主要體現在上述過程中的第一步。即從物體坐標系變換到世界坐標系。
首先法向量表示的是方向,平移是不必要的。(由於法向量多是3D向量或第四位為0,其實變換矩陣的平移部分是不起作用的)。
那么法向量變換就只剩旋轉和縮放。
而法向量的旋轉和頂點的旋轉保持一致即可,因為轉過的角度是相同的。
但是直接用World矩陣直接對法向量進行變換有可能是不對的!!
為什么呢,主要就是在於縮放有可能不是三個坐標方向的等比例縮放。
因為如果模型被不成比例的縮放,在不同方向上會有不同程度的拉伸或者壓縮,頂點的坐標會因而伸縮。
但是如果對法向量進行同樣的伸縮,那么法向量將不再垂直於對應的表面(頂點的法向量是該頂點所在幾個表面法向量的平均值)。
此時要對法向量進行正確的變換,應該是對其進行相反的縮放(比如xy是1:2縮放,那么法向量xy就要2:1縮放。)
所以法向量的變換矩陣中縮放矩陣應該是原來頂點變換縮放矩陣的逆矩陣。
這個怎么做到呢,如前所述,縮放矩陣並不是正交矩陣,不能通過轉置來得到逆矩陣。直接對原來的world矩陣求逆的話,旋轉的部分也同時被求逆了。但是旋轉又要求用原來的旋轉。
但是旋轉矩陣是正交矩陣,轉置后即可得到逆矩陣。
於是可以采用這樣的方法:對World矩陣求逆,這樣就同時得到了旋轉和縮放的逆,然后進行轉置再將旋轉矩陣變回來,因為縮放系數在對角線上所以不會有影響。這樣得到的變換矩陣就可以用來正確變換法向量了。
關於轉置,可以變換矩陣和向量相乘的順序,這樣就相當於和轉置矩陣相乘了。
所以要做的只是求出逆矩陣,然后變換矩陣和向量原來的相乘順序。
注意就是因為法向量變換的問題是由於非等比例縮放引起的,如果原來的World矩陣三個方向縮放系數相等,那么用原來的World矩陣變換法向量是沒有問題的。