按照《OpenGL SuperBible》第四版的描述,OpenGL涉及的变换共4种(ModelView 其实是View和Model的总和,不算单独的变换):View, Model, Projection, ViewPort。这里面,Viewport的变换通过glViewport函数完成即可,不涉及GLSL。下面概述View Matrix, Model Matrix, Projection Matrix。
1) Model Matrix
opengl有自己的坐标系--世界坐标系。坐标系的原点位于窗口中心。默认情况下,Y轴指向窗口上方,Z轴垂直于屏幕,指向外面,X轴水平指向屏幕右边。世界坐标系是一个直角坐标系。
1.1)物体位置不一定处于世界坐标系的中心,而是相对世界坐标的原点偏移。这个偏移操作可以用矩阵变换描述。
1.2)除了平移操作之外,物体的还可能经历旋转操作、伸缩操作,这两种操作也可以用矩阵变换描述。
以上操作的任何一种,或者彼此的组合都对应Model Matrix。在下一篇博客里,我会进一步解释。
2) View Matrix
View变换的作用是指定摄像机的位置,以及其观察方向。
3) Projection Matrix
在确定了物体的形状位置和摄像机的位置以后,最后还要确定摄像机的摄像区域。这由Projection Matrix完成。
此外,按照https://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations 的说法,Projection Matrix之后还有一个“Perspective Division”操作,把物体在世界坐标系的坐标(3D)转化为在设备坐标系(NDC)中的坐标(2D),当然这是OpenGL自行完成的,操作员不需操心。“These clip coordinates are then transformed to normalized device coordinates by the perspective division, which is just a division of all coordinates by the fourth coordinate. (Normalized device coordinates are named as such because their values are between -1 and +1 for all points in the visible part of the scene.)”
4) 矩阵乘法与标量乘法不同,矩阵乘法讲究次序。根据https://en.wikibooks.org/wiki/GLSL_Programming/Vertex_Transformations 的截图,Model Matrix 最前,View次之,Projection最后。假如物体的坐标是(x,y,z,w)或者(r,theta, phi,w)又或者(r, theta, z, w)等等,则这个4维矢量首先与Model Matrix相乘。然后才是view最后Projection。
GLSL默认矢量是列向量。所以一个4乘4的矩阵只能左乘这个列矢量:
以此类推,View Matrix 只能左乘Model Matrix作用后的结果,而Projection Matrix只能作用View和Model作用后的结果:
以上的三种操作可以通过OpenGL的函数glTranslate glRotate gluLookAt glOrtho glPerspective等来实现。但是这样开发者看不到底层的具体操作。我个人并不喜欢这样的操作,而是更倾向于自己生成矩阵,用矩阵直接操作。
在接下来的博客里,我会利用qt的QMatrix4x4类型矩阵生成对应的Model,View和Projection矩阵,来演示如何实现物体的绘制。