相机约定
模型变换把物体从局部坐标放入世界坐标。观察同一场景时,相机的位置和朝向仍然可以任意变化,因此需要把世界坐标继续转换到 相机坐标 Camera Space。
设相机位置为 e,观察方向为 g,向上参考方向为 t。课程采用右手相机坐标:相机位于原点,朝 −z 方向观察,+y 向上。先构造相机的三个单位基:
w=−∥g∥g,u=∥t×w∥t×w,v=w×u.
u,v,w 分别指向相机的右、上、后方。第一步取 w=−g^,是因为相机看向自身的 −z;第二步用叉积得到右方向;第三步再做一次叉积,使三个方向严格正交。若给定的 t 没有与 g 完全垂直,这个过程也完成了一次 Gram–Schmidt 正交化。
当 t 与 g 平行时,t×w=0,相机的横向方向无法确定。实际实现应检测这种退化情况,并换用不平行的上方向。
视图矩阵
视图矩阵 View Matrix 是相机到世界变换的逆。相机局部坐标到世界坐标的旋转矩阵以相机基为列:
Rcam→world=uxuyuzvxvyvzwxwywz.
连同相机位置,完整的相机到世界变换为
Mcam=uxuyuz0vxvyvz0wxwywz0exeyez1.
渲染需要相反方向:把世界中的点写成相机坐标,所以视图矩阵是 Mcam−1。相机基为正交单位基,旋转矩阵满足 R−1=RT。先把世界平移 −e,再投影到三个相机基上:
Mview=uxvxwx0uyvywy0uzvzwz00001100001000010−ex−ey−ez1.
对世界坐标点 p,结果前三维也可直接写成
pview=u⋅(p−e)v⋅(p−e)w⋅(p−e).
这说明视图变换的本质是:以相机为新原点,分别测量点在相机右、上、后三个方向上的坐标。把相机移动到标准位置,与让整个世界做相反变换完全等价。

正交投影
正交投影 Orthographic Projection 的可见区域是长方体。为保持与课件一致,设相机看向 −z,近平面和远平面的坐标分别为 n、f,二者都为负数,并满足 n>f。这里的 n,f 是相机坐标中的有符号位置;实际接口常把近平面、远平面写成正距离 dn,df,在该约定下应转换为 n=−dn、f=−df,不要把两种记法直接混用。长方体为
[l,r]×[b,t]×[f,n].
目标是把它映射到规范立方体 [−1,1]3。这一过程只有平移和缩放。
长方体中心为
c=(2l+r,2b+t,2f+n).
先平移 −c,各轴区间就关于原点对称;三个边长分别为 r−l、t−b、n−f,再分别乘以 2/(r−l)、2/(t−b)、2/(n−f),半边长便变成 1。因此
Mortho=r−l20000t−b20000n−f200001100001000010−2r+l−2t+b−2n+f1.
展开后,
Mortho=r−l20000t−b20000n−f20−r−lr+l−t−bt+b−n−fn+f1.
代入边界可验证:x=l,r 分别映射到 −1,1,y=b,t 分别映射到 −1,1,z=f,n 分别映射到 −1,1。正交投影不含除以深度的操作,所以物体的屏幕大小不随远近变化。

透视目标
透视投影 Perspective Projection 的可见区域是截头锥。仍采用同一有符号约定:近平面位于 z=n<0,其矩形边界为 l,r,b,t;远平面位于 z=f<n。先把截头锥挤压为正交投影使用的长方体,再应用 Mortho。
取相机空间中的点 P=(x,y,z)。连接原点与 P 的射线和近平面相交于 P′=(x′,y′,n)。从 xz、yz 两个截面观察,两个三角形分别相似:
nx′=zx,ny′=zy.
因此
x′=znx,y′=zny.
由于 n,z 同为负数,比例 n/z 为正。∣z∣ 越大,比例越小,远处物体自然缩小。

这里出现了除以 z,普通三维线性变换无法直接完成。齐次坐标允许先用矩阵得到四维裁剪坐标,再统一除以第四分量。若令
(xc,yc,wc)=(nx,ny,z),
齐次除法后就有
(wcxc,wcyc)=(znx,zny).
因此,挤压矩阵的第一、二、四行已经确定:
n0000n0000A100B0.
深度求解
挤压不能丢掉深度,否则后续无法做遮挡判断。x′、y′ 只依赖射线方向,同一条相机射线上的点会投到同一个屏幕位置;深度仍要保持前后顺序。
由于目标深度只应依赖原来的 z,设第三行产生
zc=Az+B.
齐次除法后的深度是
z′=wczc=zAz+B.
课件选择让近、远两个平面的深度保持不变。于是
z=n⟹nAn+B=n,
z=f⟹fAf+B=f.
整理为二元一次方程:
An+B=n2,Af+B=f2.
两式相减,
A(n−f)=n2−f2=(n−f)(n+f),
因此
A=n+f.
再代回第一式:
B=n2−n(n+f)=−nf.
截头锥到长方体的挤压矩阵由此得到:
Mpersp→ortho=n0000n0000n+f100−nf0.
这个结果可以逐项检查:
- 在近平面 z=n 上,x′=x、y′=y、z′=n,整个近平面保持不变;
- 在远平面 z=f 上,x′=nx/f、y′=ny/f,恰好把较大的远平面压到 [l,r]×[b,t];
- 位于近平面和远平面之间的点保持深度顺序,但深度不再线性变化。
透视矩阵先把原来的 z 放进齐次分量 w,统一矩阵乘法之后再除以 w;远小近大的效果来自这次除法。
投影矩阵
完整透视投影先挤压,再做正交归一化:
Mpersp=MorthoMpersp→ortho.
相乘得到
Mpersp=r−l2n0000t−b2n00−r−lr+l−t−bt+bn−fn+f100−n−f2nf0.
对称视锥满足 l=−r、b=−t,第一、二行中的偏移项消失。取近平面左边界 (l,y,n) 验证:
xndc=nr−l2nl−r−lr+ln=−1.
同理,x=r 映射到 1,上下边界也分别映射到 −1,1。矩阵的不同写法经常只差符号、转置或规范深度范围;比较公式前必须先统一列向量与行向量、左右手系、相机朝向和 n,f 的定义。
整个齐次矩阵乘以任意非零常数不会改变除法后的三维点。上面的推导矩阵产生 wc=z<0;常见图形管线则要求可见点满足 wc>0,并用 −wc≤xc,yc,zc≤wc 表示齐次裁剪范围。此时应把整个投影矩阵乘以 −1:
Mpersp(+w)=−Mpersp=−r−l2n0000−t−b2n00r−lr+lt−bt+b−n−fn+f−100n−f2nf0.
这样 wc=−z>0,透视除法后的 NDC 完全不变。只修改最后一行会破坏比例关系,不能得到等价投影。
深度分布
挤压后的深度为
z′=(n+f)−znf.
再经过正交投影,规范深度为
zndc=n−fn+f−z2nf.
它含有 1/z,所以透视深度不是相机空间深度的线性缩放。求导可得
dzdzndc=(n−f)z22nf.
变化率与 1/z2 成正比:靠近相机时,同样的世界空间距离占用更多深度值;远处许多深度会挤在很小范围内。把近平面设得过近,会把大量精度浪费在相机附近,使远处近乎共面的表面更容易发生 z-fighting。提高远平面距离的影响通常没有把近平面推近那么剧烈。
不同 API 会把规范深度映射到 [−1,1] 或 [0,1],也可能使用 reversed-Z 改善浮点深度精度。这些选择改变矩阵系数,却不改变深度来自 1/z 的根本原因。
视场参数
对称视锥常用垂直视场角 fovY、宽高比 a=W/H 与近平面距离 ∣n∣ 定义。观察 yz 截面,半个视场形成直角三角形:
tan2fovY=∣n∣t.
因此
t=∣n∣tan2fovY,b=−t.
又因为近裁剪面宽高比与屏幕一致,
a=t−br−l=2t2r=tr,
所以
r=at,l=−r.
视场越大,近裁剪面在同一距离处越宽,物体在屏幕中越小。近平面不能取零,因为此时相似三角形比例和透视除法都失去意义。推导中的角度按弧度参与三角函数;若接口接收 degree,应先转换为
fovYrad=fovYdeg180π,
再传给 tan,不要把 degree 数值直接当作弧度。
裁剪除法
MVP 变换 Model–View–Projection Transformation 按从右到左的顺序作用于列向量:
pclip=MprojMviewMmodelplocal.
采用常见的 wc>0 齐次裁剪规则时,这里的 Mproj 应取前文整体乘 −1 后的 Mpersp(+w);若使用具体图形 API,则以该 API 的手性、NDC 深度范围和裁剪约定替换,投影矩阵与裁剪规则必须成套一致。
结果 pclip=(xc,yc,zc,wc)T 仍是 裁剪坐标 Clip Coordinates。图元应在这一阶段对视锥边界裁剪;若三角形跨过近平面,直接对三个顶点分别除法会得到越过无穷远的错误形状。
裁剪后执行 透视除法 Perspective Divide:
(xndc,yndc,zndc)=(wcxc,wcyc,wczc).
矩阵变换作用于齐次坐标,透视除法使最终映射成为非线性投影。MVP 常被口头称为一个变换矩阵,但完整流程还包含裁剪和除法,二者不能省略或随意交换顺序。
视口变换
规范设备坐标 Normalized Device Coordinates 的 x,y∈[−1,1] 还要通过 视口变换 Viewport Transformation 映射到宽 W、高 H 的屏幕连续区域:
xs=2W(xndc+1),ys=2H(yndc+1).
只写屏幕平面映射时,对应齐次矩阵为
Mviewport=W/20000H/2000010W/2H/201.
课程的约定把近、远平面分别映射到 zndc=1,−1。若深度缓冲希望近处为 0、远处为 1,可再令
d=21−zndc.
不同 API 也可能使用另一 NDC 范围或 reversed-Z,比较方向必须随约定一起改变。像素 (x,y) 的中心位于 (x+0.5,y+0.5)。只给屏幕 x,y 只能确定一条相机射线,无法唯一逆变换到 3D 点,因为还缺少深度和齐次信息;给定深度以及完整的投影、视图约定后,才能执行反投影 unprojection。视口阶段的 z 映射只服务深度比较和深度缓冲,不参与屏幕平面位置的恢复。哪些像素被三角形覆盖、每个样本的属性如何插值,属于后续光栅化阶段。