接著上一篇再繼續(xù)講兩個比較重要的變換矩陣:透視投影和正交投影。在OpenGL中,如果想對模型進行操作,就要對這個模型的狀態(tài)(當前的矩陣)乘上這個操作對應的一個矩陣。如果乘以變換矩陣(平移, 縮放, 旋轉), 那相乘之后, 模型的位置會改變,如果乘以投影矩陣(將3D物體投影到2D平面), 模型的投影方式被設置,如果乘以紋理矩陣, 模型的紋理方式被設置,當前矩陣如何改變就看進行了哪些操作(與什么矩陣相乘)。
透視投影:
透視投影是模仿人眼觀察物體,有遠小近大的效果,所以這種投影更加真實。

對應函數(shù)為:GLKMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ)
GLKMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ)
調用GLKMatrix4MakePerspective函數(shù)創(chuàng)建一個對稱的透視投影矩陣。其中參數(shù)fovyRadians定義視野在Y-Z平面的角度,范圍是[0.0,180.0];參數(shù)aspect是投影平面寬度與高度的比率;參數(shù)nearZ和farZ分別是近遠裁剪面到視點(沿Z負軸)的距離,它們總為正值。
圖形管線會根據(jù)設置的fovyRadians、nearZ和farZ參數(shù)確定一個可視空間區(qū)域,由上下左右遠近6個平面組成,在可視區(qū)域內的圖形會被投影到近平面,之外的物體會被裁減掉。
物體的透視投影效果:
透視投影代碼:
// 旋轉
GLKMatrix4 rotateMatrix = GLKMatrix4MakeRotation(changeValue , 0.0, 1.0, 0.0);
// 平移
GLKMatrix4 translateMatrix = GLKMatrix4MakeTranslation(0, 0, -3.0);
// 透視投影
float aspect = self.view.frame.size.width / self.view.frame.size.height;
GLKMatrix4 perspectiveMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90), aspect, 0.1, 20.0);
// GLKMathDegreesToRadians(90) 是將角度轉為弧度
transformMatrix = GLKMatrix4Multiply(translateMatrix, rotateMatrix);
transformMatrix = GLKMatrix4Multiply(perspectiveMatrix, transformMatrix);
透視投影矩陣默認的可視方向是向Z軸負方向。本例中的三角形Z坐標為0顯然不在可視空間區(qū)域內,所以上面的代碼中我們先將三角形進行了Z軸平移:GLKMatrix4MakeTranslation(0, 0, -3.0)。為了演示出動態(tài)的效果,我再加上了旋轉矩陣:GLKMatrix4MakeRotation(changeValue , 0.0, 1.0, 0.0),最后把平移、旋轉和透視投影相乘,賦值到頂點著色器中。透視投影效果:
正交投影:
正交投影屬于平行投影, 投影線平行, 視景體是長方形的, 投影的內容不會出現(xiàn)近大遠小的效果

left和right是設置x軸的最小坐標和最大坐標,bottom和top設置y軸,nearZ和farZ設置Z軸。這樣創(chuàng)建的投影矩陣是一個長方體空間區(qū)域。
// 旋轉
GLKMatrix4 rotateMatrix = GLKMatrix4MakeRotation(changeValue , 0.0, 1.0, 0.0);
// 正交投影
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
GLKMatrix4 scaleMatrix = GLKMatrix4MakeScale(300, 300, 300);
GLKMatrix4 orthMatrix = GLKMatrix4MakeOrtho(-viewWidth/2, viewWidth/2, -viewHeight/2, viewHeight/2, -5, 5);
由于圖形原來非常小,所以這里加了一個縮放矩陣。
看下最終效果:
這里用三角形展示的效果不太好,如果改為矩陣那就非常清楚了。這個有興趣的朋友可以自己嘗試一下。
在上傳的源碼中我已經改用矩形展示了。