webgl 变换矩阵:旋转、平移、缩放
一,变换矩阵
对于简单的变换可以使用数学表达式来实现,但是当情形逐渐变得复杂时,利用表达式运算就会变得相当繁琐。好在我们可以使用另一个数学工具 -------- 变换矩阵 。变换矩阵在三维计算机图形学运用的非常广泛,以至于着色器本身就实现了矩阵和矢量相乘的功能。
二,变换矩阵:旋转矩阵
1,推导变换矩阵

由 P (x,y) 逆时针旋转 b 度获得 P1(x1,y1); 由三角函数可以获得 P 点和 P1 点坐标之间的关系
根据矩阵的乘法
可以得到
对比上面的三角函数表达式和下方的矩阵乘法
所以,获得的旋转矩阵为
2,修改顶点着色器编码
使用 mat4 声明 4 维矩阵变量
// 顶点着色器, 通过矩阵乘法实现平移
const VSHADER_SOURCE = `
attribute vec4 a_Position;
uniform mat4 u_xformMatrix;void main() {gl_Position = u_xformMatrix * a_Position;}
`;3,创建变换矩阵
webgl 中创建矩阵是 按列主序。
// 创建平移矩阵const xformMatrix = new Float32Array([cosB, sinB, 0.0, 0.0, -sinB, cosB, 0.0, 0.0,0.0, 0.0, 1.0, 0.0,0.0, 0.0, 0.0, 1.0,])4,传递变量绘制三角形


// 获取 u_xformmatrix 变量的存储位置const u_xformMatrix = state.gl.getUniformLocation(state.gl.program, 'u_xformMatrix') as WebGLUniformLocation;state.gl?.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);// 绘制三角形// state.gl.drawArrays(state.gl.TRIANGLE_STRIP, 0, n);state.gl.drawArrays(state.gl.TRIANGLES, 0, 3); 二。变换矩阵:平移矩阵
1,推导平移矩阵
假设点P(x,y,z,1),经过平移得到 P1(x1,y1,z1,1)
由矩阵的乘法可得
可以得到
可以得到
从而可以得到平移矩阵`,其中
分别为x, y, z 轴的平移分量。
2,创建平移矩阵
假设使三角形水平向右移动 0.5, 则
webgl 中创建矩阵是按列主序
// 创建平移矩阵const xformMatrix = new Float32Array([1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,0.0, 0.0, 1.0, 0.0,0.5, 0.0, 0.0, 1.0,])3, 传递变量绘制三角形


// 获取 u_xformmatrix 变量的存储位置const u_xformMatrix = state.gl.getUniformLocation(state.gl.program, 'u_xformMatrix') as WebGLUniformLocation;state.gl?.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);// 绘制三角形// state.gl.drawArrays(state.gl.TRIANGLE_STRIP, 0, n);state.gl.drawArrays(state.gl.TRIANGLES, 0, 3); 三,变换矩阵:缩放矩阵
1,推导缩放矩阵
假设 分别为 x, y, z 轴上的缩放因子,则可得
将上式同第二步的矩阵乘法等式做比较,可得缩放矩阵
2,创建缩放矩阵
假设三角形沿 y 轴缩小0.5 倍,则
// 创建平移矩阵const xformMatrix = new Float32Array([1.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,0.0, 0.0, 1.0, 0.0,0.0, 0.0, 0.0, 1.0,])3,传递参数,绘制三角形。
可以看到三角形沿 y 轴缩小了一半。


// 获取 u_xformmatrix 变量的存储位置const u_xformMatrix = state.gl.getUniformLocation(state.gl.program, 'u_xformMatrix') as WebGLUniformLocation;state.gl?.uniformMatrix4fv(u_xformMatrix, false, xformMatrix);// 绘制三角形// state.gl.drawArrays(state.gl.TRIANGLE_STRIP, 0, n);state.gl.drawArrays(state.gl.TRIANGLES, 0, 3); 