跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
JavaScript大前端算法

WebGL 矩阵变换详解:平移旋转缩放与复合动画

介绍 WebGL 中矩阵变换的核心原理与实战应用。涵盖平移、旋转、缩放三种基础变换的 4x4 矩阵构建方法,以及使用 gl-matrix 库实现复合变换的技巧。通过代码示例演示 CPU 端构建矩阵并传入 GPU 着色器的流程,强调变换顺序对最终效果的影响,帮助开发者理解 WebGL 渲染管线中的坐标转换机制。

咸鱼开飞机发布于 2026/4/6更新于 2026/5/2231 浏览
WebGL 矩阵变换详解:平移旋转缩放与复合动画

1. 先搞懂:WebGL + 矩阵 = 3D 图形的灵魂

WebGL(Web Graphics Library)是浏览器原生的 3D/2D 渲染 API,无需插件、直接调用 GPU 加速 —— 但想要玩转 WebGL 动画,矩阵乘法是绕不开的核心!

核心优势(标准矩阵版)

  • 矩阵统一变换逻辑:平移、旋转、缩放都通过「矩阵 × 顶点坐标」实现,完全符合 GPU 渲染规范
  • GPU 友好:矩阵运算可被 GPU 高效并行处理,动画更丝滑
  • 复合变换超灵活:多个矩阵相乘就能实现「平移 + 旋转 + 缩放」组合效果,扩展无压力

2. WebGL + 矩阵工作原理

WebGL 基于 OpenGL ES,核心是着色器;而矩阵是连接「JavaScript 逻辑」和「GPU 渲染」的桥梁:

  1. 开发者在 CPU 端构建变换矩阵(平移 / 旋转 / 缩放 / 复合)
  2. 将 4x4 矩阵传入顶点着色器的 uniform 变量
  3. GPU 通过「矩阵 × 顶点坐标」的乘法运算,计算顶点最终位置并完成渲染

关键:WebGL 中所有变换的标准写法是 gl_Position = 变换矩阵 * 顶点坐标,而非直接修改顶点 x/y 分量!


2.1 平移变换

平移是最基础的仿射变换,用 4x4 矩阵表示后,能和其他变换无缝组合!

平移矩阵原理(新手秒懂)

在计算机图形学中,平移的数学原理通过齐次坐标 + 4x4 矩阵实现:

  • 三维点表示为齐次坐标 (x,y,z,1)
  • 三维平移矩阵(WebGL 标准 4x4 形式):
text
[ 1 0 0 tx ] [ 0 1 0 ty ] [ 0 0 1 tz ] [ 0 0 0 1 ] 

矩阵乘法计算过程:

对三维点 (x,y,z,1) 执行矩阵乘法:

text
x' = 1*x + 0*y + 0*z + tx*1 = x + tx
y' = 0*x + 1*y + 0*z + ty*1 = y + ty
z' = 0*x + 0*y + *z + tz* = z + tz
w' = * + * + *z + * = 
1
1
0
x
0
y
0
1
1
1

注:WebGL 中即使处理 2D 图形,也统一使用 4x4 矩阵(z/tz 设为 0),这是 GPU 原生支持的标准格式。

实战:纯矩阵实现平移动画(代码可直接跑)
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>WebGL 矩阵实战:平移的红色三角形</title>
<style>
canvas { border: 2px solid #ff4400; display: block; margin: 20px auto; border-radius: 8px; }
</style>
</head>
<body>
<canvas></canvas>
<script>
// 1. 获取 Canvas 和 WebGL 上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) {
    alert('您的浏览器不支持 WebGL!换 Chrome/Firefox 试试');
    throw new Error('WebGL not supported');
}
// 2. 设置黑色背景
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 3. 着色器(核心:纯矩阵乘法实现平移)
const vertexShaderSource = `
attribute vec4 a_Position;
uniform mat4 u_TranslateMatrix; // 4x4 平移矩阵
void main() {
    // WebGL 标准写法:矩阵 × 顶点坐标
    gl_Position = u_TranslateMatrix * a_Position;
}
`;
const fragmentShaderSource = `
void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
`;
// 4. 封装着色器创建函数
function createShader(gl, source, type) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('着色器编译错误:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}
// 5. 创建并链接程序
const vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
const fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 6. 顶点数据(三角形)
const vertices = new Float32Array([
    -0.2, -0.2, 0.0,
    0.2, -0.2, 0.0,
    0.0, 0.2, 0.0
]);
// 7. 绑定顶点数据到 GPU
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
// 8. 矩阵平移核心:构建 4x4 平移矩阵
const u_TranslateMatrix = gl.getUniformLocation(program, 'u_TranslateMatrix');
const translateMatrix = new Float32Array(16); // WebGL 矩阵格式(16 个元素的 Float32Array)
let tx = 0.0; // 平移量 x
const step = 0.02; // 构建 4x4 平移矩阵的函数(WebGL 列主序)
function setTranslateMatrix(matrix, tx, ty, tz) {
    matrix.set([
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        tx, ty, tz, 1
    ]);
}
// 9. 动画循环
function animate() {
    // 更新平移量
    tx += step;
    if (tx > 1.0) tx = -1.0;
    // 构建 4x4 平移矩阵
    setTranslateMatrix(translateMatrix, tx, 0.0, 0.0);
    // 传递矩阵给着色器(false=不转置,WebGL 默认列主序)
    gl.uniformMatrix4fv(u_TranslateMatrix, false, translateMatrix);
    // 清屏 + 绘制
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    requestAnimationFrame(animate);
}
animate();
</script>
</body>
</html>
效果

红色三角形沿 x 轴平移,本质是不断更新 4x4 平移矩阵的 tx 分量,GPU 通过「矩阵 × 顶点」计算新位置!

文章配图 文章配图


2.2 旋转变换

旋转的核心是「4x4 旋转矩阵」,纯矩阵乘法写法更易和其他变换组合!

旋转矩阵原理(重点!)

二维点绕原点逆时针旋转 θ 角的 4x4 矩阵(WebGL 标准格式):

text
[ cosθ -sinθ 0 0 ]
[ sinθ cosθ 0 0 ]
[ 0 0 1 0 ]
[ 0 0 0 1 ]

矩阵乘法计算过程:

对二维点 (x,y)(齐次坐标 (x,y,0,1))执行矩阵乘法:

text
x' = cosθ * x + (-sinθ) * y + 0 * 0 + 0 * 1 = x*cosθ - y*sinθ
y' = sinθ * x + cosθ * y + 0 * 0 + 0 * 1 = x*sinθ + y*cosθ
z' = 0 * x + 0 * y + 1 * 0 + 0 * 1 = 0
w' = 0 * x + 0 * y + 0 * 0 + 1 * 1 = 1

矩阵乘法结果等价于:

text
x' = x*cosθ - y*sinθ
y' = x*sinθ + y*cosθ

关键:矩阵形式无需在着色器中写三角函数,只需传递完整矩阵,更符合 GPU 渲染规范!

实战:纯矩阵实现旋转动画
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>WebGL 矩阵实战:旋转的红色三角形</title>
<style>
canvas { border: 2px solid #ff4400; display: block; margin: 20px auto; border-radius: 8px; }
</style>
</head>
<body>
<canvas></canvas>
<script>
// 1. 获取上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) {
    alert('换 Chrome/Firefox 试试!');
    throw new Error('WebGL not supported');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 2. 着色器(核心:纯矩阵乘法实现旋转)
const vertexShaderSource = `
attribute vec4 a_Position;
uniform mat4 u_RotateMatrix; // 4x4 旋转矩阵
void main() {
    // WebGL 标准写法:旋转矩阵 × 顶点坐标
    gl_Position = u_RotateMatrix * a_Position;
}
`;
const fragmentShaderSource = `
void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
`;
// 3. 创建着色器 + 程序(复用)
function createShader(gl, source, type) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('编译错误:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}
const vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
const fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 4. 顶点数据
const vertices = new Float32Array([
    0.0, 0.5, 0.0,
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0
]);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
// 5. 旋转矩阵核心:构建 4x4 绕 Z 轴旋转矩阵
const u_RotateMatrix = gl.getUniformLocation(program, 'u_RotateMatrix');
const rotateMatrix = new Float32Array(16);
let angle = 0.0; // 旋转角度θ(弧度)
// 构建 4x4 绕 Z 轴旋转矩阵的函数
function setRotateZMatrix(matrix, angle) {
    const cos = Math.cos(angle);
    const sin = Math.sin(angle);
    matrix.set([
        cos, -sin, 0, 0,
        sin, cos, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    ]);
}
// 6. 动画循环
function animateRotate() {
    angle += 0.02;
    // 构建 4x4 旋转矩阵
    setRotateZMatrix(rotateMatrix, angle);
    // 传递旋转矩阵给着色器
    gl.uniformMatrix4fv(u_RotateMatrix, false, rotateMatrix);
    // 绘制
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    requestAnimationFrame(animateRotate);
}
animateRotate();
</script>
</body>
</html>
效果

三角形绕原点旋转,本质是不断更新 4x4 旋转矩阵的 cosθ/sinθ 分量,GPU 自动完成「矩阵 × 顶点」运算!

文章配图 文章配图


2.3 缩放变换

缩放是改变图形大小的核心变换,同样通过 4x4 矩阵乘法实现,是复合变换的重要组成部分!

缩放矩阵原理(核心!)

二维点沿 x/y 轴缩放的 4x4 矩阵(WebGL 标准格式):

text
[ sx 0 0 0 ]
[ 0 sy 0 0 ]
[ 0 0 sz 0 ]
[ 0 0 0 1 ]
  • sx:x 轴缩放因子(>1 放大,<1 缩小,负数翻转)
  • sy:y 轴缩放因子
  • sz:z 轴缩放因子(2D 场景设为 1)
矩阵乘法计算过程:

对二维点 (x,y)(齐次坐标 (x,y,0,1))执行矩阵乘法:

text
x' = sx * x + 0 * y + 0 * 0 + 0 * 1 = x * sx
y' = 0 * x + sy * y + 0 * 0 + 0 * 1 = y * sy
z' = 0 * x + 0 * y + sz * 0 + 0 * 1 = 0 (2D 场景 sz=1)
w' = 0 * x + 0 * y + 0 * 0 + 1 * 1 = 1

矩阵乘法结果等价于:

text
x' = x * sx
y' = y * sy

关键:缩放矩阵的核心是对角线上的缩放因子,非对角线元素均为 0,保证仅改变大小不改变位置(绕原点缩放)。

实战:纯矩阵实现缩放动画
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>WebGL 矩阵实战:缩放的红色三角形</title>
<style>
canvas { border: 2px solid #ff4400; display: block; margin: 20px auto; border-radius: 8px; }
</style>
</head>
<body>
<canvas></canvas>
<script>
// 1. 获取上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) {
    alert('您的浏览器不支持 WebGL!换 Chrome/Firefox 试试');
    throw new Error('WebGL not supported');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 2. 着色器(核心:纯矩阵乘法实现缩放)
const vertexShaderSource = `
attribute vec4 a_Position;
uniform mat4 u_ScaleMatrix; // 4x4 缩放矩阵
void main() {
    // WebGL 标准写法:缩放矩阵 × 顶点坐标
    gl_Position = u_ScaleMatrix * a_Position;
}
`;
const fragmentShaderSource = `
void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
`;
// 3. 创建着色器 + 程序(复用)
function createShader(gl, source, type) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('编译错误:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}
const vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
const fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 4. 顶点数据
const vertices = new Float32Array([
    0.0, 0.5, 0.0,
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0
]);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
// 5. 缩放矩阵核心:构建 4x4 缩放矩阵
const u_ScaleMatrix = gl.getUniformLocation(program, 'u_ScaleMatrix');
const scaleMatrix = new Float32Array(16);
let scaleFactor = 1.0; // 缩放因子
const step = 0.01; // 缩放步长
let isEnlarging = true; // 放大/缩小标记
// 构建 4x4 缩放矩阵的函数
function setScaleMatrix(matrix, sx, sy, sz) {
    matrix.set([
        sx, 0, 0, 0,
        0, sy, 0, 0,
        0, 0, sz, 0,
        0, 0, 0, 1
    ]);
}
// 6. 动画循环
function animateScale() {
    // 更新缩放因子(来回缩放)
    if (isEnlarging) {
        scaleFactor += step;
        if (scaleFactor >= 2.0) isEnlarging = false;
    } else {
        scaleFactor -= step;
        if (scaleFactor <= 0.5) isEnlarging = true;
    }
    // 构建 4x4 缩放矩阵(x/y 轴等比缩放)
    setScaleMatrix(scaleMatrix, scaleFactor, scaleFactor, 1.0);
    // 传递缩放矩阵给着色器
    gl.uniformMatrix4fv(u_ScaleMatrix, false, scaleMatrix);
    // 清屏 + 绘制
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    requestAnimationFrame(animateScale);
}
animateScale();
</script>
</body>
</html>
效果

三角形绕原点在 0.5 倍~2 倍之间来回缩放,本质是不断更新 4x4 缩放矩阵的 sx/sy 分量,GPU 自动完成「矩阵 × 顶点」运算!

文章配图 文章配图


2.4 矩阵进阶:平移 + 旋转 + 缩放复合变换

手动组合多个矩阵容易出错?gl-matrix 库可一键完成「平移 + 旋转 + 缩放」的矩阵乘法,是工业级开发的首选方案!

gl-matrix 库的核心优势
  • 封装所有 4x4 矩阵运算:mat4.translate()/mat4.rotateZ()/mat4.scale() 直接生成变换矩阵
  • 自动处理矩阵乘法:复合变换只需按顺序调用 API,无需手动计算矩阵相乘
  • 性能优化:针对 WebGL 做了 GPU 适配,动画更丝滑
实战:平移 + 旋转 + 缩放复合动画
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>WebGL 矩阵进阶:平移 + 旋转 + 缩放复合动画</title>
<style>
canvas { border: 2px solid #ff4400; display: block; margin: 20px auto; border-radius: 8px; }
</style>
<!-- 引入 gl-matrix 库(直接用 CDN) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
</head>
<body>
<canvas></canvas>
<script>
// 1. 获取上下文
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
if (!gl) {
    alert('您的浏览器不支持 WebGL!换 Chrome/Firefox 试试');
    throw new Error('WebGL not supported');
}
gl.clearColor(0.0, 0.0, 0.0, 1.0);
// 2. 着色器(核心:接收 4x4 复合变换矩阵)
const vertexShaderSource = `
attribute vec4 a_Position;
uniform mat4 u_ModelMatrix; // 复合变换矩阵(平移 + 旋转 + 缩放)
void main() {
    // 标准写法:复合矩阵 × 顶点坐标
    gl_Position = u_ModelMatrix * a_Position;
}
`;
const fragmentShaderSource = `
void main() {
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 红色
}
`;
// 3. 创建着色器 + 程序(复用)
function createShader(gl, source, type) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);
    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error('编译错误:', gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}
const vertexShader = createShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
const fragmentShader = createShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 4. 顶点数据
const vertices = new Float32Array([
    0.0, 0.5, 0.0,
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0
]);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const a_Position = gl.getAttribLocation(program, 'a_Position');
gl.vertexAttribPointer(a_Position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
// 5. 复合矩阵核心(重点!)
const u_ModelMatrix = gl.getUniformLocation(program, 'u_ModelMatrix');
const modelMatrix = mat4.create(); // 创建单位矩阵(初始无变换)
let tx = 0.0; // 平移量 x
let angle = 0.0; // 旋转角度θ
let scaleFactor = 1.0; // 缩放因子
let isEnlarging = true;
function animateWithMatrix() {
    // 1. 重置为单位矩阵(每次循环清空变换)
    mat4.identity(modelMatrix);
    // 2. 按顺序执行复合变换(⚠️ 顺序决定最终效果!)
    // 第一步:缩放(先缩放,保证旋转/平移基于原始大小)
    mat4.scale(modelMatrix, modelMatrix, [scaleFactor, scaleFactor, 1.0]);
    // 第二步:旋转(再旋转,保证平移基于旋转后的方向)
    mat4.rotateZ(modelMatrix, modelMatrix, angle);
    // 第三步:平移(最后平移,保证整体位置移动)
    mat4.translate(modelMatrix, modelMatrix, [tx, 0.0, 0.0]);
    // 3. 更新参数
    tx += 0.015;
    if (tx > 1.0) tx = -1.0;
    angle += 0.02;
    // 缩放参数更新
    if (isEnlarging) {
        scaleFactor += 0.005;
        if (scaleFactor >= 1.5) isEnlarging = false;
    } else {
        scaleFactor -= 0.005;
        if (scaleFactor <= 0.7) isEnlarging = true;
    }
    // 4. 传递复合矩阵给 GPU
    gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix);
    // 5. 绘制
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, 3);
    requestAnimationFrame(animateWithMatrix);
}
animateWithMatrix();
</script>
</body>
</html>
效果

三角形同时完成「沿 x 轴平移 + 绕原点旋转 + 0.7~1.5 倍缩放」的复合动画,gl-matrix 自动完成所有矩阵乘法运算,代码简洁且高效!

文章配图 文章配图


矩阵核心知识点(必记!)

  1. 变换顺序≠乘法交换律:矩阵乘法不满足交换律,变换顺序直接决定最终效果(推荐顺序:缩放 → 旋转 → 平移):
    • 缩放→旋转→平移:图形先调整大小,再旋转方向,最后移动位置(最符合直觉)
    • 平移→旋转→缩放:图形先移动,再旋转,最后缩放(会导致平移距离也被缩放)
  2. 单位矩阵是基础:mat4.identity() 生成单位矩阵(无变换),是所有矩阵变换的起点
  3. 矩阵格式要正确:WebGL 中矩阵必须是 Float32Array 类型的 16 个元素(列主序),传递时 gl.uniformMatrix4fv 的第二个参数必须为 false

新手矩阵避坑指南

  1. 先跑通代码,再理解矩阵:不用一开始死磕矩阵乘法,先改 tx/angle/scaleFactor 数值,看动画变化,直观理解矩阵作用
  2. 拒绝手动改顶点坐标:WebGL 标准写法是「矩阵 × 顶点」,直接修改 x/y 分量会丧失 GPU 并行计算优势
  3. 优先用 gl-matrix 库:实际开发中避免手动拼矩阵,减少 90% 错误,专注业务逻辑
  4. 注意缩放中心:默认缩放绕原点进行,若需绕自定义点缩放,需先平移到原点→缩放→平移回原位置

3. 矩阵核心总结

  1. WebGL 动画的本质:CPU 端构建 4x4 变换矩阵 → 传递给着色器 → GPU 执行「矩阵 × 顶点坐标」计算新位置
  2. 三大基础变换矩阵:
    • 平移:第四列前三个元素为平移量(tx/ty/tz)
    • 旋转:左上角 2x2 矩阵为 cosθ/sinθ 组合(绕 Z 轴)
    • 缩放:对角线上的元素为缩放因子(sx/sy/sz)
  3. 实战技巧:用 gl-matrix 库简化矩阵操作,严格遵守「缩放→旋转→平移」的复合变换顺序,注意矩阵乘法无交换律

目录

  1. 1. 先搞懂:WebGL + 矩阵 = 3D 图形的灵魂
  2. 核心优势(标准矩阵版)
  3. 2. WebGL + 矩阵工作原理
  4. 2.1 平移变换
  5. 平移矩阵原理(新手秒懂)
  6. 实战:纯矩阵实现平移动画(代码可直接跑)
  7. 效果
  8. 2.2 旋转变换
  9. 旋转矩阵原理(重点!)
  10. 实战:纯矩阵实现旋转动画
  11. 效果
  12. 2.3 缩放变换
  13. 缩放矩阵原理(核心!)
  14. 矩阵乘法计算过程:
  15. 实战:纯矩阵实现缩放动画
  16. 效果
  17. 2.4 矩阵进阶:平移 + 旋转 + 缩放复合变换
  18. gl-matrix 库的核心优势
  19. 实战:平移 + 旋转 + 缩放复合动画
  20. 效果
  21. 矩阵核心知识点(必记!)
  22. 新手矩阵避坑指南
  23. 3. 矩阵核心总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • ROS rqt 工具箱核心插件配置与无人机调试实战
  • Vue3-Element-Admin 前端代码自动生成指南
  • 基于 Spring Boot 与微信小程序的 4S 店服务预约系统设计
  • Midjourney 工作原理、使用流程及优缺点分析
  • Web 开发者转型 AI 实战:基于 Agent 的代码质量分析 Skill 开发指南
  • 双重机器学习之因果推断:CATE 条件平均处理效应估计五大方法与实战
  • Ubuntu 升级 OpenSSH 10.2p1 与 OpenSSL 3.5.4 避坑实践
  • 三维人体姿态估计前沿算法与论文案例
  • VS Code 配置 Claude Code 解决 Git Bash 路径错误
  • IPSec 协议簇详解:AH、ESP 与 IKE 协议原理
  • 医学人工智能中的分层处理与跨模态融合:深度架构设计研究(基础教程.上)
  • AMD AI MAX+395 迷你主机基于 ROCm 部署 vLLM 大模型实践
  • 网络安全入门教程:从零开始掌握基础技术与工具
  • 基于 ROS 和 EtherCAT 的机器人多轴协同控制实现方案
  • CSS 颜色函数和渐变技术详解
  • SketchUp STL 插件安装与使用指南
  • Hashcat 实战指南:从安装到高级密码恢复
  • MySQL 性能优化:索引优化与查询优化
  • Flutter 使用 React 风格库在 OpenHarmony 上的适配与实践
  • 用 AI 辅助解析 B 站充电视频页面结构与鉴权逻辑

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online