首页/ 学科题库/ webgl/ WebGL 正交投影与法线矩阵
webgl 实战教程

WebGL 正交投影与法线矩阵

2026-09-13 约 8 分钟 juanwangdev

WebGL 正交投影与法线矩阵

一句话结论:正交投影去掉透视收缩用于 2D 与等轴测场景,法线必须用逆转置矩阵变换,非等比缩放会让直接变换的法线歪掉。

正交投影适用场景

是什么

正交投影是一种不产生透视收缩的投影方式,投影后 w 分量恒为 1,物体大小与距相机的远近无关。它用左右、上下、近远六个平面定义一个长方体可视区域。

解决什么问题

它解决需要精确测量与对齐的场景问题。屏幕 UI、2D 图表、等轴测游戏、平面图预览都要求相同尺寸的物体在画面上表现一致,透视投影的近大远小会破坏这种一致性。

为什么这样做

正交投影的可视区域是一个轴对齐的长方体,深度值在其中线性分布,坐标到屏幕的映射是一次仿射变换。这让像素与坐标可以一一对应,便于精确排布元素,也让深度比较的精度在整个范围内均匀。

怎么用

JavaScript
const ortho = mat4.create();
// left, right, bottom, top, near, far
mat4.ortho(ortho, -aspect, aspect, -1, 1, 0.1, 100);
gl.uniformMatrix4fv(uProjection, false, ortho);

// 二维 UI:直接用像素范围定义投影,1 单位 = 1 像素
mat4.ortho(ortho, 0, canvas.width, canvas.height, 0, -1, 1);
场景推荐投影原因
三维产品展示透视需要立体与纵深感
2D 图表、UI 层正交尺寸必须一致、像素对齐
等轴测游戏正交保持各方向比例相同
建筑平面图正交需要量取真实尺寸
阴影贴图光源视图正交平行光无透视,深度均匀

常见坑

  • 用正交投影做三维展示 → 原因:画面缺乏纵深 → 处理:展示类场景改用透视投影
  • 参数没有跟随画布更新 → 原因:宽高比变化 → 处理:尺寸变化时按 aspect 重建正交矩阵
  • 用正交投影做阴影贴图时 near/far 过大 → 原因:深度精度浪费 → 处理:收紧到场景包围盒范围
  • 二维场景中 z 全部相同导致深度冲突 → 原因:深度值相同 → 处理:用绘制顺序代替深度测试

法线矩阵与向量变换

是什么

法线矩阵是用于变换法线向量的矩阵,等于模型矩阵左上 3x3 部分的逆的转置。它保证变换后的法线仍然垂直于物体表面,是光照计算正确的前提。

解决什么问题

它解决非等比缩放导致光照错误的问题。若直接用模型矩阵变换法线,沿某一轴放大后法线会朝该轴偏斜,表面与光线的夹角被算错,会出现明暗不自然甚至整体发黑。

为什么这样做

法线是协变向量,其变换规则与位置向量互为对偶。数学上,保持法线与切平面垂直关系的变换矩阵正是原变换的逆转置,因此只要缩放不均匀,就必须单独构造法线矩阵,而不能复用模型矩阵。

怎么用

JavaScript
// 法线矩阵 = transpose(inverse(mat3(model)))
const normalMatrix = mat3.create();
mat3.normalFromMat4(normalMatrix, model);   // gl-matrix 提供的取法
gl.uniformMatrix3fv(uNormalMatrix, false, normalMatrix);
glsl
attribute vec3 aNormal;
uniform mat3 uNormalMatrix;
varying vec3 vNormal;

void main() {
  vNormal = normalize(uNormalMatrix * aNormal);
  gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
}

常见坑

  • 用 mat4(model) 直接乘 vec4(aNormal, 0.0) → 原因:非等比缩放下法线偏斜 → 处理:改用 3x3 法线矩阵
  • 忘记归一化 → 原因:缩放改变了向量长度 → 处理:变换后调用 normalize
  • 只对法线做旋转 → 原因:忽略了缩放的逆转置 → 处理:统一由工具函数生成法线矩阵
  • 每帧在着色器里做逆转置 → 原因:矩阵求逆开销大 → 处理:在 CPU 端算好后以 uniform 传入

要点总结

  • 正交投影无透视收缩,适合 2D、UI、等轴测与平面图场景
  • 正交投影六参数定义长方体可视区,深度线性分布
  • 法线必须用模型矩阵 3x3 的逆转置矩阵变换,否则非等比缩放时光照失真
  • 变换后法线要归一化,矩阵求逆放在 CPU 端做
  • 三维展示用透视,精确测量与像素对齐用正交

常见问题

什么场景应该用正交投影?

需要保持物体大小不随距离变化的场景,例如 UI 元素、二维图表、等轴测视图、建筑平面与 CAD 预览。正交投影下平行线保持平行,便于精确比较尺寸与位置。

正交投影和透视投影的区别是什么?

透视投影有近大远小的效果,w 分量随距离变化;正交投影的 w 恒为 1,不改变顶点大小,深度值随距离线性分布,画面没有透视收缩。

为什么法线不能直接用模型矩阵变换?

因为非等比缩放会让法线不再垂直于表面。模型矩阵会把法线沿缩放方向拉伸,导致光照方向计算错误,必须使用模型矩阵左上 3x3 的逆转置矩阵。

只有旋转和平移时还需要法线矩阵吗?

严格来说需要,但此时逆转置矩阵与原始旋转矩阵相同,可以直接用模型矩阵的左上 3x3 部分。只有存在非等比缩放时两者才会出现差异。

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