iOS开发学习OpenGL ES系列 -- 投影变换矩阵

接着上一篇再继续讲两个比较重要的变换矩阵:透视投影和正交投影。在OpenGL中,如果想对模型进行操作,就要对这个模型的状态(当前的矩阵)乘上这个操作对应的一个矩阵。如果乘以变换矩阵(平移, 缩放, 旋转), 那相乘之后, 模型的位置会改变,如果乘以投影矩阵(将3D物体投影到2D平面), 模型的投影方式被设置,如果乘以纹理矩阵, 模型的纹理方式被设置,当前矩阵如何改变就看进行了哪些操作(与什么矩阵相乘)。

透视投影:
透视投影是模仿人眼观察物体,有远小近大的效果,所以这种投影更加真实。

如果设置当前矩阵的投影方式就需要使用函数生成透视或正交投影矩阵,然后与当前矩阵相乘。看一下生成透视的效果:

对应函数为:GLKMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ)

GLKMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ)

调用GLKMatrix4MakePerspective函数创建一个对称的透视投影矩阵。其中参数fovyRadians定义视野在Y-Z平面的角度,范围是[0.0,180.0];参数aspect是投影平面宽度与高度的比率;参数nearZ和farZ分别是近远裁剪面到视点(沿Z负轴)的距离,它们总为正值。

图形管线会根据设置的fovyRadians、nearZ和farZ参数确定一个可视空间区域,由上下左右远近6个平面组成,在可视区域内的图形会被投影到近平面,之外的物体会被裁减掉。

物体的透视投影效果:

透视投影代码:

// 旋转
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显然不在可视空间区域内,所以上面的代码中我们先将三角形进行了Z轴平移:GLKMatrix4MakeTranslation(0, 0, -3.0)。为了演示出动态的效果,我再加上了旋转矩阵:GLKMatrix4MakeRotation(changeValue , 0.0, 1.0, 0.0),最后把平移、旋转和透视投影相乘,赋值到顶点着色器中。透视投影效果:
透视投影.gif

正交投影:
正交投影属于平行投影, 投影线平行, 视景体是长方形的, 投影的内容不会出现近大远小的效果

对应的函数为:GLKMatrix4MakeOrtho(float left, float right, float bottom, float top, float nearZ, float farZ)
left和right是设置x轴的最小坐标和最大坐标,bottom和top设置y轴,nearZ和farZ设置Z轴。这样创建的投影矩阵是一个长方体空间区域。

// 旋转
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);

由于图形原来非常小,所以这里加了一个缩放矩阵。

看下最终效果:
正交投影.gif

这里用三角形展示的效果不太好,如果改为矩阵那就非常清楚了。这个有兴趣的朋友可以自己尝试一下。

在上传的源码中我已经改用矩形展示了。

本例源码:LearningOpenGL ES GitHub

推荐阅读更多精彩内容