現代OpenGL+Qt學習筆記之五:OpenGL矩陣變換

現代OpenGL+Qt學習筆記之五:OpenGL矩陣變換

主要內容

   主要是關於OpenGL中的矩陣變換,通過介紹一個點的變換過程,也可以幫助理解OpenGL的管線的執行過程。沒有非常詳細的數學和幾何變換內容的介紹,好在QMatrix4x4已經幫我們實現了所有的矩陣變換功能。

概述

  在OpenGL管線中,頂點位置、法向等幾何數據在進行光柵化過程之前會通過頂點操作和圖元裝配進行變換。在瞭解這些變換之前,需要先了解幾個不同的座標系統。
幾何變換

物體座標

  所謂物體座標,就是物體的局部座標系,在進行變換之前,它具有初始的位置和初始朝向。在OpenGL固定管線中,要對物體進行變換,通常是通過glRotatef()、glTranslatef()和glScalef(),分別實現對物體的旋轉、平移和縮放。

視點座標

  視點座標時通過模型視圖矩陣(GL_MODELVIEW matrix)和物體座標相乘得到的。即通過模型視圖矩陣將物體空間轉換到視點空間中。在OpenGL中,模型視圖矩陣是模型矩陣(Mode)和視圖(View)矩陣的結合(MviewMmodel ),其中模型矩陣是將物體從物體空間變換到世界空間中,而視圖矩陣是將世界空間變換到視點空間中。

這裏寫圖片描述

  注意到,在OpenGL中是沒有獨立的矩陣的,因此爲了模擬相機變換。那麼場景(三維物體和光照)的變換應該是視圖變換的逆變換。換句話說,在OpenGL中定義的相機在視點空間的位置總是在(0, 0, 0),且朝向z軸內部,且不能被改變。關於這部分更加詳細的介紹見後文模型視圖矩陣

  爲了在變換後能夠計算光照等,法向量也需要從物體座標變換爲視點座標。注意到法向量的變換和物體位置的變換是不同的,不能直接乘以模型視圖矩陣,而是要左乘模型視圖矩陣的逆的轉置矩陣。

這裏寫圖片描述

裁切座標

  視點座標再通過投影矩陣(GL_PROJECTION matrix)變換後就得到了裁切座標。投影矩陣定義了視景體和頂點數據投影的方式(垂直投影或透視投影)。該座標系叫做裁切座標的原因是變換後的頂點數據(x, y, z)通過和±w比較後,可能會有部分數據會被裁切。有關這部分更加詳細的介紹見後文投影矩陣

投影變換

歸一化設備座標(NDC)

  歸一化設備座標是將裁切座標除以w後得到的,該過程被稱爲透視除法(perspective division)。改座標和窗口座標或屏幕座標相似,只是還沒有平移和縮放到屏幕像素中。所有3座標軸上數據範圍全部被縮放到-1到1之間。

歸一化

窗口座標(屏幕座標)

  窗口座標是由NDC經過視口變換得到的。NDC通過平移和縮放剛好放入到渲染屏幕當中。在OpenGL管線中,窗口座標隨後會被傳遞到光柵化過程中,成爲一個片元。glViewport()函數是用來設置渲染區域的範圍的,glDepthRange()可以指定窗口座標的z值。窗口座標就是通過上述兩個函數提供的數據計算得到的。

glViewport(x, y, w, h); 
glDepthRange(n, f);

透視除法

  視口變換公式可以通過NDC和窗口座標之間的線性關係得到。
NDC和窗口座標之間的線性關係

OpenGL變換矩陣

4x4變換矩陣

  如上,OpenGL中的變換矩陣是4x4的,且16個元素的存儲順序是列主序的,Qt中的QMatrix4x4矩陣也是一樣。OpenGL中有4種不同類型的矩陣,即模型視圖矩陣、投影矩陣、紋理矩陣和顏色矩陣。在固定管線中,通常通過glMatrixMode()函數切換當前的矩陣類型,但是在目前的可編程渲染管線中,矩陣因爲都是自己定義並傳遞給渲染器,所以基本上不存在矩陣類型的切換問題。

模型視圖矩陣

  模型視圖矩陣是視圖矩陣和模型矩陣的結合。要模擬視圖(相機)的變換,需要對整個場景進行逆變換。幸運的是,很多庫中都有方便的函數接口,實現這樣的逆變換。如glu庫中的gluLookAt()函數。Qt中的QMatrix4x4::LookAt()函數等。

模型視圖矩陣的4列

  如上,將模型視圖矩陣分爲4列來分別考慮。其中最右邊一列是平移變換,其中元素m15 是齊次座標,在投影變換中會用到該元素。

  3元集(m0,m1,m2) , (m4,m5,m6)(m8,m9,m10) 是歐氏變換和仿射變換,如旋轉和縮放,注意到這3個3元集分別對應3個相互垂直的座標軸。
- (m0,m1,m2) : X軸,默認值是(1,0,0)
- (m4,m5,m6) : Y軸,默認值是(0,1,0)
- (m8,m9,m10) : Z軸,默認值是(0,0,1)

  要通過改變矩陣中的元素實現變換需要非常多的線性代數和幾何學內容,要介紹和實現起來也需要一定的內容。好在很多矩陣庫已經幫我們實現了這些功能,在實際用時,只要調用簡單的函數即可。如QMatrix4x4類就是專門爲這些變換設計的類,除了前面介紹的LookAt()函數外,還有translate()、rotate()、scale()和perspective()函數等,分別實現平移矩陣、旋轉矩陣、縮放矩陣和投影矩陣的構建和變換,還有setToIdentity()可以對矩陣進行單位化。

  還有一點需要注意,在對幾何數據進行變換時,通常是左乘一個變換矩陣,而要對一個數據進行多次變換時,其矩陣相乘的順序是和變換順序相反的,如要對一個點v先進行MA 變換,再進行MB 變換,則最終的變換公式爲。

v=MB(MAv)=(MBMA)v.

投影矩陣

  可以這麼說,投影矩陣主要功能有兩個:一是定義視景體,視景體決定了哪些變換後的幾何數據需要被裁切;二是定義了幾何數據投影到屏幕中的方式,即正交投影和透視投影,其中透視投影更加接近我們真實的視覺感覺,因此也更加常用。

視景體

  如圖是透視投影下的視景體示意圖,其中有6個裁切平面,分別是上、下、左、右、遠、近、平面,8個視景體中的頂點也如圖所示。

  其中遠平面的頂點可以通過相似三角形比計算得到,如對於遠平面的左邊:

遠平面左邊頂點

  對於正交投影,其相似比是1,因此遠平面的上下左右值是和近平面相同的。

紋理矩陣

  在紋理映射之前,紋理座標(s, t, r, w)會乘以一個紋理矩陣。在默認情況下紋理矩陣是單位矩陣,紋理會直接映射到物體對應的給定的紋理座標上。通過定義不同的紋理座標矩陣,可以實現對紋理的滑動、旋轉、伸展和褶皺等。

顏色矩陣

  顏色矩陣作用於(r, g, b, a)顏色上,用來實現顏色空間之間的轉換,因爲不是很常用,我也不太懂。。

小結

  本文主要介紹了OpenGL中的矩陣變換過程,包括各種座標系統和變換矩陣。本文的內容主要參考自OpenGL Transformation,其中關於矩陣變換的內容的介紹更加具體和詳細,注重細節,且還有一個可以下載的示例程序,包括源碼。雖然其實現是在固定管線的基礎上實現的,但程序仍然值得一讀,要想了解更加具體的矩陣變換理論也可以參考該網頁。

  有關這部分內容的程序示例,將和後面要介紹的OpenGL光照結合一起介紹,還將在前面固定不動的程序中加入鼠標時間處理功能,實現通過使用鼠標控制物體的旋轉和縮放。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章