首页/ 学科题库/ webgl/ WebGL 齐次坐标与模型矩阵变换
webgl 实战教程

WebGL 齐次坐标与模型矩阵变换

2026-09-13 约 8 分钟 juanwangdev

WebGL 齐次坐标与模型矩阵变换

一句话结论:齐次坐标让平移变成矩阵乘法,模型矩阵负责把顶点从模型自身坐标搬到场景坐标,两者是所有顶点变换的起点。

齐次坐标与四维向量

是什么

齐次坐标是在三维坐标之外增加一个 w 分量的四维表示法,点写作 vec4(x, y, z, 1.0),方向向量写作 vec4(x, y, z, 0.0)。WebGL 中顶点着色器的 gl_Position 就是裁剪空间下的四维齐次坐标。

解决什么问题

它解决平移无法用矩阵乘法表达的问题。纯三维的线性变换只能表达旋转与缩放,平移需要额外加法;引入 w 分量后,平移可以写进 4x4 矩阵的最后一列,于是旋转、缩放、平移、投影全部统一为一次矩阵乘法,可以任意串联。

为什么这样做

GPU 的顶点处理单元擅长一次矩阵乘向量运算。把变换统一成矩阵乘法,就能把缩放、旋转、平移、视图、投影预先相乘成一个矩阵,顶点着色器里只做一次乘法,把多次运算压缩为一次,这是顶点变换性能的关键。

怎么用

glsl
attribute vec3 aPosition;
uniform mat4 uModelMatrix;
uniform mat4 uViewProjectionMatrix;

void main() {
  // 点的 w 为 1,方向向量为 0,二者变换规则不同
  gl_Position = uViewProjectionMatrix * uModelMatrix * vec4(aPosition, 1.0);
}
JavaScript
// 平移写进矩阵最后一列,因此能被乘法表达
const T = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 0, 1, 0,
  tx, ty, tz, 1, // 列主序:最后一列存放平移量
];

常见坑

  • 用 vec4(aPosition, 0.0) 表示顶点位置 → 原因:w 为 0 表示方向向量,无法平移 → 处理:位置一律补 1.0
  • 手动实现透视除法 → 原因:GPU 在裁剪后自动执行除法 → 处理:着色器里不要自己除以 w
  • 误以为 w 恒等于 1 → 原因:投影矩阵的 w 会被改写 → 处理:透视投影下 w 通常等于负的视空间 z

模型矩阵与顶点变换

是什么

模型矩阵是把顶点从模型局部坐标系变换到世界坐标系的 4x4 矩阵。它描述物体在场景中的位置、朝向与大小,通常由缩放、旋转、平移三个基础变换按固定顺序相乘得到。

解决什么问题

它解决模型复用与场景摆放问题。同一个立方体模型只需要一份顶点数据,通过不同的模型矩阵就能出现在场景的不同位置、以不同角度和大小呈现,避免为每个实例复制顶点。

为什么这样做

顶点数据应当只描述形状,摆放属于运行时状态。把摆放信息放进矩阵,顶点缓冲就可以被多个物体共享,绘制时只需切换 uniform,无需重传顶点数据,这也是批量绘制与实例化渲染的基础。

怎么用

JavaScript
// 严格按 缩放 → 旋转 → 平移 的顺序拼接
const model = mat4.create();
mat4.identity(model);
mat4.translate(model, model, [x, y, z]);         // 先写平移,最后作用于顶点
mat4.rotateY(model, model, angle);               // 再旋转
mat4.scale(model, model, [sx, sy, sz]);          // 最后缩放

gl.uniformMatrix4fv(uModel, false, model);
变换顺序结果
缩放 → 旋转 → 平移(推荐)围绕自身轴缩放旋转,再整体移动
平移 → 旋转物体绕世界原点公转,位置偏移
旋转 → 缩放(非等比)几何体被沿旋转后的轴拉伸,出现剪切

常见坑

  • 矩阵拼接顺序写反 → 原因:矩阵乘法不满足交换律 → 处理:固定使用缩放、旋转、平移顺序
  • 每帧重复计算静态矩阵 → 原因:CPU 端浪费 → 处理:静态物体的模型矩阵只算一次并缓存
  • 忘记更新 uniform → 原因:切换物体后仍用上一个矩阵 → 处理:每次绘制前重新设置 uModel
  • 用逐顶点方式做物体位移 → 原因:改动顶点数据开销大 → 处理:位移全部交给模型矩阵

要点总结

  • 齐次坐标用 w 分量把平移写成矩阵乘法,位置补 1.0、方向补 0.0
  • GPU 自动执行透视除法,w 由投影矩阵决定
  • 模型矩阵把顶点从局部坐标变换到世界坐标,决定摆放位置与姿态
  • 矩阵乘法不交换,模型矩阵固定按缩放、旋转、平移拼接
  • 位移应交给矩阵而非修改顶点数据,静态矩阵要缓存复用

常见问题

顶点坐标为什么要用四维而不是三维?

因为三维矩阵无法表达平移。加上第四个分量 w 后,平移可以写成矩阵乘法,旋转、缩放、平移与透视除法因此能统一成一次矩阵运算,也方便串联多个变换。

齐次坐标中的 w 分量有什么用?

w 用于透视除法。GPU 在裁剪之后把 x、y、z 都除以 w,w 越大顶点越靠近画面中心,远处的顶点因此自动变小,这正是透视投影的实现方式。

模型矩阵的作用是什么?

模型矩阵把顶点从模型自身的局部坐标系变换到场景的世界坐标系,决定物体放在哪里、转多少角度、缩放多少倍,是 MVP 矩阵中的第一环。

为什么先缩放再旋转和先旋转再缩放结果不同?

因为矩阵乘法不满足交换律。缩放和旋转的顺序不同,变换的基准轴也不同,常见做法是严格按照缩放、旋转、平移的顺序拼接模型矩阵。

想在手机上练这篇的配套题目?
使用微信 卷王开发者小程序/App,首页顶部扫一扫识别下方二维码,即可解锁本讲对应真题与错题本。
了解产品 App
← 上一篇 WebGL 顶点数据动态更新与状态机缓存 下一篇 → WebGL 视图矩阵与透视投影配置