学过线性代数的同学都知道模型的变换包括平移、旋转、缩放都可以通过矩阵的运算来表示。用于变换的矩阵称为 Model Matrix。
看一个例子,将图中三角形先向右平移 0.5, 再绕 Z 轴旋转 60度
矩阵的运算使用了作者写的 cuon-mattrix.js 这个库
<script src="lib/cuon-matrix.js"></script>
// vertex shader
var VERTEX_SHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'uniform mat4 u_ModelMatrix;\n' +
'void main() {\n' +
' gl_Position = u_ModelMatrix * a_Position;\n' +
'}\n';
// fragment shader
var FRAGMENT_SHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0,0.0,0.0,1.0);\n' +
'}\n';
var canvas = document.getElementById("canvas");
var gl = canvas.getContext('webgl');
if (!initShaders(gl, VERTEX_SHADER_SOURCE, FRAGMENT_SHADER_SOURCE)) {
alert('Failed to init shaders');
}
var vertices = new Float32Array([
0.0, 0.5,
-0.5, -0.5,
0.5, -0.5
]);
initVertexBuffers(gl, vertices);
var modelMatrix = new Matrix4();
// <model matrix> = <rotation matrix> * <translation matrix>
modelMatrix.setRotate(60, 0, 0, 1); // (0,0,1) 表示绕 Z 轴旋转
modelMatrix.translate(0.5, 0, 0);
var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
- uniform mat4 u_ModelMatrix
mat4 是一个 4*4 的矩阵
- gl_Position = u_ModelMatrix * a_Position
计算出变换矩阵乘以 a_Position
- var modelMatrix = new Matrix4();
// <model matrix> = <rotation matrix> * <translation matrix>
modelMatrix.setRotate(60, 0, 0, 1);
modelMatrix.translate(0.5, 0, 0);
先向右平移得到 :
<model matrix> = <translation matrix> * <origin>
再绕 Z 轴旋转 60度得到 :
<model matrix> = <rotation matrix> *(<translation matrix> * <origin>) = (<rotation matrix> * <translation matrix>) * <origin>
先 setRotate 再调用 translate 就是用矩阵里面已经保存的旋转矩阵的值再乘以新计算出来的平移矩阵的值
矩阵乘法满足结合律但不满足交换律,所以先平移再旋转和先旋转再平移是不一样的。
- gl.uniformMatrix4fv(location, transpose, array)
transpose: 是否转置,webgl 中必须为 false
array: 是 column major order (列优先) 数组
这里通过 modelMatrix.elements 得到矩阵对应的数组
webgl 中矩阵数组是以列序排列的,什么是列序呢?假设一个矩阵数组是 [a, e, i, m, b, f, j, n, c, g, k, o, d, h, l, p], 那么它对应的矩阵是下面这样的
练习:
- 实现三角形先绕 Z 轴旋转 60度再向右平移 0.5 看看是什么效果
思考:
- 有兴趣的同学手动计算一下旋转矩阵和平移矩阵和变换矩阵,看看跟库函数计算出的是否一样,可通过 Matrix4 对象的 elements 属性得到矩阵数组,另外注意矩阵数组是列优先的。