本节摘要:变换数学是管线的心电图——MVP 三矩阵分别完成「摆物体、摆相机、压视锥」,齐次坐标的第四分量 w 承载透视,法线矩阵用逆转置抵消非均匀缩放的破坏。本节不背公式,用几何直觉逐个重建这些构造,手推一次 MVP 复合,解剖深度精度与近平面的依赖关系,并给出 GLM 的工程用法与三个数值稳健性守则。它是 2.1 节的前传补全,也是第 5 章光照数学的底座。
2.1 节把变换链当黑盒用了:三矩阵一乘,顶点到裁剪空间。但黑盒在两处必然漏电。第一处是调试:画面里物体「歪了、压扁了、绕着奇怪的中心转」,你没有矩阵的几何直觉就只能在数值堆里乱试。第二处是光照:法线变换用错矩阵(2.1 节的病变预告),光照全盘错位,而这个错误的理解与修复,必须追溯到「矩阵作用于点与作用于方向为什么效果不同」。本节的目标:让每个矩阵在你脑中是一幅几何画面,而不是一串数字。
模型矩阵回答「这个物体在世界里怎么摆」。任何摆放都可以分解成「缩放 → 旋转 → 平移」的复合(矩阵从右往左作用)。两个几何直觉值得先建立:平移矩阵动的是原点——物体自己的局部原点被搬到世界何处;旋转矩阵动的是坐标系——物体绕哪根轴、转多少。复合时顺序不可交换:先转再移是「原地转身后前进」,先移再转是「绕世界原点公转」——角色应该用前者、太阳系轨道是后者的样子,顺序错换症状非常直白。
齐次坐标在此登场。三维平移不是线性变换(原点必须保持不动),普通的 3×3 矩阵表达不了「搬家」。解法是升一维:四分量坐标 (x, y, z, 1),平移搬进 4×4 矩阵的最后一列。这个多出来的分量一物三用:承载平移、区分点(w=1)与方向(w=0,平移对它无效——方向没有位置)、以及后面投影阶段的透视除数。**「w=0 的向量旋转缩放照常但拒绝平移」**,这就是法线、光方向这类「方向量」能安全过矩阵的原因之一。
观察矩阵把世界翻译成「以相机为原点」的坐标。直觉陷阱在「反向」:想让相机后退两步,等价于整个世界前进两步——观察矩阵是世界万物集体做的反向运动。GLM 的 glm::lookAt(eye, center, up) 替你构造它:位置、注视点、天顶方向三个参数定一个相机姿态,内部实际在构造一个旋转加平移,把相机「搬」到原点朝负 z 看并向负 z 平移场景。负 z 的约定(1.2 节的历史遗留)在这里显形:相机看向负 z 轴,远处物体 z 越负——「远处的深度是更小的负数」这个反直觉事实,是无数 z 比较错误的源头。
投影是最容易被神话的一步,几何上它只做一件事:把视锥体(被近平面和远平面夹住的四棱台)线性映射成裁剪空间的标准箱子——而且它是个货真价实的线性变换,装在 4×4 矩阵里。透视的全部机关在矩阵的最后一行:它被构造成「让输出 w 恰好等于输入 z 的负值」。于是远处顶点(z 负得多)得到大 w,近处得到小 w——随后的透视除法除以 w,远处坐标整体缩小,透视感成立。

正交投影是对照组:矩阵不埋 w 机关(w 恒为 1),没有近大远小,平行线保持平行——CAD 制图、二维界面、影子贴图的光源视角都用它。两套投影在管线里完全同构,只差矩阵的构造参数,这个认知能让你在切换投影时不慌。
三个矩阵可以预先右乘复合成一个(GLM 里 projection * view * model 的顺序,作用从右往左)。顶点着色器里一次 mat4 乘 vec4 完成「摆物体、摆相机、压视锥」三连。省的不只是着色器计算——更重要的是 CPU 端每帧一次复合、一次 glUniformMatrix4fv 上传,替代三个矩阵三次上传(乘上传次数的减少,是第 6 章驱动开销话题的预演)。但复合只该发生在不需要中间产物的时候:光照需要世界空间位置(4.1 节样本代码里 FragPos 的来历),那就保留 model 单独传——按下游需求裁剪矩阵链,不是无脑全复合。
2.1 节开了处方「法线用模型矩阵的逆转置」,现在补上辩护。关键在法线不是点,是垂直于表面的方向。均匀缩放下,方向与表面垂直关系在变换后保持——直接用模型矩阵没问题。但非均匀缩放(压扁砖块那个例子)会让「直接变换后的法线」不再垂直于「变换后的表面」。数学上的修复恰是逆转置:可以证明,若表面被矩阵 M 变换,则原法线被 M 的逆转置变换后仍垂直于新表面。直觉版理解:逆转置在「撤销」缩放分量对方向角的扭曲——转置把列作用换成行作用,逆把拉伸换算成收缩,两者合谋把垂直关系保住。
工程上三行搞定:glm::mat3 normalMatrix = glm::transpose(glm::inverse(model)); 取 mat3 是砍掉平移(方向不搬家,w=0 的知识复用)。判断你需不需要它:模型只要带非均匀缩放就必须用;纯刚体运动(旋转平移)时逆转置恰好等于原矩阵的旋转部分,用了也无害——所以「永远用逆转置」是安全的默认姿势。
变换数学的最后一块是工程边界。守则一:近平面尽量远——深度精度分布的恶主(2.4 节已展开,z-fighting 的根)。守则二:大场景拆局部原点——浮点精度在离原点十万八千里处衰减(顶点开始抖动、接缝开裂),大世界场景要把坐标按区块平移回原点附近再变换。守则三:矩阵别逐元素累积误差——每帧用「位置加朝向」重新构造矩阵,而不是上一帧的矩阵连续左乘小增量(百万帧后漂移肉眼可见)。三条都属于「出问题前没人注意、出问题后极难排查」的类型,值得在代码评审清单里占一行。
解剖台三完工。语言、工具链、数学三件套齐备,下一章冲向管线最出效果的地带——光:从冯氏模型一路解剖到 PBR 与后处理,前三章的全部积累将在那里变现。