下图中的描述为我们清晰地解释了MVP矩阵的作用
理解:
我们可以认为把真实世界中的3D物体渲染到屏幕上是一个类似用摄像机拍摄照片的过程,要经过如图几个步骤,1.放置摄像机(视图变换) 2.放置模型(现实世界中的物体,经过模型变换)3.设置焦距(投影变换),第一个步骤我们可以理解为视图变换,就是摄像机在某个位置,观察到物体的成像方式,摄像机放在不同位置,成像效果肯定不一样,所以通过视图变换,我们可以改变摄像机的位置;模型变换就是可以理解为物体的运动(旋转,平移,缩放),最后我们经过上两步的变换之后,要把成像的结果投影到裁剪空间,这里就是投影变换,投影到裁剪空间的坐标,最后经过视口变换,转换为物理设备坐标系,展示最终成像效果。
OpenGL实际运行中,先进行模型变换(Mdoel transform),然后是视图变换(view transform),最后是投影变换(projection transform).
在这个Demo中,我们不再直接以字符串的形式加载着色器了,而是把着色器语言放在文件中,加载文件的形式。
下面我们结合代码来讲解各个矩阵。
1.模型变换
GLKMatrix4 translate1 = GLKMatrix4MakeTranslation(-0.7, 0, 0 );
GLKMatrix4 rotate1 = GLKMatrix4MakeRotation(varyFactor * M_PI * 2, 0, 1, 0);
GLKMatrix4 modelMatrix1 = GLKMatrix4Multiply(translate1, rotate1);
这里先进行旋转变换,然后平移变换,结合成一个变换矩阵,这里就是对模型的变换。
2.视图变换(摄像机)
GLKMatrix4 cameraMatrix = GLKMatrix4MakeLookAt(0, 0, 2 * (varyFactor + 1), 0, 0, 0, 0, 1, 0);
这个函数的原型是
GLKMatrix4MakeLookAt(<#float eyeX#>, <#float eyeY#>, <#float eyeZ#>, <#float centerX#>, <#float centerY#>, <#float centerZ#>, <#float upX#>, <#float upY#>, <#float upZ#>)
前面三个参数构成摄像机在空间中的位置(eyeX,eyeY,eyeZ),中间三个参数构成观察点(centerX,centerY,centerZ),这就表示摄像机看向的点,最后三个参数表示摄像机向上的朝向(upX, upY, upZ),参照下图可以加深理解。
改变这几个参数就能模拟出摄像机在3D世界中通过不同角度拍摄物体的效果。
3.投影矩阵
这个在上一篇文章中已经描述过,就是最终投影在视平面的变换。
这里采用的是透视投影,模仿人眼观察3D世界的效果。
最后还有一个视口变换(viewport transform),不过GLKit已经帮我们完成了操作。
最终代码实现的效果如下: