directx 3d與opengl座標系統的差異性,給我們帶來很大的麻煩,讓跨平台程式設計的新手很困惑。最近在做乙個跨平台的遊戲,仔細看了下兩者的矩陣,發現並沒有什麼大區別,將d3d左手系的矩陣傳遞給opengl shader完全可以正常工作。
先說一下兩者一些概念上的區別:
(1)座標系統不同
d3d左手座標系,opengl右手座標系
(2)矩陣行序不同
d3d行優先,opengl列優先。這兩個不同,直接導致了座標變換順序與矩陣乘法順序的相反性。如果是先縮放,再旋轉,最後平移,對應的矩陣分別為s、r、t,則d3d的最終矩陣為m = s * r * t,opengl為m = t * r * s
(3)裁減空間z取值範圍不同
d3d是[0, 1],opengl是[-1, 1]
表面上來看,兩者矩陣差別很大,但其實不然。
1.左右手座標系
對於顯示卡裝置來說,
裝置座標系是左手座標系
,即z軸指向螢幕裡面,z值越大表示距離視線越遠。因此,opengl的右手系,在進入裁減空間的時候,會轉換成左手系。這也就是說,在渲染管線內部,座標系是統一的。不管是左手座標系矩陣,還是右手座標系矩陣,只要變換到裁減空間中的點是左手系就可以了。
2.矩陣行序
行矩陣和列矩陣,在邏輯上乙個是另乙個的轉置,但在物理存貯結構上卻是完全一致的。如乙個平移變換(x, y, z):
需要注意的是,矩陣乘法並不關心矩陣是行矩陣還是列矩陣,都是按照第乙個矩陣的行去乘以第二個矩陣的列。對於列矩陣而言,這正是其蹩腳的地方,為了保證乘法意義的有效性,其座標變換順序跟矩陣乘法順序恰好相反。
還要注意一點,在shader中,opengl的矩陣乘法規則跟d3d是不同的。按照矩陣乘法規則(第乙個矩陣行*第二個矩陣列):
d3d矩陣乘法: ma(0 1 2 3) * mb(0 4 8 12)
opengl矩陣乘法: ma(0 4 8 12) * mb(0 1 2 3)
因此,對於opengl shader而言,變換順序跟矩陣乘法順序依然是反的。如果我們能將傳入opengl shader的矩陣做一次轉置,那麼opengl shader的矩陣乘法意義將跟d3d shader完全一致!
3.修改投影矩陣
由於opengl的裁減空間z取值範圍為[-1, 1]跟d3d的[0, 1]不同,我們不能簡單的使用d3d投影矩陣,必須重新定義d3d投影矩陣。
[cpp]view plain
copy
?void matrix::perspectiveprojectionlh2( float fov, float aspectratio,
float nearplane, float farplane )
void matrix::perspectiveprojectionlh2( float fov, float aspectratio,
float nearplane, float farplane )
4.總結使用左手系變換來統一兩個平台是比較方便的。總結一下修改opengl渲染管線的步驟:
(1)在c++層統一使用左手座標系變換;
(2)修改投影矩陣,以適應裁減空間z座標範圍[-1, 1];
(3)矩陣在傳入shader的時候,將矩陣的轉置矩陣傳入;
(4)在shader層,統一使用左手座標系變換。
如果,不想修改shader中的變換,只用做到(1)和(2)就夠了。
推導投影矩陣
跨越opengl和d3d的鴻溝
統一D3D與OpenGL座標系統
2014年07月20日 16 23 03 directx 3d與opengl座標系統的差異性,給我們帶來很大的麻煩,讓跨平台程式設計的新手很困惑。最近在做乙個跨平台的遊戲,仔細看了下兩者的矩陣,發現並沒有什麼大區別,將d3d左手系的矩陣傳遞給opengl shader完全可以正常工作。先說一下兩者一...
OpenGL和D3D的區別
1 世界座標系 opengl為右手座標系d3d為左手座標系 2 裁剪空間 opengl中z的範圍 1.0,1.0 d3d為 0.0,1.0 3 shader shader開始是以彙編的形式出現,在推出一段時間後,就出現如下幾種類c的高階語言 注 這些高階語言會被編譯成顯示卡識別的彙編 opengl的...
D3D世界座標變換到螢幕座標
d3d中世界座標變換到螢幕座標,可用於繪製座標軸文字.code d3d世界座標轉螢幕座標 private function vector2point x as single,y as single,z as single as point 是有順序的,先世界 在檢視 在投影 dim vectorop...