想象你是一位动画电影导演,要拍摄一部叫做《小美奇遇记》的3D动画。主演小美是个圆滚滚的立方体机器人,她得先在自己的化妆间里摆好姿势(这间化妆间以她为中心),然后走到舞台上站到指定位置,导演老张扛起摄像机从某个角度对准她,镜头取景框决定哪些画面能进电影,最后信号录进录像带变成观众看到的二维画面。这整个过程,就是 3D 图形中一个顶点从“模型空间”一路变身成“屏幕像素”的坐标之旅。 本节课我们要拆解的,正是这条 3D 坐标变换流水线:模型空间 → 世界空间 → 视图空间 → 裁剪空间 → 屏幕空间。每个空间都有自己的坐标系,靠一个个 4×4 矩阵把顶点接力传递。掌握了这条管线,你就理解了 3D 引擎(如 Unity、Unreal)乃至游戏显卡最核心的数学运作逻辑。哪怕你未来做 AI 渲染、三维重建或自动驾驶仿真,都和这一套变换密不可分。
这一课是走进计算机图形学大门的“数学钥匙”。无论做游戏开发、三维建模工具还是 AI 视觉仿真,理解坐标变换都能让你看懂引擎源码、定位渲染 Bug,并亲手搭建自己的 3D 管线。
可视化演示
动态演示3D坐标变换的核心机制,通过采集/分析/决策/反馈四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
3D坐标变换:模型空间 模型空间与世界空间的模型变换 世界空间到视图空间的视图变换 核心机制可视化 3D坐标变换整体架构与关键组件
模型空间变换
清晨的化妆间里,小美站在一个标着原点的地板上。造型师用量尺记录她每个部位的位置:眼睛在 (0, 0.8, 0.5),左脚在 (-0.3, 0, 0),右脚在 (0.3, 0, 0)。这些坐标全都以小美自己为参考点——她往左转,坐标跟着转;化妆间搬走了,坐标依然不变。这个以物体自身为中心的坐标系,就叫模型空间,也叫本地空间。
3D 建模软件(如 Blender、Maya)中,美术师雕刻模型时看到的网格坐标,就是模型空间坐标。一个模型可能包含成千上万个顶点,每个顶点在模型空间里都有一个固定的三维位置。为什么要多此一举建一个“以自己为中心”的空间?因为这样小美的模型文件才能被反复复用——今天她演主角,明天当群演,模型本身不用改,只需要在场景里给她安排一个位置就行。
在数学上,我们把模型空间里的一个顶点记作列向量。为了后面统一做矩阵乘法,这里引入齐次坐标,多写一个 1:
化妆间里的坐标,就是模型空间。 它记录的是“小美自己身体上每个点长在哪”,跟舞台在哪、摄像机在哪完全无关。如果顶点位置定义在建模时出错——比如把左脚坐标写成了右脚——那模型一进引擎就会“天生残疾”。
- 三维坐标$x$、$y$、$z$ 分别是顶点相对模型原点的左右、上下、前后距离,单位通常是米或引擎自定义的单位。
- 补上齐次分量在末尾添加一个值为 1 的第四分量,它让平移、旋转、缩放都能统一成矩阵乘法,是后续透视投影的关键伏笔。
世界空间变换
导演老张拿着剧本说:“小美,你站到舞台正中央偏右的位置,面向观众席。”场务在舞台地面上铺了一张大坐标纸,以舞台中心为原点,标好了东南西北。小美走出化妆间,走到位置 (3, 0, 2),再转了 30° 面向观众。此时,她身体上的每个点都获得了一个全新的、以舞台为中心的坐标——这就是世界空间。
从模型空间到世界空间,靠的是模型矩阵(Model Matrix)。它把“小美身上各点相对她自己”的坐标,变成“相对整个舞台”的坐标。这个矩阵由三个基础变换组合而成:缩放 S(小美今天要求把自己放大 1.2 倍,显得更有气势)、旋转 R(面向观众转 30°)、平移 T(走到舞台上的指定位置)。
小美走进舞台的那一刻,她的每个顶点都完成了从“化妆间坐标”到“舞台坐标”的换算。 世界空间里,所有演员、道具、灯光都共享同一套坐标,这样小美站在 (3, 0, 2) 时,灯光师才能准确地把光束打在她头顶。
- 先缩放$S$ 沿三个轴方向分别缩放模型,缩放不改变顶点相对模型原点的方向,只改变“身体比例”。
- 再旋转$R$ 让模型绕某个轴转动。旋转也不会改变顶点到原点的距离,只是改变它相对模型的朝向。
- 最后平移$T$ 把整个模型搬移到舞台的指定位置。平移是“整体搬家”,矩阵里放在左上角第四列。
- 从右往左乘矩阵乘法从右往左生效。顶点先经过 $S$,再经过 $R$,最后经过 $T$。顺序不能调换——先旋转再平移,和先平移再旋转,小美在舞台上的位置和朝向会完全不同。
视图空间变换
现在轮到导演老张了。他没有站上舞台,而是扛着摄像机退到观众席后方,半蹲下来,以 30° 的俯角对准小美。世界空间是“上帝视角”的全局坐标,但摄像机拍到的画面,取决于摄像机的位置和朝向。视图空间,就是以摄像机为原点的坐标系:摄像机所在位置是原点,它看的方向是前方,它的头顶方向是上方。
世界坐标变到视图坐标,靠的是视图矩阵(View Matrix)$V$。这个矩阵通常由 LookAt 函数构造:你告诉它摄像机在哪(eye)、看点在哪(center)、哪个方向是上(up),它就能生成一个矩阵,把整个世界重新摆放到“摄像机面前”。
导演把摄像机架好,整个舞台就活在了他的镜头坐标系里。 视图空间里,小美站在摄像机前方负 Z 方向,左右上下都相对摄像机而言。此时无论世界坐标多么复杂,后续的投影都只需关心“摄像机看到了什么”。
- 确定三个基向量由视线方向 $f$(center − eye 归一化)、右方向 $s$($f$ 与 up 叉积归一化)、上方向 $u$($s$ 与 $f$ 叉积)构成摄像机坐标系的三根轴。
- 构造视图矩阵把三根轴写成矩阵的行,并用它们与摄像机位置的点积完成平移部分,实现“把摄像机搬回原点”。
齐次坐标原理
细心的你可能会问:为什么每个顶点都要写 4 个数?三维坐标 (x, y, z) 不是挺好吗?让我们回到剧组的工牌制度。每个演职人员都挂一张工牌:正常演员工牌号是 1,意味着他是“具体的点”,有实际位置;而另一种工牌号是 0,代表“方向”——比如灯光师说的“光束朝正前方打”,这只是个方向,不代表“舞台上某个位置有个人”。
这个多出来的维度,就是齐次坐标中的 $w$ 分量。引入它的核心原因有两个:第一,把平移变成矩阵乘法。三维空间中平移 $x + t$ 没法写成 3×3 矩阵乘法(因为矩阵乘法无法表达加法),但升到四维后,平移也能用 4×4 矩阵统一表达。第二,为透视除法埋下伏笔——后面做透视投影时,$w$ 会携带深度信息。
用分块矩阵的写法,能一眼看清齐次坐标如何优雅地统一旋转、缩放与平移:
齐次坐标就像剧组工牌,用第四维的小小标记把“点”和“方向”区分开。 它让所有变换统一成 4×4 矩阵乘法,GPU 也因此能用同一套硬件电路快速处理所有顶点变换——这是 3D 图形学最优雅的数学设计之一。
- 分块表示左上角的 $R$ 是 3×3 旋转/缩放矩阵,右上角的 $t$ 是三维平移向量,底行是 $(0,0,0,1)$。
- 对点作用计算过程是“先做旋转缩放,再加平移”,这正是仿射变换的数学本质:线性变换 + 平移。
- $w$ 分量的工程含义点(工牌号为 1)平移会改变位置;方向向量(工牌号为 0)平移后不变——所以灯光的朝向不受摄像机位置影响。
裁剪空间变换
摄像机架好了,但导演老张不可能把所有东西都拍进画面——太远的山、太近的镜头贴脸、左右超出镜头边缘的布景,都得裁掉。视锥体(Frustum)就是导演的“取景范围”:一个近平面、一个远平面、上下左右四个斜面围成的平截头体。只有落在视锥体内的顶点才需要渲染。
把视图空间变换到裁剪空间,靠的是投影矩阵 $P$。投影矩阵一方面把视锥体“压扁”成一个标准盒子,方便后续裁剪;另一方面在 $w$ 分量里写入深度,为近大远小做准备。这是整个管线里最有“魔法感”的一步:
视锥体就是导演的取景框,投影矩阵则负责把三维世界“压”进这个框。 注意这里的裁剪空间坐标还带着 $w$ 这个附加维度,真正的“压扁”要等下一步透视除法来完成。
- 焦距缩放 $m$$m = \dfrac{1}{\tan(\text{fov}/2)}$,fov 是摄像机纵向视场角。视场角越大,看到的范围越广,物体显得越小。
- 横向修正 $aspect$屏幕宽高比(如 16:9)修正横向缩放,保证画面不被拉伸变形。
- 深度映射第 3 行第 3、4 列把视图空间的深度映射到裁剪空间的 $z$ 范围,并引入近平面 $n$ 与远平面 $f$。
- $w$ 分量写入 $-z$第 4 行第 3 列为 -1,把视图空间深度以 $-z$ 的形式存进 $w$——这是透视除法的关键输入。
透视除法与NDC
现在到了最激动人心的时刻。投影矩阵已经计算出了 $P_{\text{clip}} = (x, y, z, w)$,但我们真正想要的,是把这个带 $w$ 的四维坐标变成标准化的三维坐标。方法出奇简单:用 $w$ 去除以 $x$、$y$、$z$。这就是透视除法。
除法听起来简单,效果却神奇:因为离摄像机越远的顶点,它的 $-z$ 越大,$w$ 也就越大,除以 $w$ 后 $x$、$y$ 被压缩得越厉害——于是远处的物体变小了,近大远小就这样诞生了。除法后的坐标称为 NDC(Normalized Device Coordinates,规范设备坐标),它的 $x$、$y$、$z$ 都被限制在 [-1, 1] 范围内,这个标准盒子让后续所有工作变得极其简单。
透视除法相当于导演把取景框里的画面“打印”成一张标准底片。 谁离摄像机近,谁在底片上占比大;谁离得远,谁就缩成一个小点。深度值也在这时被规整成统一尺码,为后续的深度测试(判断谁遮挡谁)铺好了路。
- x 分量除法裁剪空间的 $x$ 除以 $w$,得到水平方向的规范化坐标,范围约在 [-1, 1] 之间。
- y 分量除法同理处理纵向坐标,$y=0$ 表示屏幕中线,$y=1$ 是屏幕顶端(不同图形 API 的上下方向略有差异)。
- z 分量除法$z$ 也除以 $w$,得到线性化的深度值:近平面处为 -1,远平面处为 1(以 OpenGL 为例)。
视口变换映射
底片洗出来了,但观众要看的是电影院的银幕——可能是 1920×1080 的横屏,也可能是手机 1080×2400 的竖屏。视口变换就是把 NDC 标准盒子里的坐标(范围 [-1, 1]),映射到屏幕的像素坐标系(范围 [0, width] × [0, height])。
这一步没有矩阵,只是简单的线性映射。把 NDC 的 -1 映射到屏幕 0,+1 映射到屏幕宽/高,中间按比例均匀分布。视口矩形(viewport rectangle)决定映射到屏幕的哪个区域——比如游戏分屏时,左半边玩家、右半边玩家,各自映射到不同的视口区域。
从底片到银幕,只需要一个比例尺。 同样的 NDC 坐标,在 4K 银幕上映射出 3840 个像素,在手机屏幕上映射出 1080 个像素——这就是分辨率适配的底层逻辑。
- 把 [-1, 1] 归一化到 [0, 1]$(x_{\text{ndc}} + 1) / 2$ 把 -1 变成 0,把 1 变成 1,中间值线性映射。
- 乘屏幕尺寸$u$、$v$ 乘以像素宽高,得到像素坐标。注意 $y$ 方向取反,因为 NDC 的 $y$ 朝上,而屏幕像素的 $y$ 朝下。
- 加上视口偏移如果画面不是铺满全屏(比如分屏),要加上视口矩形左上角的像素偏移。
变换管线串联
现在把全部旅程串起来。小美从化妆间出发(模型空间),走到舞台指定位置(世界空间,模型矩阵 M),导演从摄像机角度观看(视图空间,视图矩阵 V),经过取景框压缩和透视除法(裁剪空间与 NDC,投影矩阵 P),最后被印上银幕(屏幕空间,视口变换)。完整管线如下:
实际操作中,CPU 会把三个矩阵预先乘成一个 MVP 矩阵($M_{\text{proj}} \times V_{\text{view}} \times M_{\text{model}}$),每个顶点只需做一次矩阵乘法。 小美从化妆间到银幕的旅程,最终被压缩成一行矩阵乘法——这就是 3D 引擎渲染千万个顶点依然能保持流畅的秘密。
- 模型矩阵 M模型空间 → 世界空间,包含缩放、旋转、平移。
- 视图矩阵 V世界空间 → 视图空间,把场景摆到摄像机面前。
- 投影矩阵 P视图空间 → 裁剪空间,用视锥体压缩场景,并把深度写入 $w$。
- 透视除法与视口变换裁剪空间 → NDC → 屏幕像素坐标,最终得到画面上该顶点的二维位置。
AI 应用场景
游戏引擎中的场景对象管理
阶段:游戏 AI 与场景理解
解决的问题:在 Unity 或 Unreal 中,策划需要在场景里放置成百上千个 NPC、道具和建筑。如果每个物体都手工维护各自的顶点坐标,场景编辑将是一场灾难。借助模型→世界变换,每个预制体(Prefab)只需保存本地的模型资源,场景中指定位置、旋转、缩放即可复用。
具体案例:在 Unity 中拖拽一个小美角色到场景中,Inspector 面板显示 Transform 组件的 Position (3, 0, 2)、Rotation (0, 30, 0)、Scale (1.2, 1.2, 1.2)。引擎后台自动构造模型矩阵,把预制体的所有顶点变换到世界空间。AI 寻路系统、碰撞检测和 NavMesh 都在世界空间里工作,大家共享同一套坐标。
三维建模软件的视图导航
阶段:交互式三维可视化
解决的问题:用户在 Blender 中按住鼠标中键旋转视角时,模型本身没动,动的是摄像机。传统做法需要手动计算每个顶点相对新视角的位置,而视图矩阵让这个过程变成一次矩阵更新。
具体案例:Blender 的 3D 视口中,用户旋转视角时,软件实时更新视图矩阵(LookAt 的 eye 点在球面上移动,center 始终指向模型中心),GPU 对每个顶点重新做 view 变换,画面便以每秒钟 60 帧的速度平滑旋转。AI 辅助建模工具(如自动生成模型后预览)也依赖这套视图管线。
AR/VR 中虚拟物体的空间锚定
阶段:空间计算与位姿估计
解决的问题:AR 眼镜要在真实世界的桌面上放一个虚拟咖啡杯,必须知道设备的精确位置和朝向(六自由度位姿)。位姿数据被编码成视图矩阵和投影矩阵,虚拟物体才能稳定地“粘”在桌面上,不随头部晃动而漂移。
具体案例:HoloLens 通过 SLAM 算法估计设备位姿,每帧把位姿转换成视图矩阵,配合透视投影矩阵渲染虚拟内容。当 AI 识别出桌面平面后,虚拟咖啡杯的模型空间坐标通过 M→V→P 变换,叠加到真实场景的对应像素位置上,实现逼真的混合现实效果。
Python 演示
import numpy as np def mat_model(tx, ty, tz, ry, sx, sy, sz): # 模型矩阵 = 平移 x 旋转 x 缩放 S = np.array([ [sx, 0, 0, 0], [0, sy, 0, 0], [0, 0, sz, 0], [0, 0, 0, 1]], dtype=float) c, s = np.cos(ry), np.sin(ry) R = np.array([ [c, 0, s, 0], [0, 1, 0, 0], [-s, 0, c, 0], [0, 0, 0, 1]], dtype=float) T = np.array([ [1, 0, 0, tx], [0, 1, 0, ty], [0, 0, 1, tz], [0, 0, 0, 1]], dtype=float) return T.dot(R.dot(S)) def mat_view(eye, target, up): # LookAt 视图矩阵 f = target - eye f = f / np.linalg.norm(f) s = np.cross(f, up) s = s / np.linalg.norm(s) u = np.cross(s, f) return np.array([ [s[0], s[1], s[2], -np.dot(s, eye)], [u[0], u[1], u[2], -np.dot(u, eye)], [-f[0], -f[1], -f[2], np.dot(f, eye)], [0, 0, 0, 1]], dtype=float) def mat_proj(fov, aspect, near, far): # 透视投影矩阵 m = 1.0 / np.tan(fov / 2.0) return np.array([ [m / aspect, 0, 0, 0], [0, m, 0, 0], [0, 0, (far + near) / (near - far), 2 * far * near / (near - far)], [0, 0, -1, 0]], dtype=float) def main(): # 小美:中心在原点的单位立方体,8 个顶点 vertices = np.array([ [-0.5, -0.5, -0.5, 1], [0.5, -0.5, -0.5, 1], [0.5, 0.5, -0.5, 1], [-0.5, 0.5, -0.5, 1], [-0.5, -0.5, 0.5, 1], [0.5, -0.5, 0.5, 1], [0.5, 0.5, 0.5, 1], [-0.5, 0.5, 0.5, 1]], dtype=float) # 三步:搬运到世界 -> 摄像机取景 -> 透视压缩 M = mat_model(0, 0, -6, 0.5, 1, 1, 1) V = mat_view(np.array([0, 0, 0]), np.array([0, 0, -1]), np.array([0, 1, 0])) P = mat_proj(np.deg2rad(60), 16.0 / 9.0, 0.1, 100.0) MVP = P.dot(V.dot(M)) # 变换到裁剪空间 clip_pts = [MVP.dot(p) for p in vertices] # 透视除法 + 视口映射 width, height = 800, 450 screen_pts = [] for c in clip_pts: ndc = c[:3] / c[3] sx = (ndc[0] + 1) / 2.0 * width sy = (1 - ndc[1]) / 2.0 * height screen_pts.append((round(sx, 1), round(sy, 1), round(ndc[2], 4))) for row in screen_pts: print(row) if __name__ == "__main__": main()
MVP = P.dot(V.dot(M))把投影、视图、模型三个矩阵预乘成一个 MVP 矩阵,每个顶点只需一次矩阵乘法,这是 GPU 渲染管线的高效核心。clip_pts = [MVP.dot(p) for p in vertices]对 8 个顶点分别做矩阵乘法,得到裁剪空间坐标,此时坐标仍是四维的(x, y, z, w)。ndc = c[:3] / c[3]透视除法:用 w 分量同时除 x、y、z,实现近大远小,得到 NDC 坐标。sx = (ndc[0] + 1) / 2.0 * width视口变换的 x 映射:从 [-1, 1] 线性映射到 [0, width] 像素范围。
常见误区
误区我一开始以为模型空间变换完,还要再乘一个“世界矩阵”才能到世界空间,所以写了两个矩阵,结果场景里物体位置全乱了。
正解模型矩阵就是“从模型空间变换到世界空间”的那个矩阵,它是一个整体,内部由缩放、旋转、平移组合而成。没有单独的“世界矩阵”这回事。就像小美从化妆间到舞台只有“走一段路”这一个动作,而不是“先走到门口再走到舞台”两个独立动作。
为何常见:很多教程把 M、V、P 三个矩阵并列介绍,初学者容易误以为 M 内部还有多个子矩阵要对顶点依次作用,实际它们已经合并成一个矩阵了。
误区我写代码时先做了透视除法,再把结果拿去裁剪,结果屏幕边缘出现了奇怪的重影。
正解正确顺序是:先做投影矩阵变换得到裁剪空间坐标,在裁剪空间里判断顶点是否在视锥体内(硬件裁剪),然后才做透视除法得到 NDC。如果把除法提前,w 分量就丢了,裁剪判断失去了正确的深度依据。就像导演得先看取景框决定谁进画面,再洗照片,不能先洗照片再决定裁剪。
为何常见:透视除法公式简单(除以 w),看起来像是一个“收尾步骤”,容易被随手提前;但裁剪阶段依赖的是 w 未除之前的齐次坐标范围。
误区第四维 w 就是数学上为了让矩阵变成方阵硬凑出来的,反正永远是 1,没什么实际意义。
正解齐次坐标有两个重要工程作用:一是让平移也能写成矩阵乘法,否则必须单独做加法;二是 w 在透视除法中携带深度信息,是实现近大远小的关键。此外 w=0 可以表示方向向量(如灯光方向),这在线性代数层面解决了“方向不受平移影响”的问题。
为何常见:在模型和世界变换阶段 w 确实恒为 1,看起来“没用”;直到透视投影阶段 w 才开始承载深度,初学者没走到那一步自然感受不到它的价值。
误区矩阵乘法反正都是乘,我习惯先乘平移再乘旋转,结果物体绕了奇怪的点转圈。
正解矩阵乘法不满足交换律。正确习惯是先缩放、再旋转、最后平移(S→R→T),这样旋转是绕模型自身原点转的,符合“先摆姿势、再转身、最后走到指定位置”的直觉。顺序反过来,旋转会变成绕世界原点转,物体就像被甩出去一样。
为何常见:小学数学里乘法交换律深入人心,矩阵乘法打破了这一直觉;而且初学时只验证过一个轴的简单情况,看不出顺序差异。
面试题
Q1. 在齐次坐标中,一个“点”的 w 分量通常取什么值?
- A.0,表示方向向量
- B.1,表示具体位置← 正确答案
- C.任意实数都可
- D.等于 x、y、z 的平均值
答案:B。齐次坐标中 w=1 表示具体的点(工牌号为 1 的演员),w=0 表示方向向量(只指示方向的灯光)。本题考察对 w 分量语义的基本理解,其余选项都不符合齐次坐标的定义。
Q2. 模型空间(本地空间)的坐标系原点位于哪里?
- A.世界舞台的中心
- B.摄像机镜头的位置
- C.物体自身设定的基准点← 正确答案
- D.屏幕的左上角像素
答案:C。模型空间以物体自身为原点,美术师建模时所有顶点都相对这个基准点定义。世界中心属于世界空间,镜头位置属于视图空间,屏幕左上角属于屏幕空间。这正是“化妆间坐标”的比喻含义。
Q3. 模型矩阵组合 M = T × R × S 中,顶点实际经历的变换顺序是?
- A.先平移、再旋转、最后缩放
- B.先缩放、再旋转、最后平移← 正确答案
- C.先旋转、再平移、最后缩放
- D.三个变换同时作用于顶点
答案:B。矩阵乘法从右往左生效,所以顶点先乘 S 做缩放,再乘 R 旋转,最后乘 T 平移。顺序不能调换,否则旋转会绕错误中心进行——这正是“先摆姿势再转身最后走位”的剧组流程。
Q4. NDC(规范设备坐标)中 x、y、z 分量的取值区间是?
- A.[0, 1]
- B.[0, width] 与 [0, height]
- C.[-1, 1]← 正确答案
- D.[-∞, +∞]
答案:C。透视除法后的 NDC 坐标三个分量都被规范化到 [-1, 1] 区间,这个标准盒子让裁剪、深度比较和视口映射都变得简单。[0,1] 是深度缓冲常用的映射区间,[0,width] 是屏幕像素区间。
Q5. 透视除法在整个管线中的正确位置是?
- A.模型变换之前
- B.视图变换之前
- C.裁剪判断之后、视口变换之前← 正确答案
- D.屏幕像素输出之后
答案:C。管线顺序是投影矩阵得到裁剪坐标 → 裁剪判断 → 透视除法得到 NDC → 视口变换得到屏幕坐标。透视除法必须在裁剪之后进行,因为裁剪依赖 w 分量未除之前的齐次坐标做范围判断。
Q6. 以下哪些操作可以统一用 4×4 变换矩阵表达?
- A.模型的平移← 正确答案
- B.模型的旋转← 正确答案
- C.模型的缩放← 正确答案
- D.顶点颜色的混合
答案:ABC。平移、旋转、缩放都是仿射变换,借助齐次坐标可统一写成 4×4 矩阵。颜色混合属于像素着色阶段,与几何坐标变换无关,不能由变换矩阵表达。
Q7. 构造 LookAt 视图矩阵时,必须提供哪三个输入?
- A.物体位置、物体旋转、物体缩放
- B.摄像机位置、观察目标点、上方向← 正确答案
- C.视场角、宽高比、近裁剪面
- D.世界原点、世界三轴、世界缩放
答案:B。LookAt 函数的三个参数是 eye(摄像机位置)、center(观察目标点)、up(上方向),由它们推导出视图矩阵的三根基向量。视场角和宽高比属于投影矩阵参数,与视图矩阵无关。
Q8. 关于透视投影和正交投影,下列说法正确的是?
- A.透视投影会产生近大远小效果← 正确答案
- B.正交投影适合工程制图类应用← 正确答案
- C.正交投影也需要透视除法← 正确答案
- D.透视投影的 w 分量恒为 1
答案:ABC。透视投影的 w 分量包含深度信息,除法后产生近大远小;正交投影的 w 恒为 1,不做透视除法(相当于除 1),因此平行线保持平行,常用于 CAD 制图。C 项说“正交投影也需要透视除法”有一定迷惑性——它形式上也会除以 w,只是 w 恒为 1,结果不变。
Q9. 视口变换的主要作用是什么?
- A.把顶点变换到世界空间
- B.把 NDC 坐标映射为屏幕像素坐标← 正确答案
- C.对顶点执行透视除法
- D.判断顶点是否在视锥体内
答案:B。视口变换是管线最后一步,把 [-1,1] 的 NDC 坐标按屏幕宽高线性映射为像素坐标。世界空间变换、透视除法、裁剪分别对应其他管线阶段。
Q10. 关于 MVP 矩阵 P_clip = M_proj × V_view × M_model × P_model,以下说法正确的是?
- A.矩阵从右往左依次应用,模型变换最先执行← 正确答案
- B.三个矩阵可以在 CPU 端预先合并成 MVP 矩阵← 正确答案
- C.改变摄像机位置时,只需更新 V 矩阵← 正确答案
- D.模型缩放不会影响最终屏幕上的像素范围
答案:ABC。矩阵右乘先生效,模型最先变换;CPU 可预乘 MVP 减少 GPU 计算量;摄像机移动只影响视图矩阵 V。而模型缩放会影响顶点在裁剪空间的坐标范围,进而影响屏幕上的像素大小,因此 D 错误。