Ogl Step6 Translation Transformation
背景
这一节开始介绍3D环境下物体的转换。通用的方式是用矩阵或多个矩阵连乘最后乘以顶点坐标来实现转换。后面的每一节都会详解一种转换。
下图是把左图的三角形平移到右图的位置。
一种方式是提供向量的位置作为一个一致变量给着色器然后在处理每一个顶点是加上这个向量来实现平移的效果。然而,这种方式不是通用的转换方式。另外的,如果这个顶点值改变了,那么后面的转换就是基于这个被改变的顶点进行转换了,而不是平移前的转换了。这很麻烦。一个更好的方式是用一个矩阵代表平移乘以其他的转换矩阵。但是你无法找到一个矩阵乘以左图三角形的左下角的点(0,0),能够得到(1,1)。实际情况是你无法在二维矩阵实现这种转换。通用的公式是M * P = P1(x + v1, y + v2, z + v3).我们需要的是一个矩阵M和一个点P(x, y, z)和一个向量V(v1, v2, v3)。矩阵M平移P到P+V的位置。在P1中我们观察到P1每一维的值是对应的P的值和V的值相加的结果。左边的值可以认为是与单位阵相乘的结果:I * P = P(x, y, z)。所以我们从单位阵开始去寻找一个能够实现右边的每一维的相加结果(…+V1, …+V2, …+V3)的矩阵。 如下图:
由上可以得出两个结论:
1. a, b, c, d, e 和 f 其中的任意两个会对每一维度有影响,所以它们必须为0,如此又变为单位矩阵。
2. 因为x,y,z会影响三个维度的值,所以也必须为0.这样的话向量变为零向量,而零向量转换之后还是零向量。
我们必须找到一个矩阵能够提供如下的运算:
所以我们必须找到一种方式加上v1-v3,上面的a到f必须为0.我们把矩阵增加一行和一列。变为4X4的矩阵。把向量也增加一个维度w变为四维的。最终得到我们的平移矩阵如下:
现在即使x,y,z都为0.我们也可以实现平移了。
用4维向量来表示3维的向量也成为齐次坐标,在3D图形中是非常流行的方式。第四维称作’w’。在之前的着色器中gl_Position也是齐次坐标。w维在3D投影到2D中扮演着十分重要的角色。在一般情况下点使用w=1,向量则用w=0.原因是点可以被平移而向量不行。你可以改变向量的长度和方向,所有长度和方向一样的向量被认为是一样的,向量是相对的。所以如果w=0,向量乘以平移矩阵结果是一样的向量。
代码漫游
1 2 3 |
|
我们把4x4矩阵的定义放在math_3.h中。
1
|
|
我们用这个句柄去访问着色器中的一致变量world matrix。
1 2 3 4 5 |
|
上面定义的矩阵会在X坐标[-1 1]之间平移。
1
|
|
这是glUniform*函数的一种形式加载一致变量到着色器中。这里指定了加载4x4的矩阵,当然还有其他的版本2x2, 3x3 …。第一个参数是一直变量的位置(我们可以通过glGetUniformLocation()获取)。第二个参数表示我们要更新的矩阵的个数,第三个参数代表数组的方位顺序,GL_TRUE代表行主顺序的数组,C语言就是用这种顺序的。GL_FALSE代表列主顺序的数组,典型的是Fortran语言。
下面的是着色器的代码。
1
|
|
这是一个4x4矩阵的一致变量,还有mat2 和 mat3分别代表2x2 和 3x3的矩阵。
1
|
|
在顶点缓冲区中三角顶点是3维的,上面的语句是把它扩充到4维,用1填充。有两种方式来表示4维的顶点,一种是像上面那样,先定义一个3维的顶点,然后在顶点缓冲区中去扩充。第二种是直接定义一个4维的顶点。很明显第二种方式比较浪费空间,因为第4维的值一直是1. 更好的方式是第一种,保留原先的3维的顶点然后在着色器中去连接第四维w。在GLSL中的语法是’vec4(Position, 1.0)‘。 总结:在每一帧中我们都生成一个平移矩阵,实现X坐标在[-1 1]之间平移。三角形被平移的归一化盒子外面的将被裁剪。