图形学是什么

计算机图形学 Computer Graphics 研究如何用计算机生成、表示和处理视觉内容。它的输入通常是一个场景描述:几何形状、材质、光源、相机以及随时间变化的运动;输出可以是一张图像,也可以是一段动画。把场景中的几何、光照和材质综合成相机能够看到的图像,这个过程通常称为渲染 Rendering。

屏幕上的图像是二维的,但它往往来自三维场景。三维模型决定物体在哪里、长什么样,材质决定它如何与光作用,光源决定能量从哪里来,相机决定从哪个位置观察。图形学的任务是把这些因素放进同一套可计算的模型中,再在有限时间内得到稳定的图像。

透视与正交观察体积以及三角形在像素网格上的离散覆盖

图中左侧的两个观察体积分别对应透视投影和正交投影。透视投影的视线从相机一点发散,远处截面更大,物体会近大远小;正交投影的投影线彼此平行,物体大小不随深度变化。右侧把连续的三角形轮廓叠到像素网格上,说明投影先确定连续位置,光栅化再判断哪些离散像素被覆盖。斜边呈阶梯状,是连续几何被离散采样后的结果。

四条主线

课程把图形学按问题组织成四条主线。

  • 光栅化 Rasterization:把连续的几何图元投影到屏幕,再离散成像素或采样点。它是实时渲染最常用的基础方法。
  • 几何 Geometry:研究曲线、曲面、网格和复杂形体的表示、编辑、细分与简化。
  • 光传输 Light Transport:计算光的发射、反射、折射和散射,求出最终到达相机的光。光线追踪和路径追踪属于这条主线。
  • 动画与模拟 Animation and Simulation:描述物体随时间的位置、姿态和形变,并根据力学或其他物理规律模拟布料、刚体、流体和粒子。

光栅化通常速度快,适合游戏和交互式应用;光线追踪能够更自然地处理阴影、反射和间接光,但计算成本通常更高。实时图形学通常以每秒约 30 帧作为直观门槛,离线渲染则可以用更长时间换取更高质量。实时光线追踪试图缩小两者之间的差距,这正是图形学中常见的速度与质量取舍。

学科边界

可以把几个方向画成不同的映射关系:

  • 图形学通常从模型、材质和光源出发生成图像,即 model → image;
  • 计算机视觉通常从图像推断物体、几何和语义,即 image → model;
  • 图像处理主要在已有二维图像之间做增强、变换和重建,即 image → image;
  • 几何建模和物理模拟可以在没有图像输入的情况下,从模型生成另一个模型,即 model → model。

真实研究中的边界并不绝对。计算摄影会改变成像方式,深度学习也可能同时出现在视觉、图像处理和图形学中;增强现实系统往往先用视觉识别现实,再把图形学内容叠加回画面。这里的区分用于理解问题的输入和输出,不是给研究领域划一条不可跨越的线。

OpenGL、DirectX、Vulkan 和 Metal 是应用程序与图形硬件之间的 API,建模软件和游戏引擎是内容创作或运行工具。它们建立在图形学理论上,但 API 的调用方式不等于图形学本身。理解投影、光栅化、光照和可见性的原理之后,再学习某一种 API 会容易得多。

向量

点 Point 表示空间中的绝对位置,向量 Vector 表示位移、方向和长度。数学中常称向量,物理中也常称矢量。给定点 AA 和 BB,从 AA 指向 BB 的位移向量是

AB→=B−A.\overrightarrow{AB}=B-A.

向量整体平移后,只要方向和长度不变,仍表示同一个向量。它没有必须固定的绝对起点。向量通常写作带箭头的字母 a⃗\vec a,印刷体中也常写成粗体 a\mathbf a。

点和向量的运算需要遵守类型关系。两个点相减得到从一个点指向另一个点的向量;点加向量得到新的点;两个向量可以相加,但两个点相加没有自然的几何意义。这个区分在齐次坐标中还会进一步编码成末位的 1 和 0。

三维列向量可以写成

v=(xyz).\mathbf v=\begin{pmatrix}x\\y\\z\end{pmatrix}.

图形学默认把向量写成列向量。转置 TT 把行和列互换,例如 (x,y,z)T(x,y,z)^T 是横排坐标写法;行向量也可以使用,但后续矩阵乘法必须始终遵守同一约定。

向量运算

向量加法有两种等价的几何解释。平行四边形法则把两个向量的起点放在同一点,以它们为邻边作平行四边形,对角线就是和向量;三角形法则把第二个向量的起点接到第一个向量的终点,首尾相接可以自然推广到任意多个向量。代数上,向量加法就是对应分量相加。

标量乘法按分量缩放向量。标量为正时方向不变,为负时方向反向,绝对值决定长度缩放;标量为零得到零向量。减法可以写成加上相反向量。

三维向量的欧氏模长是

∥v∥=x2+y2+z2.\lVert\mathbf v\rVert=\sqrt{x^2+y^2+z^2}.

在二维中,水平 4 格、竖直 3 格的向量长度是 42+32=5\sqrt{4^2+3^2}=5。模长为 1 的向量称为单位向量。任意非零向量都可以归一化:

v^=v∥v∥.\hat{\mathbf v}=\frac{\mathbf v}{\lVert\mathbf v\rVert}.

零向量没有方向,不能归一化。法线是垂直于表面切平面的方向,切向量沿表面延伸;在光照、相机和光源计算中,这些方向通常先归一化。

在笛卡尔坐标系中,若基向量 ex,ey\mathbf e_x,\mathbf e_y 是互相垂直的单位向量,则

v=xex+yey.\mathbf v=x\mathbf e_x+y\mathbf e_y.

模长写成各分量平方和的平方根,依赖于坐标基的正交性和单位长度。若基向量不是正交单位基,就不能直接套用这个公式。

坐标系本身也不是唯一的:局部坐标描述模型,世界坐标描述场景,相机坐标描述观察,规范化设备坐标和屏幕坐标描述投影后的结果。不同坐标系之间的换算会在几何变换一节中统一写成矩阵乘法。

点积

点积 Dot Product 把两个向量映射为一个标量:

a⋅b=∥a∥∥b∥cos⁡θ=axbx+ayby+azbz.\mathbf a\cdot\mathbf b =\lVert\mathbf a\rVert\lVert\mathbf b\rVert\cos\theta =a_xb_x+a_yb_y+a_zb_z.

其中 θ\theta 是两个向量的夹角。若两个向量都是单位向量,点积就是 cos⁡θ\cos\theta,因此可以用

cos⁡θ=a⋅b∥a∥∥b∥\cos\theta=\frac{\mathbf a\cdot\mathbf b} {\lVert\mathbf a\rVert\lVert\mathbf b\rVert}

求夹角。点积大于 0 表示夹角小于 90∘90^\circ,等于 0 表示垂直,小于 0 表示夹角大于 90∘90^\circ。对于单位向量,点积从 1 到 −1 连续表示方向的接近程度。判断正负时,分界不是向量 a\mathbf a 所在的直线,而是经过原点且垂直于 a\mathbf a 的直线(二维)或平面(三维)。

点积满足交换律、分配律和标量相容性:

a⋅b=b⋅a,\mathbf a\cdot\mathbf b=\mathbf b\cdot\mathbf a,

a⋅(b+c)=(a⋅b)+(a⋅c),\mathbf a\cdot(\mathbf b+\mathbf c) =(\mathbf a\cdot\mathbf b)+(\mathbf a\cdot\mathbf c),

(ka)⋅b=k(a⋅b).(k\mathbf a)\cdot\mathbf b=k(\mathbf a\cdot\mathbf b).

点积没有通常意义下的结合律,因为第一次点积已经得到标量;(a⋅b)c(\mathbf a\cdot\mathbf b)\mathbf c 与 a(b⋅c)\mathbf a(\mathbf b\cdot\mathbf c) 一般是不同方向的向量。

在光照中,法线、光线方向和观察方向通常都先归一化。这样 n⋅l\mathbf n\cdot\mathbf l 直接表示入射角余弦,n⋅h\mathbf n\cdot\mathbf h 可以表示观察方向是否接近高光方向。若忘记归一化,点积会同时混入向量长度,数值就不能只解释成方向接近程度。

投影

向量 a\mathbf a 在非零参考向量 b\mathbf b 上的投影向量为

proj⁡ba=a⋅bb⋅bb.\operatorname{proj}_{\mathbf b}\mathbf a =\frac{\mathbf a\cdot\mathbf b}{\mathbf b\cdot\mathbf b}\mathbf b.

若 b^\hat{\mathbf b} 是单位向量,公式简化为

proj⁡b^a=(a⋅b^)b^.\operatorname{proj}_{\hat{\mathbf b}}\mathbf a =(\mathbf a\cdot\hat{\mathbf b})\hat{\mathbf b}.

投影长度带符号:夹角为锐角时为正,钝角时为负。把 a\mathbf a 分解成平行和垂直两部分:

a=a∥+a⊥,a⊥=a−a∥.\mathbf a=\mathbf a_{\parallel}+\mathbf a_{\perp},\qquad \mathbf a_{\perp}=\mathbf a-\mathbf a_{\parallel}.

在漫反射中,光线方向和法线方向的点积就是入射余弦。光线位于表面背面时点积为负,实际单面模型通常使用 max⁡(0,n⋅l)\max(0,\mathbf n\cdot\mathbf l)。

点积把向量投影到给定方向,投影长度随夹角余弦变化

图中黑色向量 a\mathbf a 是参考方向,向量 b\mathbf b 被投影到 a\mathbf a 所在直线上;红色箭头表示 b\mathbf b 的平行分量,投影长度由直角三角形给出。图中的 b⊥\mathbf b_\perp 是“投影到参考方向”的标记,几何上对应平行分量,并不是与 a\mathbf a 垂直的残差。参考方向反过来时,有符号投影也会反向。保留符号对于坐标分解和光照背面判断都很重要。

叉积

叉积 Cross Product 输出一个同时垂直于两个输入向量的向量:

a×b=(aybz−azbyazbx−axbzaxby−aybx).\mathbf a\times\mathbf b= \begin{pmatrix} a_yb_z-a_zb_y\\ a_zb_x-a_xb_z\\ a_xb_y-a_yb_x \end{pmatrix}.

它的模长为

∥a×b∥=∥a∥∥b∥sin⁡θ,\lVert\mathbf a\times\mathbf b\rVert =\lVert\mathbf a\rVert\lVert\mathbf b\rVert\sin\theta,

等于以 a,b\mathbf a,\mathbf b 为邻边的平行四边形面积。方向由右手定则确定。交换顺序会变号,自身叉积是零向量:

a×b=−(b×a),a×a=0.\mathbf a\times\mathbf b=-(\mathbf b\times\mathbf a), \qquad \mathbf a\times\mathbf a=\mathbf0.

叉积满足分配律和标量相容性,但不满足结合律。叉积还可以写成对偶矩阵:

[a]×=(0−azayaz0−ax−ayax0),a×b=[a]×b.[\mathbf a]_\times= \begin{pmatrix} 0&-a_z&a_y\\ a_z&0&-a_x\\ -a_y&a_x&0 \end{pmatrix}, \qquad \mathbf a\times\mathbf b=[\mathbf a]_\times\mathbf b.

在二维平面中,把向量嵌入 z=0z=0 平面,叉积只剩 z 分量:

((B−A)×(P−A))z=(Bx−Ax)(Py−Ay)−(By−Ay)(Px−Ax).((B-A)\times(P-A))_z =(B_x-A_x)(P_y-A_y)-(B_y-A_y)(P_x-A_x).

这个有符号面积的正负判断点 PP 在有向边 ABAB 的左侧还是右侧。对于逆时针三角形 ABCABC,依次计算 AB/APAB/AP、BC/BPBC/BP、CA/CPCA/CP 的叉积;三个结果都非负时,点在闭三角形内部。顺时针三角形对应三个结果都非正。落在边界上时,工程实现必须统一约定,否则相邻三角形可能重复着色或留下裂缝,硬件常用左上规则处理。

二维叉积的 z 分量以正负区分测试点位于有向边的左右

图的左侧把两个向量放在 xyxy 平面中,叉积沿垂直平面的 z 方向;交换向量顺序会让 z 分量反向。右侧用三角形 ABCABC 和测试点 PP 展示三条有向边的内测:逆时针绕序下,若 PP 对三条边都落在同一侧,就位于三角形内部。

坐标框架

三维标准正交基由三个长度为 1、两两垂直的向量 u,v,w\mathbf u,\mathbf v,\mathbf w 构成:

∥u∥=∥v∥=∥w∥=1,\lVert\mathbf u\rVert=\lVert\mathbf v\rVert=\lVert\mathbf w\rVert=1,

u⋅v=v⋅w=w⋅u=0.\mathbf u\cdot\mathbf v=\mathbf v\cdot\mathbf w =\mathbf w\cdot\mathbf u=0.

若 u×v=w\mathbf u\times\mathbf v=\mathbf w,则这是右手坐标系。任意向量 p\mathbf p 都可以按投影分解:

p=(p⋅u)u+(p⋅v)v+(p⋅w)w.\mathbf p=(\mathbf p\cdot\mathbf u)\mathbf u +(\mathbf p\cdot\mathbf v)\mathbf v +(\mathbf p\cdot\mathbf w)\mathbf w.

图形管线会使用多套坐标系:物体自身的局部坐标、描述整个场景的世界坐标、相机坐标、规范化设备坐标和屏幕坐标。坐标系之间的变换必须明确轴向、手性、深度范围和矩阵乘法约定。OpenGL 传统相机/世界约定采用右手坐标;其他 API 或资产工具也可能采用左手坐标,不能把某一个 API 名称直接等同于左手系。

矩阵

矩阵 Matrix 是按行列排布的数表。若 AA 是 m×nm\times n、BB 是 n×pn\times p,则 ABAB 存在且为 m×pm\times p。结果第 i,ji,j 个元素是 AA 第 ii 行与 BB 第 jj 列的点积:

(AB)ij=∑k=1nAikBkj.(AB)_{ij}=\sum_{k=1}^{n}A_{ik}B_{kj}.

例如 3×23\times2 矩阵乘 2×42\times4 矩阵得到 3×43\times4 矩阵。课程例子中,第二行与第四列的点积为 5×4+2×3=265\times4+2\times3=26,第三行与第一列的点积为 0×3+4×2=80\times3+4\times2=8。

矩阵乘法一般不满足交换律:AB≠BAAB\ne BA;但满足结合律和分配律。结合律允许把一长串变换先合成为一个矩阵,非交换性则要求严格保留变换顺序。

矩阵与列向量相乘时,矩阵写在左侧。关于 y 轴反射的二维矩阵是

(x′y′)=(−1001)(xy),\begin{pmatrix}x'\\y'\end{pmatrix} = \begin{pmatrix}-1&0\\0&1\end{pmatrix} \begin{pmatrix}x\\y\end{pmatrix},

即 x′=−x,y′=yx'=-x,y'=y。单位矩阵 II 是乘法的中性元,逆矩阵满足

AA−1=A−1A=I,(AB)−1=B−1A−1.AA^{-1}=A^{-1}A=I, \qquad (AB)^{-1}=B^{-1}A^{-1}.

转置交换行列,且

(AB)T=BTAT.(AB)^T=B^TA^T.

若矩阵满足 R−1=RTR^{-1}=R^T,它称为正交矩阵。旋转矩阵属于正交矩阵,因此旋转的逆可以直接用转置得到。点积也能写成矩阵乘法:

a⋅b=aTb.\mathbf a\cdot\mathbf b=\mathbf a^T\mathbf b.

方阵的行列式描述有向面积或体积的缩放。绝对值表示缩放倍率,符号表示定向是否翻转;行列式为 0 时至少有一个方向坍缩,矩阵没有逆。行列式满足

det⁡(AB)=det⁡(A)det⁡(B),\det(AB)=\det(A)\det(B),

因此复合变换的总体积倍率等于各步倍率相乘。

矩阵和向量为坐标、变换和相机运动提供了统一表达。下一讲将从这些基本操作出发,建立二维和三维的几何变换。