2011-12-13 323 views
11

我在OpenGL中製作了一個遊戲,其中我在世界空間中有幾個物體。我想要製作一個功能,讓我可以接收對象的位置(3D)並將其轉換到屏幕的位置(2D)並返回。C++/OpenGL將世界座標轉換爲屏幕(2D)座標

我知道下面的可變因素的對象,保護矩陣和視圖矩陣的3D位置:

Matrix projectionMatrix; 
Matrix viewMatrix; 
Vector3 point3D; 

回答

29

要做到這一點改變,你必須首先把你的模型空間中的位置和改造他們夾-空間。這是通過矩陣乘法完成的。我將使用GLSL風格的代碼,使我在做很明顯的:

vec4 clipSpacePos = projectionMatrix * (viewMatrix * vec4(point3D, 1.0)); 

通知我如何轉換您的3D載體引入4D向量乘法之前。這是必要的,因爲矩陣是4x4,並且不能將4x4矩陣與3D矢量相乘。你需要第四個組件。

下一步是將此位置從剪輯空間轉換爲標準化的設備座標空間(NDC空間)。 NDC空間在所有三個軸的範圍[-1,1]內。這是由第四將最前面的三個座標做:

vec3 ndcSpacePos = clipSpacePos.xyz/clipSpacePos.w; 

顯然,如果clipSpacePos.w是零,你有問題,所以你應該檢查事前。如果它是零,那意味着物體在投影平面中;它的視圖空間深度爲零。而這樣的頂點會被OpenGL自動剪裁。

下一步是從這個[-1,1]空間轉換到窗口相對座標。這需要使用您傳遞給glViewport的值。前兩個參數是窗口左下角的偏移量(vec2 viewOffset),後兩個參數是視口區域的寬度/高度(vec2 viewSize)。鑑於這些,窗口空間的位置是:

vec2 windowSpacePos = ((ndcSpacePos.xy + 1.0)/2.0) * viewSize + viewOffset; 

而這就像你一樣。請記住:OpenGL的窗口空間相對於窗口的左下角的而不是左上角的

+0

如何在沒有使用着色器程序的情況下實現這一目標?我的意思是,只是普通的OpenGL函數? – mr5

+0

我經過一段時間谷歌搜索後發現的最佳答案,也是我發現的唯一一個提到不得不由clipSpacePos.w進行分割的人。 –

+2

注意:如果窗口空間相對於窗口的左上角,那麼'windowSpacePos'應該是 'vec2(((ndcSpacePos.x + 1.0)/ 2.0)* viewSize.x + viewOffset.x,( (1.0 - ndcSpacePos.y)/ 2.0)* viewSize.y + viewOffset.y)' –

相關問題