OpenGL中涉及到的矩陣變換


先看兩個問題:

  1. 我們有什麼?答:模型的初始位置座標(三維座標)。
  2. 我們要得到什麼?答:我想要把模型展示在屏幕上展示的二維座標(二維座標)。

從初始位置座標到平面的二維座標經過了下面的流程,後面逐一介紹。
在這裏插入圖片描述

1、局部座標系

局部座標系指的是圖中的LOCAL SPACE,又被稱作本地座標系、本地空間、局部空間等。總是這就是一個小範圍的概念,描述的只是模型本身的座標。也是模型文件中存儲的頂點座標所在的座標系。

2、世界座標系

  • 世界座標系指的是圖中的WORLD SPACE。剛開始接觸座標變換時,會有這樣的疑問,爲什麼要有世界座標系?直接用局部座標系作爲世界座標系爲什麼不行?原因是局部座標系只是相對於單獨一個模型的,當我們想在屏幕上看到很多個模型時,如果我們以某個模型所在的局部座標系爲基準去構造其他的模型,那麼就很有可能會出現所有的模型都疊放在了原點。所以,世界座標用來確定每個模型的局部座標系的位置。也就是每個模型在三維空間中的位置。世界座標系所描述的空間通常會被抽象成"場景"或者"世界"。

  • 爲了能讓場景中所有的模型都能進行統一的變換,所以必須將所有的模型自身相對於局部座標系的座標,轉換爲相對於世界座標系中的座標。這個過程只要將模型的座標進行相應的平移變換就能得到。而這一步進行的平移變換,就是圖中提到的模型矩陣(Model Matrix),用模型相對於局部座標系的位置座標右乘一個矩陣就可以得到相對於世界座標系的座標。

2.1 爲什麼要用矩陣?

到這裏應該有個疑問,爲什麼平移要用到矩陣?其實不光是平移,模型在場景中的伸縮、旋轉、視圖變換、投影變換也是通過矩陣變換來做的。應用矩陣來計算這些變換的原因如下:

  1. 在線性代數中,所有的線性變換(見下面解釋)都可以通過構造一個矩陣,並以矩陣乘法的方式完成。
  2. 在圖形變換中,涉及到就是空間映射(通過一個座標系空間的座標求出對應另外一個座標系中的座標就是空間映射)和頂點變換,這這種變換都是線性變換。
  3. 所以,正好可以將圖形中的變換應用線性代數中的矩陣變換來計算,這樣做可以將所有的變換都統一成矩陣變換,也方便GPU在計算座標時進行優化。

線性變換的概念。

  • 線性變換:指的是一個向量空間V到自身的映射。換句話說,一個n維向量在經過線性變換以後仍然是n維向量的變換,並不會導致它變成n+1維或者更大維度的向量。線性變換的數學定義——線性空間V上的一個變換A稱爲線性變換,對於V中任意的元素α,β和數域P中任意k,都有:
    在這裏插入圖片描述

2.2 模型矩陣(Model Matrix)

在模型頂點座標由局部座標系變換到世界座標系的過程中。可以只經過平移變換來進行。除此之外,在這一過程中,也可以隨模型的形態進行設置,例如伸縮、旋轉等。

首先來看最簡單的伸縮變換:假設有一個頂點的座標爲(x,y,z),那麼將該點的x、y、z分別在其分量上伸縮SxS_xSyS_ySzS_z,則變換過程如下:

[xSxySyzSz]=[Sx000Sy000Sz][xyz]=[x1y1z1] \left[ \begin{matrix} x*S_x \\ y *S_y\\ z *S_z \end{matrix} \right] = \left[ \begin{matrix} S_x &0 &0\\ 0 &S_y & 0\\ 0 &0&S_z \end{matrix} \right]*\left[ \begin{matrix} x \\ y \\ z \end{matrix} \right] = \left[ \begin{matrix} x_1 \\ y_1 \\ z_1 \end{matrix} \right]

發現伸縮的過程是可以寫成一個頂點座標左乘一個333*3矩陣(矩陣的乘法可參考這篇文章圖形變換中涉及到的數學知識)來實現的。再看一下平移的過程:發現一個問題,如果像伸縮一樣來處理平移變換,是沒有辦法將平移變換寫成333*3矩陣右乘的形式的
[x+Txy+Tyz+Tz]=[x1y1z1] \left[ \begin{matrix} x+T_x \\ y +T_y\\ z +T_z \end{matrix} \right] = \left[ \begin{matrix} x_1 \\ y_1 \\ z_1 \end{matrix} \right]

解決此問題的方法是用齊次座標(可參考這篇文章圖形變換中涉及到的數學知識)來表示頂點座標,給頂點座標加一個維度再進行相應的計算,就可以將平移變換的過程轉化成下面的流程。

同樣,爲了保證統一,伸縮的過程可以轉換爲:

旋轉過程的變換矩陣有三種,分別是沿着x、y、z軸進行旋轉的矩陣(三個矩陣的由來可參考這篇文章圖形變換中涉及到的數學知識):

3、視圖座標系

       人眼在觀察一個物體,在不同角度不同位置去觀察,看到的效果是不一樣的。所以,在三位場景中,我們除了定義模型本身以外,還需要定義觀察點位置、觀察方向等。定義完觀察點的相關信息以後,就可以得到一個在該觀察點位置所看到場景狀態。這個場景的每個位置的座標也是需要定義的。而定義這個圖像座標的座標系,被成爲視圖座標系

在這裏插入圖片描述

3.1 視圖座標系的定義

  • 觀察點位置(viewPositionviewPosition):世界座標中的一個位置座標。
  • 觀察點方向(viewDirectionviewDirection):viewDirection=viewPositionworldOriginviewDirection=viewPosition-worldOrigin,觀察點方向等於觀察點位置減去世界座標原點。
  • zzviewDirectionviewDirection所在直線作爲視圖座標系的z軸。該方向爲z軸負方向,viewDirection-viewDirection爲z軸正方向。
  • xx:以觀察點爲始點,沿着世界座標系的y軸,去一個向量,我們稱爲UpDirection。用viewDirectionviewDirectionUpDirectionUpDirection進行叉乘,可以得到x軸(爲什麼叉乘可以得到x軸可參考這篇文章圖形變換中涉及到的數學知識)。
  • yy:用z軸和x進行叉乘就可以得到y軸了。

叉乘的幾何意義:兩個向量叉乘可以得到一個與兩個向量都垂直的一個向量。

3.2 視圖矩陣

       視圖矩陣(流程圖中的View Matrix),使用矩陣的好處之一是如果你定義了一個座標空間,裏面有3個相互垂直的軸,你可以用這三個軸外加一個平移向量來創建一個矩陣,你可以用這個矩陣乘以任何向量來變換到那個座標空間。這正是視圖矩陣(流程圖中的View Matrix)所做的,現在我們有了3個相互垂直的軸和一個定義攝像機空間的位置座標,我們可以創建視圖矩陣了。

4、投影座標系

  • 以上的變換都是針對三維的頂點座標進行變換。但是最終我們呈現在屏幕上的圖像是一個二維座標。將一定範圍內的座標轉化到標準化設備座標系的過程(而且它很容易被映射到2D觀察空間座標)被稱之爲投影(Projection),因爲使用投影矩陣能將3維座標投影(Project)到很容易映射的2D標準化設備座標系中。

  • 除了將三維座標轉換成二維座標以外,場景中的模型座標並不是所有的點都需要被呈現出來,因爲屏幕的大小是固定的,如果模型被擴大了很多倍,或者場景內的模型非常多,不可能將場景內的內容全部都呈現出來,需要將場景進行裁剪。

例如,每個維度都是從-1000到1000。投影矩陣接着會將在它指定的範圍內的座標轉換到標準化設備座標系中(-1.0,1.0)。所有在在範圍(-1.0,1.0)外的座標都不會被繪製出來並且會被裁剪。在投影矩陣所指定的範圍內,座標(1250,500,750)將是不可見的,這是由於它的x座標超出了範圍,隨後被轉化爲在標準化設備座標中座標值大於1.0的值並且被裁剪掉。

所以在頂點座標經過視圖座標系到投影座標系需要做兩件事:將三維座標轉爲二維座標(通過投影實現)和裁剪(由投影空間決定)。爲了將頂點座標從觀察空間轉換到投影座標系,我們需要定義一個投影矩陣(Projection Matrix),它指定了座標的範圍。

投影空間分爲兩種:正射投影(Orthographic Projection)透視投影(Perspective Projection).

  • 正射投影(Orthographic Projection):矩陣定義了一個類似立方體的平截頭體,指定了一個裁剪空間,每一個在這空間外面的頂點都會被裁剪。創建一個正射投影矩陣需要指定可見平截頭體的寬、高和長度。在這裏插入圖片描述

正射投影矩陣:一個立方體投影空間的確定需要6個,即 : left , right , bottom , top , near , far

(正射投影矩陣)2/(rightleft)00(right+left)/(rightleft)02/(topbottom)0(top+bottom)/(topbottom)002/(farnear)(far+near)/(farnear)0001 \begin{matrix} 2 / (right - left) & 0 & 0 & -(right + left)/(right - left)\\ 0 & 2 / (top - bottom) & 0 & -(top + bottom)/(top - bottom)\\ 0 & 0 &-2 / (far - near) & -(far + near)/(far - near) \\ 0 & 0 & 0 & 1 \end{matrix} \tag{正射投影矩陣}

  • 透視投影(Perspective Projection):它是從某個投射中心將物體投射到單一投影面上所得到的圖形。透視圖與人們觀看物體時所產生的視覺效果非常接近。

透視投影矩陣 : 四棱錐可視空間是由以視點爲頂點的四棱錐構成 , 確定四棱錐可視空間的參數有fov(可視頂面和底面的夾角) , aspect(遠/近裁切面的寬高比) , near(近裁切面位置) , far(遠裁切面位置) 。

(正射投影矩陣)Math.cos(fov/2)/(aspectsin(fov/2))0000Math.cos(fov/2)/Math.sin(fov/2)0000(far+near)/(farnear)2nearfar/(farnear)0010 \begin{matrix} Math.cos(fov/2) /(aspect * sin(fov/2)) & 0 & 0 & 0\\ 0 & Math.cos(fov/2) /Math.sin(fov/2) & 0 &0\\ 0 & 0 & -(far + near) / (far - near) & -2 * near * far / (far - near)\\ 0 & 0 & -1& 0 \end{matrix} \tag{正射投影矩陣}

投影座標系可以理解爲投影空間中近裁切面接收投影時的一個二維座標系。

5、屏幕座標系

  • 最開始的頂點座標在經過以上4個座標系、3個變換矩陣。得到了當前的座標。每個矩陣被運算的順序是相反的(記住我們需要從右往左乘上每個矩陣)。最後的頂點應該被賦予頂點着色器中的gl_Position且OpenGL將會自動進行透視劃分和裁剪。最終經過投影后的點的座標爲:
  • 頂點着色器的輸出需要所有的頂點都在裁剪空間內,而這是我們的轉換矩陣所做的。OpenGL然後在裁剪空間中執行透視劃分從而將它們轉換到標準化設備座標。OpenGL會使用glViewPort內部的參數來將標準化設備座標映射到屏幕座標,每個座標都關聯了一個屏幕上的點(屏幕上的點就是由屏幕座標系來定義的)。這個過程稱爲視口轉換

到此爲止,一個3維的頂點座標經過一系列的變換最終被映射到了屏幕上。

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