笛卡尔坐标系: 我们的顶点使用的是标准化的笛卡尔坐标,X、Y、Z轴都是(-1,1)的范围,映射到屏幕上就是viewport视口的中心点是原点,2D视口的左上、左下、右上、右下分别是(-1,1,0)、(-1,-1,0)、(1,1,0)、(1、-1,0),
只考虑2D的情况下我们绘制一个三角形时,它的表现如下:
顶点数组:
纹理坐标系: 每一个顶点都对应一个纹理坐标以确定怎么从纹理中读取颜色数据,纹理坐标是以它的左下角为原点的,右上角为(1,1)的标准化笛卡尔坐标系。
上面这个顶点坐标和纹理坐标最终展示的是一张完整的纹理图片在屏幕的正中央,长宽都为viewport的一半。
观察空间(略,还未详细研究过,只知道可以通过改变观察矩阵,转换视角,类似于人转动头导致看到的东西不一样了)
裁剪空间(投影矩阵): 在一个顶点着色器运行的最后,OpenGL期望所有的坐标都能落在一个特定的范围内,且任何在这个范围之外的点都应该被裁剪掉(Clipped)。被裁剪掉的坐标就会被忽略,所以剩下的坐标就将变为屏幕上可见的片段。这也就是裁剪空间(Clip Space)名字的由来。
因为将所有可见的坐标都指定在-1.0到1.0的范围内不是很直观,所以我们会指定自己的坐标集(Coordinate Set)并将它变换回标准化设备坐标系,就像OpenGL期望的那样。
通俗地讲,意思就是opengl在视口映射的是一个标准化的正方体空间,只有所有坐标值(x、y、z的值)在-1到1之间的内容才会被渲染出来(可见),这与我们设备(屏幕)坐标系存在一个转换关系,我们为了方便转化,所以定义了投影矩阵去处理这2者之间的映射关系。
● 正交投影和透视投影矩阵
正交投影:
正交投影所观察到的物体不会因为远近而呈现不同的大小,所以它一般适合做纯2D的东西。
创建一个正交投影: let orthMatrix = GLKMatrix4MakeOrtho(0, viewportSize.x, viewportSize.y, 0, -1.0, 1.0)
viewportSize即你设置的viewport的size,参数也很明了:
这样,你如果想绘制一个在viewport上position为(100,100)的物体时,只需要在顶点着色器中用输出的位置坐标乘以这个正交投影矩阵即可正确绘制出物体。
透视投影: 如果你曾经体验过实际生活给你带来的景象,你就会注意到离你越远的东西看起来更小。这个奇怪的效果称之为透视(Perspective)
在GLKit中我们可以创建一个透视投影矩阵:
参数
● 视野角度
● viewport的aspect
● near的z轴坐标
● far的z轴坐标
物体变换的组合与矩阵:
我们为上述的每一个步骤都创建了一个变换矩阵:模型矩阵、观察矩阵和投影矩阵。
注意矩阵运算的顺序是相反的(记住我们需要从右往左阅读矩阵的乘法)。
注意:物体的运动变换顺序应该遵循先缩放、后旋转、再平移,为什么,有一篇博文写的比较详细:为什么要先缩放再旋转最后平移
最终gl_position = M(projection) * M(translation)*M(rotation)M(scale) vec4(vertex)
这就是物体的变换。