3D UI 場景中如何把 X Y 平面的尺寸對映為螢幕畫素

Plato發表於2016-08-08

之前用kanzi的3D UI引擎和cocos-2d的時候都有遇到過這個問題,就如何把3D場景中的XY平面的尺寸對映為與螢幕畫素一一對應的,即XY平面上的一個單位對應平面上的一個畫素。這個在3D UI開發過程中似乎並非必須,或者說很少有人這樣用,因為在遊戲場景中,UI可以處於場景的任何位置,並不侷限於XY平面內。

本次的分享總結所述的3D UI應用場景並非在遊戲中,而是注重在GUI應用上(類似QT等),即使用3D繪圖技術實現的一套類似2D UI一樣效果的引擎,由於UI系統是3D的,故能實現3D的動畫效果。把3D場景中的XY平面的尺寸對映為平面畫素一一對應的優點,是能保持並延續我們在2D開發時候的習慣,方便精準地控制UI控制元件在整個螢幕上的位置佈局。

本文的重點是“3D UI場景中把XY平面的尺寸對映為螢幕畫素”,因此需要您有如下的基本知識:

1、基本3D數理知識;

2、Opengl相關知識;

3、對3D計算機圖形學中“攝像機”概念有所瞭解;

本文包括如下內容:

  •  glm 3D數學庫簡介;
  •  透視視錐體介紹;
  •  使用glm函式庫生成攝像機矩陣;
  •  分析如何調整攝像機和透視視錐體,使的3D場景中的XY平面的尺寸與螢幕畫素對應;

glm 3D 數學庫簡介

什麼是3D數學庫?

所謂3D數學庫,簡單地說就是把在3D計算機程式設計中常用到的資料型別、數學函式、3D處理公式及方法等統一集中起來,方便我們在處理3D場景時使用。

glm 3D數學庫是Opengl官網推薦使用的,包含了幾乎所有我們在處理3D場景是需要的數學函式。

glm的使用也非常簡單,glm提供的原始碼全部都是標頭檔案,我們只需把glm的標頭檔案引用到自己需要使用的工程中即可。

如下例項程式碼中,我們通過glm建立了一個4×4的矩陣,並對該矩陣進行了平移變換(詳細的glm使用介紹,大家可以參考glm官網的教程或文件)。

作為簡介,glm的介紹就到此結束。

透視視錐體介紹

所謂的透視不是你所想的眼睛能看穿牆的意思,別多想了!簡單點,透視就是表示物體近大遠小的效果的意思。

如下圖所示,透視視錐體梯體幾何圖形,它類似於人的眼睛所能看到的範圍,在梯體之外的物體將不可見。

在3D數學裡,用什麼表示這個透視視錐體呢?沒錯,是矩陣!

使用glm函式庫能簡單地生成透視視錐體的矩陣,如下例項程式碼:

(透視視錐體)

上訴例項程式碼中,projection又被成為透視矩陣,所有3D世界裡的物體,經過與projection矩陣相乘後,最終得到的物體將呈現如下兩種特點:

1、遠小近大的效果;

2、處於透視視錐外的物體將被忽略;

使用 glm 函式庫生成攝像機矩陣

本段我們先以一段程式碼起頭,如下:

lookAt函式得到的結果是一個檢視矩陣。有人把檢視矩陣稱為攝像機,也有人把檢視矩陣和透視投影矩陣合在一起稱為攝像機,我喜歡後者。

結合投影矩陣,我們總結一下,攝像機分別由如下引數決定:

1、透視投影矩陣projection決定了攝像機的視野範圍,包括視覺張角FOV、近平面、遠平面;

2、檢視矩陣決定了攝像機的位置、觀察方向;

最後投影矩陣與檢視矩陣將共同決定我們整個場景的顯示效果。

分析如何調整攝像機和透視視錐體,使的3D場景中的XY平面的尺寸與螢幕畫素對應;

OK,終於來到了本文標題討論的問題點,3D UI場景中把XY平面的尺寸對映為螢幕畫素。

其實到現在為止,我們問題的解決方案也清晰了,如何實現“3D UI場景中把XY平面的尺寸對映為螢幕畫素” 呢?是的,就是調整攝像機的位置、遠/近平面、攝像機視角,使XY平面的單位尺寸恰好與平面畫素的單位對應即可。

那麼現在剩下的問題是:如何調整攝像機,使得我們的XY平面恰好與平面畫素對應呢?

在我們繼續之前,我們先來了解一個概念:齊次座標。

百度百科解釋說:齊次座標就是將一個原本是n維的向量用一個n+1維向量來表示。例如,二維點(x,y)的齊次座標表示為(hx,hy,h)(h可以是任意值)。

我們可以理解為,任何三維的點(hx,hy,h),在二維平面上的投影點均為(x,y)。

(透視視錐體側面平面圖)

上圖為透視視錐體側面平面圖,其中GI為透視視錐體的近平面,BF為遠平面,LS和TZ分別為視錐體的兩個不同位置的截面。

從2D平截視錐體看,透視視錐體GBFI範圍內的三維物體最後均被投影到GI平面上。由齊次座標概念可知,點B、U、M在GI平面上的投影均為點M,同理點F、W、P在GI平面上的投影均為點I。

我們:

假設TZ平面為XY平面且與螢幕畫素對應,螢幕高度畫素為h,角∠BAF = FOV (FOV為攝像機張角)

故,UW = h,UV = h/2;

故,

即,由螢幕寬度和攝像機張角,要使XY平面與螢幕畫素對應,我們求得攝像機位置點距離XY螢幕距離長度為AV。

下面的程式碼設定為螢幕左上角為原點是,攝像機的設定。

相關文章