速成 · 计算机图形学
计算机图形学不是“会调用 OpenGL 就行”,它真正研究的是:怎样把对三维世界的描述,稳定、高效地变成二维屏幕上的像素。
课件的 11 讲可以压成一条流水线:
如果只剩几个小时,先把下面六个问题想明白。
一、一个点怎样走到屏幕上
齐次坐标把平移也纳入矩阵乘法。列向量约定下,一个物体坐标点依次经过
- :把局部模型摆进世界。
- :把世界改写到以相机为原点的坐标系。
- :把可见空间映到裁剪空间。
随后做透视除法
再由视口变换把 映到屏幕像素。矩阵乘法不可交换,所以代码里矩阵写反会直接得到另一种几何效果。
正交投影没有“近大远小”;透视投影让远处物体因除以深度而缩小。法线不能一律乘模型矩阵:非均匀缩放下,应使用
二、连续三角形怎样变成离散像素
裁剪先去掉视锥外的部分。线段可用 Cohen–Sutherland 区域码快速接受、拒绝或求交;多边形可依次对四条裁剪边执行 Sutherland–Hodgman。
光栅化则问:哪些像素中心落在三角形内?对三个有向边函数同号即可判内。只扫描三角形包围盒,并增量更新边函数,比逐像素重新求直线方程更快。
三角形顶点属性用重心坐标插值:
颜色、深度、法线和纹理坐标都可沿用这套权重。但透视投影后,纹理坐标不能直接做屏幕空间线性插值,而要先插值 与 ,最后相除。
锯齿、摩尔纹和错误运动感都是采样不足的不同表现。空间反走样的核心不是“把边缘抹糊”,而是先低通、再采样。最直观的实现是每像素多次采样后取平均。
三、谁挡住谁
背面剔除可先删掉朝向远离相机的三角形,但不能解决物体间遮挡。Painter 算法按远到近画,遇到相交或循环遮挡会失效;BSP 能预先建立空间顺序,但动态场景不方便。
实时光栅化通常使用 Z-buffer:
- 深度缓冲初始化为最远值。
- 每个片元算出插值深度。
- 只有比当前记录更近的片元才能写颜色,并更新深度。
它把全局排序改成了每像素的局部比较,复杂度近似与产生的片元数成正比。
四、为什么同一个面会有明暗
课件采用局部 Blinn–Phong 模型:
是法线, 指向光源, 是光线与视线的半程向量。环境项防止背光面全黑;漫反射决定大体明暗;镜面项形成高光,指数 越大,高光越尖。
“模型”和“计算频率”要分开:
- Flat:每个三角形算一次,棱角明显。
- Gouraud:每顶点算光照,再插值颜色,可能漏掉小高光。
- Phong shading:插值法线,再逐片元算光照,最平滑。
五、纹理和阴影在补什么信息
纹理映射为表面建立 坐标,再从纹理图反查颜色。放大时可用双线性插值;缩小时一个像素覆盖很多纹素,单点采样会闪烁。Mipmap 预先存储逐级低通降采样图,按像素足迹选择层级;三线性插值再在相邻两级间过渡。各向异性过滤用于细长而倾斜的像素足迹。
Bump Mapping 不增加几何,只扰动法线,因此轮廓不会变;Displacement Mapping 真正移动表面,需要足够细的网格。
Shadow Mapping 做两遍渲染:
- 从光源看场景,记录最近深度。
- 从相机看场景,把片元投回光源坐标,比较它与 Shadow Map 中的深度。
深度误差会产生自阴影斑点,需要 bias;分辨率不足造成锯齿,可用 Percentage Closer Filtering 多点比较后求平均。
六、曲线、曲面与网格怎样表示形状
几何表示没有绝对最优。隐式曲面 容易做内外判断和布尔运算,却不易直接枚举表面点;显式参数曲面 容易采样和绘制,却未必容易判断内外。点云、三角网格、 Bezier 曲线和细分曲面都是显式表示。
三次 Bezier 曲线由四个控制点决定:
它插值首尾点、位于控制点凸包内,并具有仿射不变性。复杂形状通常拼接低次曲线;位置相接是 ,一阶导数也相接才是 。Bezier 曲面是两个参数方向上的张量积。
三角网格把几何位置和连接关系分开。半边结构把一条无向边拆成方向相反的两条半边,用 twin、next、face 等指针把邻域查询降到局部操作。Loop 细分提升三角网格分辨率;Quadric Error Metric 通过边折叠并累计到邻接平面的平方距离来做简化。
最后记住的做题顺序
- 先标清当前坐标系和矩阵作用方向。
- 再分清顶点阶段、光栅化阶段和片元阶段。
- 插值题先写重心坐标;有透视就检查是否需要除以 。
- 可见性题先区分背面剔除、深度测试与阴影,它们解决的是三个不同问题。
- 光照题先画出 ,再代公式。
- 网格题先区分几何数据和连接关系,再讨论局部编辑或细分。
这条主线走通后,11 讲课件就不再是互不相干的算法,而是同一张图形流水线上的不同工位。