“相机在看物体”只是直觉。数学上并没有真的搬动一台相机,而是不断换坐标系,最终把三维点映到二维屏幕。

1. 换坐标系到底在算什么
设新坐标系的三条基向量为 u,v,w,原点为 q。从新坐标到旧坐标可写成
C=uxuyuz0vxvyvz0wxwywz0qxqyqz1.
若已知一个点在旧坐标中的表示,要得到它在新坐标中的坐标,就用 C−1。这里常见的混淆是:
- 变换几何:真的把点移动了。
- 变换坐标:点没动,只换一把尺子描述。
两者矩阵互为逆,但数字可能长得很像。
2. 物体、世界与相机坐标
模型通常在自己的局部坐标里建好,模型矩阵 M 把它摆进世界。每个物体可以有不同的 M,世界坐标则让所有物体共享同一参照。
相机矩阵 C 表示“相机局部坐标怎样进入世界”;视图矩阵要把世界改写到相机坐标,因此
V=C−1.
给定相机位置 e、观察目标 c 和参考上方向 up,OpenGL 风格相机可取
z=∥e−c∥e−c,x=∥up×z∥up×z,y=z×x.
相机朝本地 −z 方向看。把这组基和相机位置组成 C 后求逆,或直接利用旋转矩阵转置,就得到 LookAt 视图矩阵。
3. 法线为什么用逆转置
假设切向量 t 与法线 n 正交,即 tTn=0。几何变换后切向量为 Mt。要让新法线 n′ 仍满足
(Mt)Tn′=0,
可推出
n′=(M−1)Tn.
平移对方向无效;纯旋转时逆转置又等于旋转本身,所以错误往往要等到非均匀缩放才暴露。
4. 正交投影
正交投影把长方体视景体
[l,r]×[b,t]×[n,f]
平移到原点并缩放到标准立方体。它保留平行关系,远近不改变物体大小,适合工程图、界面和某些阴影计算。
视口宽高比若与投影视景体不一致,最终图像会被拉伸。投影矩阵负责“看多大范围”,视口负责“画到屏幕哪一块”,两者不要混在一起。
5. 透视投影
透视投影沿穿过相机中心的射线投到近裁剪面,因此会出现近大远小和平行线汇聚。课件的推导先把截锥体挤压成长方体,再复用正交投影。
关键不是背整张矩阵,而是理解齐次分量的作用:投影矩阵让裁剪坐标的 wc 与深度相关,之后做
(xndc,yndc,zndc)=(wcxc,wcyc,wczc).
这一步叫透视除法。越远的点通常除以越大的量,屏幕投影因此越小。在透视除法之前进行齐次裁剪,可以正确处理跨过相机或近裁剪面的图元。
6. 从 NDC 到屏幕
透视除法后,点位于标准化设备坐标。把 [−1,1]2 映到左下角 (tx,ty)、宽高为 W,H 的视口:
xs=tx+2xndc+1W,ys=ty+2yndc+1H.
还要留意屏幕坐标原点在左下还是左上;不同图形 API 和图像库可能不同。
7. 一条点的完整路径
列向量约定下:
pclip=PVMpobject.
然后依次做裁剪、透视除法、视口映射和光栅化。调试一个“看不见”的物体时,按顺序检查:
- 模型是否真的在世界中。
- 相机朝向是否正确,up 是否与视线平行。
- near、far、FOV 和宽高比是否合理。
- 裁剪坐标是否落在视锥内,w 的符号是否正常。
- 深度测试、背面剔除和视口是否把结果丢掉。
逐坐标系检查,比盲目改矩阵符号有效得多。