行動裝置的屏幕是二維平面,要想把一個三維場景渲染在手機二維屏幕上,需要利用OpenGL中的矩陣投射,將三維空間中的點映射到二維平面上。三維矩陣的相關知識是學習OpenGL最重要的課程之一。
線性代數學習OpenGL三維投射知識之前,我們得事先了解下一些基礎的線性代數知識,如向量運算,矩陣運算。
向量運算向量: 指一個同時具有大小和方向的幾何對象,因常常以箭頭符號表示以區別於其它量而得名。
向量加減向量的加(減)法定義是分量的相加(減),即將一個向量中的每一個分量加上(減去)另一個向量的對應分量:
向量相乘點乘叉乘矩陣運算矩陣簡介數學上,一個 m x n 的矩陣是一個m行n列元素排列成的矩形陣列。以下是一個由6個數字元素構成的3行3列的矩陣:
矩陣運算規則矩陣的加減矩陣與標量之間的加減:
矩陣與矩陣之間的加減:
矩陣數乘
矩陣相乘
單位矩陣在OpenGL中,由於大部分的向量都是4分量 (x,y,z,w),所以我們通常使用 4x4 的變換矩陣。當中最簡單的變換矩陣是單位矩陣。單位矩陣是一個除了對角線以外都是0的NxN矩陣。
單位矩陣通常是生成其他變換矩陣的起點。
縮放矩陣對一個向量進行縮放指的是對向量的長度進行縮放,而保持它的方向不變。
位移矩陣位移是在原始向量的基礎上加上另一個向量從而獲得一個在不同位置的新向量的過程,從而在位移向量基礎上移動原始向量。
(Rx,Ry,Rz)代表任意旋轉軸,θ是角度:
OpenGL在每次頂點著色器運行後,所有頂點都為標準化設備坐標,每個頂點(x,y,z)都應該在-1.0d到1.0之間。通常情況下,我們會根據畫布(屏幕)的大小設定一個坐標範圍,在頂點著色器中將這些坐標轉換為標準化設備坐標。在項目中,物體坐標最終被轉化為屏幕坐標之前會變換到多個坐標系統,因為在相應的過度坐標系中做特定運算會方便容易一些。對我們來講,一般情況下需要用到5個不同的坐標系統:
局部空間(Local Space):物體起始坐標;如一個正方體a,原點是正方體的中心O1(0,0,0)。
世界空間(World Space):物體在更大的空間範圍的坐標;如我們構造了一個圓球來表示世界,圓心為世界坐標原點O2,把正方體放在圓球中t(x1,y1,z1)位置。那么正方體a的圓心O1在世界系統會轉化為(x1,y1,z1)。物體的坐標從局部坐標變換到是世界坐標由模型矩陣(Model Matrix)負責實現。
模型矩陣是一種變換矩陣,能對物體進行位移,縮放,旋轉。
觀察空間(View Space): 觀察空間是將世界坐標轉化為用戶視野前方的坐標。一般用一個觀察矩陣(View Matrix)來完成轉換。
裁剪空間(Clip Space):頂點著色器運行到最後,OpenGL期望所有的坐標落在一個特定的範圍內,且任何在這個範圍之外的點會被裁剪掉。為了將頂點坐標從觀察變換成裁剪空間,需定義一個投影矩陣(Projection Matrix),它指定一個範圍的坐標,比如每個維度上的 -100 到 100。投影矩陣會將在這個指定範圍內的坐標變換為標準化設備坐標的範圍(-1。0,1.0)。使用投影矩陣能將3D坐標投影到2D的標準化設備坐標系中。
將觀察坐標變換為裁剪坐標的投影矩陣分為兩種不同的形式:正交投影矩陣(Orthographic Projection Matrix),透視投影矩陣(Perspective Projection Matrix)。
正交投影(Orthographic Projection)正交投影矩陣定義一個立方體的平截頭箱,在這個立方體之外的頂點都會被裁剪掉。
正交投影矩陣直接將坐標映射到2D平面上。不過正交投影沒有透視效果,遠處箱子和近處箱子投射到平面上是一樣大的,這和我們日常生活中看東西時近大遠小的視覺效果是不符的。要解決這個問題,我們需要用到透視投影。
透視投影(Perspective Projection)透視投影定義一個大平截頭體。透視投影有兩種表述方式:
glFrustum (left, right, bottom, top, zNear, zFar);
left,right,bottom,top定義near裁剪面大小,zNear和zFar定義從觀察點到遠近兩個裁剪面的距離。這六個參數定義出六個裁剪面構成的視錐體。
gluPerspective(fovy, aspect, zNear, zFar);
fovy: camera 在 y 方向上的視線角度(0~180)
aspect定義近截面的寬高比 aspect=w/h
zNear, zFar: 觀察點到遠近兩個裁剪面的距離
透視體參數轉換車過視錐體參數:
tan(fovy/2) = (h / 2)/zNear -> h w = h * aspect -> w
矩陣組合基於前面介紹的4個變換矩陣:模型矩陣,世界矩陣,觀察矩陣和投影矩陣。一個頂點坐標將會根據以下過程變換到裁剪坐標:
Vclip=Mprojection⋅Mview⋅Mmodel⋅Vlocal
注意矩陣運算的順序是從右往左閱讀,最終計算出來的頂點賦值給gl_Position
3D Demo至此我們了解了OpenGL 3D渲染中需要知道的矩陣知識,運用這些知識,便可進行開發OpenGL3D程序了;蘋果官方提供一個很好的GL demo GLEssentials
結束作者簡介:peicheng(程培),天天P圖iOS工程師