齐次坐标
齐次坐标
1. 先确认那个限制确实存在
第 1 篇算过:任何 2×2 矩阵乘以原点 ,结果都还是 。
而平移的定义就是"把所有点(包括原点)挪到别处"。所以:
2×2 矩阵永远做不了平移。 这不是"还没找到合适的数字",是这类运算本身办不到。
图:缩放、旋转、切变——三种典型的 2×2 变换,形状怎么变都行,但那个黑点始终钉在原地。
这就麻烦了。图形管线希望把一长串变换乘成一个矩阵(第 2 篇第 4 节讲过),可是平移偏偏是最常用的操作之一。要么放弃"全部合并",每次变换都写成"矩阵乘一下、再单独加个偏移";要么想办法把平移也变成矩阵乘法。
图形学选了后者。
2. 加一维:把平面搬到 z = 1 那一层
办法出人意料地简单:把二维平面塞进三维空间里,放在 这个高度上。
也就是说,平面上的点 ,记成三维的 。
在三维空间里,有一种叫切变(shear)的线性变换:把每个点沿 方向推一段。写成矩阵是
代进去算算,对一个 的点:
加上了 , 没变, 还是 1。从这一层平面上看,这就是往右平移了 。
图:整层平面的 都是 1,所以"推的距离正比于 "这条规则对这一层的每个点给出的都是同一个数——推得一样远,也就是整体平移。
关键在于:切变是一个标准的线性变换,它在三维里完全可以用矩阵表达。 我们没有发明新运算,只是换了个维度看问题,平移就自动变成了矩阵乘法的一部分。
这套把 维问题抬到 维来做的坐标记法,叫齐次坐标(homogeneous coordinates)。
多出来的那个分量通常写作 :
3. 点的 w 是 1,方向的 w 是 0
第 1 篇列过一张表:点减点得到向量、点加向量得到点、而点加点没有意义。当时说这个区分只能靠命名和类型来维持。
齐次坐标把"平移应该影响点、不该影响方向"这个区别编进了数字本身:
- 点(位置)的 记作 1;
- 向量(方向、位移)的 记作 0。
让 分量跟着算术走,可以自动得到前四行这些有用的结果:
| 运算 | 怎么算 | 结果的 | 结论 |
|---|---|---|---|
| 点 − 点 | 0 | 得到向量 ✅ | |
| 点 + 向量 | 1 | 得到点 ✅ | |
| 向量 + 向量 | 0 | 得到向量 ✅ | |
| 向量 × 3 | 0 | 还是向量 ✅ | |
| 点 + 点 | 2 | 非零 ,归一化后仍是点;不能拿它当非法标记 |
最后一行要格外小心:齐次坐标不是类型检查器。 对两个规范化的点
直接相加会得到 ;除以 后,它表示的正是 、 的中点。这仍是一个有效的齐次点,并不会因为 自动"报错"。
问题在于,齐次表示允许整体乘任意非零倍数:同一个点既能写成 ,也能写成 。若直接拿不同倍数的表示相加,归一化后的权重也会跟着改变。因此"点 + 点"不是一个对齐次表示天然良定义的通用运算;要表达中点,应明确写成仿射组合 ,并让权重和为 1。是否合法仍靠运算语义或类型系统约束,不能只看 。
这还有一个立刻能用的推论。看第 2 节那个平移矩阵,把它作用在一个 的向量上:
平移对向量不起作用——完全正确,因为"往右 3 米"这个位移,不管你在哪儿说它,都还是"往右 3 米"。同一个矩阵,作用在点上会平移,作用在方向上不会,全靠 那一位自动区分。
这个性质在第 4 篇讲法线时会变成一件要紧事:法线是方向,绝不能被平移影响。用 表示它,这件事就自动成立了。
4. 3×3 矩阵的三块分区
现在可以给整个矩阵划分区了:
| 分区 | 管什么 |
|---|---|
| 左上 2×2() | 形状:旋转、缩放、翻转、切变 |
| 第三列() | 平移到哪 |
| 第三行(,末位通常是 1) | 透视 |
在第三行是 的仿射情形下,旋转、翻转、缩放写在左上角那块,平移写在第三列。要组合变换,就把对应的 3×3 矩阵相乘(第 2 篇第 4 节),一次矩阵乘法就能合并这些操作。第三行出现 后,还要结合最后的除法理解各块的作用。
分块读法说明各组系数的用途;逐行读法则说明输出坐标怎样算出来。下面把三行放在一起看,再分别改变每一行。
5. 逐行理解:第一行、第二行与第三行
仍采用矩阵左乘列向量的约定。对输入点 ,完整乘法是:
这里的撇号表示矩阵乘法后的齐次分量。当 时,最终二维坐标记为 :
| 行 | 直接算出的分量 | 对最终二维坐标的作用 |
|---|---|---|
| 第一行 | 决定 的分子 | |
| 第二行 | 决定 的分子 | |
| 第三行 | 决定 共用的除数 |
第一、第二行并不分别代表某一种完整变换:一行只负责一个输出分量,旋转等变换需要两行配合。第三行则能通过共同的除数同时影响两个坐标。
5.1 第一行:改变横向坐标
先固定第二行为 、第三行为 ,只改第一行:
此时 ,所以 、。三个系数分别决定原来的 、原来的 和常量偏移怎样贡献到新的横向坐标。
下面每种情况都从单位矩阵出发,独立修改第一行,输入点均为 :
| 第一行 | 坐标关系 | 点 的结果 | 几何效果 |
|---|---|---|---|
| 横向放大 2 倍 | |||
| 关于 轴镜像 | |||
| 横向切变,高度不同则横向偏移不同 | |||
| 所有点沿 平移 3 |
因此,第一行里的 不会直接改变输出的纵坐标;它让输入的纵坐标参与计算输出的横坐标。同样, 位于第三列,却通过第一行的求和改变横向位置。
5.2 第二行:改变纵向坐标
现在固定第一行为 、第三行为 ,只改第二行:
此时 、。仍对输入点 ,独立修改第二行:
| 第二行 | 坐标关系 | 点 的结果 | 几何效果 |
|---|---|---|---|
| 纵向放大 2 倍 | |||
| 关于 轴镜像 | |||
| 纵向切变,横向位置不同则纵向偏移不同 | |||
| 所有点沿 平移 3 |
的作用与上一节的 对称:它把输入的横坐标混入输出的纵坐标。这里用 表示方向;若屏幕坐标的 向下,增加 就是向下移动。
两行同时变化时,可以得到更完整的变换。例如在 向右、 向上的坐标系中,绕原点逆时针旋转 :
第一行给出 ,第二行给出 ,两者一起将 变成 。只改其中一行不能完成这次旋转。
5.3 第三行:改变两个坐标共用的除数
前两节固定第三行为 。对规范化的输入点 ,它给出的结果是:
输出的 恒为 1,不随输入的 改变。所以做完变换,点仍在 那一层,第一、第二行算出的 就是最终二维坐标。
现在让前两行恢复单位矩阵的形式 、,只把第三行里的 改成 0.35:
此时 、,但 随着 变了。虽然前两行没有修改,最终仍要把两个坐标一起除以 ,所以 和 都会受到影响。
这就需要明确齐次三元组与二维点的对应关系。
齐次的含义:一整条射线代表同一个点
答案是:把它拉回 那一层,看它落在哪。 拉回的办法就是三个分量都除以 。
图:从原点出发穿过某个点的那条射线上,所有点代表的都是同一个二维坐标。图中使用 、、,各自除以第三个分量,都得到 。
验算一下最后那个:
这个"除以 "的动作叫透视除法(perspective divide)。"齐次"这个名字就是这么来的——同比例放大整个三元组,代表的还是同一个点。
至此问题 3 的答案也齐了:多出来的坐标 ,记的是这个点在三维空间里所处的"高度"——点待在 那一层,所以记 1;方向用 声明"我不参与平移";变换之后 不再是 1,就用三个分量除以 ,把它拉回那一层。
除完之后的几何效果
图:左边第三行是 , 恒为 1,除不除都一样,方格还是方格。右边第三行是 , 越大 越大,除完之后坐标就被压缩得越狠——方格网变成了梯形,原本平行的竖线不再平行。
平行线不再平行、远处的东西变小——这正是"透视"这个词在日常语境下的意思。所以第三行被称为透视行,不是打比方,是名副其实。
拿一个具体的数走一遍。第三行取 、其余部分保持单位矩阵,作用在点 上:先算输出的第三个分量
再把 、 除以 :
本来 的地方,变换后被"压缩"到了约 ;而 处 ,分毫未动。 越大压得越狠——正是上图右边那幅样子。
完整计算分成两步:先用三行分别算出 ,再在 时得到 。本例因为前两行保持单位形式,才可以直接用原始 作分子;一般矩阵不能省略前两行的计算。
当 且 时,输出表示无穷远点,没有有限的二维坐标,不能进行这次除法。若三个输出分量全为零,则不是有效的齐次点。
仿射变换可以省去除法。 对规范化输入点,第三行是 时除数恒为 1,因此可直接使用前两行的结果。常见的二维平移、旋转、缩放和切变都属于这种情形;具有透视效果的二维变换则需要保留这一步。
6. 升到 4×4:同一招再用一次
三维的情况完全对称:三维点 记成四维的 ,用 4×4 矩阵,第四列管平移,第四行管透视。
那一个纯二维的 3×3 怎样搬进 4×4?直接把它写出来:
读法:原来的"形状块"照搬,原来的"平移列"挪到第四列,原来的"透视行"挪到第四行,中间新插进来的那一行一列是单位变换——新的第三维完全不参与。这也符合直觉:一个纯二维的变换,不该对 做任何事。验一下:新矩阵的第三行是 ,作用在 上, 原样进来、原样出去。
顺带一提:上面的矩阵按数学惯例书写。同一个 4×4 落到具体代码里时,存储布局有行主序、列主序两种约定,同一个变换的数字排法会不一样,见延伸阅读。
第 4 篇开始,我们要用的就是完整的 4×4 了。
自测
问题 1:为什么 2×2 装不下平移?
因为 2×2 矩阵乘法是线性变换,而线性变换必把原点映到原点——无论四个数字怎么填,原点乘完还是原点(第 1 节)。可平移的定义恰恰是"把所有点(包括原点)挪到别处"。实验图里缩放、旋转、切变三种变换,形状怎么变都行,原点上的黑点却始终钉在原地。这不是还没找到合适的数字,是这类运算本身办不到。
问题 2:加一维之后,平移、旋转、翻转怎样合并进同一个矩阵?
把平面抬到 那一层,三维的切变落到这层上就是二维的平移(第 2 节),平移从此也能写成矩阵乘法。于是 3×3 矩阵可以一次装下三块分区:左上 2×2 写旋转、翻转、缩放、切变,第三列写平移(第 4 节)。比如把一个图层水平翻转再摆回原位:翻转写进左上块,图形翻到负半轴之后,第三列再写上补偿的平移把它拉回来——全部装在同一个矩阵里,一次乘法完成。
问题 3:多出来的那一维坐标(w)代表什么?
它是点被抬进三维空间后的第三个坐标。点记 ,因为平面本身就放在 那一层;方向记 ,平移因此自动对它不起作用(第 3 节)。变换之后 不再是 1 时,三个分量除以 就能把点拉回那一层——这个除法叫透视除法,顺带解锁了"远处变小"的透视效果(第 5 节)。
以后再看到一个 3×3(或 4×4)矩阵,先切三刀:左上角那块看形状,最后一列看平移,最后一行看有没有透视。三块各管各的,一眼就能读出这个矩阵大概要干什么。
1. 齐次坐标 (6, 4, 2) 对应二维平面上的哪个点?
。
三个分量都除以 :,前两个分量就是答案。
顺带一提,、、 是同一个点的三种写法——这就是"齐次"。
2. 把平移矩阵作用在 (5, 3, 0) 上,结果是什么?这说明了什么?
结果还是 ,一点没变。
因为 ,平移列里的 、 都要乘以 才能加进来,乘 0 之后就没了。
这说明 的三元组表示方向而不是位置,而平移对方向本来就不该有影响。"往右 3 米"这个位移,在哪儿说都是"往右 3 米"。
3. 一个 3×3 矩阵的第三行是 (0, 0, 2),其余部分是单位矩阵。它对图形做了什么?
把图形整体缩小到一半。
,恒为 2。所有点除以 2,于是 。
这也说明第三行的最后一个数不是必须为 1——它对所有点来说是个全局缩放因子。恒为 1 只是最省事的归一化选择。
4. 变换之后某个点的 w' 算出来是 0,几何上意味着什么?能否直接当作原点?
若 不同时为 0,输出表示无穷远点。 的方向平行于 平面,没有对应的有限二维坐标。若三个分量全为 0,则不是有效的齐次点。
不能把它改成 :那会把无穷远点错误地变成原点。应保留它的齐次含义,或在具体投影过程中按有效范围处理图元,避免直接除以零。
5. 把二维的 3×3 搬进三维的 4×4 时,为什么新插进来的第三维对角位置要设成 1 而不是 0?
因为那是新插进来的第三维()自己对自己的系数,设成 1 表示" 原样保留",也就是对第三维做单位变换。
设成 0 的话,任何点的 都会被压成 0,整个三维空间被拍扁成一个平面——那可不是"把二维变换升维",那是把三维内容毁掉。
6. 为什么水平翻转加垂直翻转等于旋转 180°?
两次翻转的线性部分是
这正是 180° 旋转;第三列的平移量负责把结果放回原来的矩形。
7. 把翻转和旋转合并进同一个矩阵时,为什么"先翻转再旋转"和"先旋转再翻转"的结果不一样?
矩阵作用在列向量上时,靠近向量的先生效。所以"先垂直翻、再水平翻、最后旋转"和"先旋转、再翻转"是两种完全不同的复合变换,非方形的图形换了顺序就会落到不同的位置——矩阵乘法不满足交换律,第 2 篇里已经用字母 F 见识过了。
8. 只把第一行改成 (1,1,0),或只把第二行改成 (1,1,0),对点 (1,2) 的结果各是什么?其余行保持单位矩阵形式。
只改第一行时,、、,结果为 ,是横向切变。
只改第二行时,、、,结果为 ,是纵向切变。
相同的三个系数放在不同行,计算的是不同的输出分量,不能只看数字而忽略所在行。
9. 矩阵三行分别为 (2,0,3)、(0,1,−1)、(0,0.5,1),点 (1,2) 最终变到哪里?
先分别计算三个齐次分量:
再进行归一化:
除数来自第三行,分子来自前两行;不能算完 后直接拿原始点 去除。
小结
| 概念 | 一句话 | 对应位置 |
|---|---|---|
| 为什么加一维 | 2×2 挪不动原点,平移塞不进去 | 第 1 节:三种 2×2 变换都挪不动原点 |
| 齐次坐标 | 把平面放到 层,三维切变 = 二维平移 | 第 2 节:一次切变让整层平移 |
| 点 vs 方向 | 点的,方向的 | 自测 2:平移对 不起作用 |
| 点+点的限制 | 归一化后仍是点,不能充当非法标记 | 第 3 节:点+点归一化后是中点 |
| 三块分区 | 左上=形状,末列=平移,末行=透视 | 第 4 节:三色分区图 |
| 第一行 | 算出 ,决定横坐标的分子 | 第 5.1 节:横向缩放、镜像、切变与平移 |
| 第二行 | 算出 ,决定纵坐标的分子 | 第 5.2 节:纵向变化及两行配合的旋转 |
| 第三行 | 算出 ,提供两个坐标的共同除数 | 第 5.3 节:前两行不变也能改变最终坐标 |
| 透视除法 | 除以,把点拉回 那层 | 第 5 节:方格网变梯形 |
| 齐次的含义 | 一条过原点的射线代表同一个点 | 第 5 节:同一射线上的三个三元组 |
| 非零齐次输出表示无穷远点,不能直接除或改成原点 | 自测 4:区分无穷远点与无效的全零输出 | |
| 仿射情形 | 第三行是 ,规范化点的 恒为 1 | 第 5.3 节:可直接使用前两行结果 |
| 升到 4×4 | 同一招再用一次,末列平移、末行透视 | 第 6 节:新插的行与列是单位变换 |
延伸阅读
- 3Blue1Brown《线性代数的本质》第 9 集附录(三维中的线性变换):https://www.bilibili.com/video/BV1ys411472E
- GAMES101 Lecture 4:Transformation Cont.(齐次坐标部分):https://games-cn.org/intro-graphics/
- Scratchapixel: Geometry — Row Major vs Column Major Vector:https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/geometry/row-major-vs-column-major-vector.html

觉得有用?关注公众号「阿豪讲Framework」
Android 系统开发,新文章第一时间推送。