视频加载失败

课程

57104 字
约 164 分钟

计算机图形学期末复习提纲与考点详析 (2026_review_Sonder9999)

计算机图形学note·更新于 2026-09-15

计算机图形学期末复习提纲与考点详析 (2026_review_Sonder9999)


考试基本信息

一、 考试范围与重点章节

  • 第 1 章:绪论(基础概念与学科关联)
  • 第 2 章:图形系统(帧缓存计算与流水线阶段)
  • 第 3 章:二维基本图形光栅化与裁剪 (重点,包含中点法、Bresenham、多边形扫描转换、Liang-Barsky、多边形裁剪)
  • 第 4 章:图形几何变换 (重点,包含齐次坐标、复合变换、OpenGL 变换应用)
  • 第 5 章:三维观察 (重点,包含投影分类、透视投影、灭点、三视图)
  • 第 6 章:三维造型(实体造型、细分与 CSG 方法)
  • 第 7 章:真实感图形技术 (重点,包含 Z-Buffer 消隐、光照模型、三种着色算法、光线跟踪)

二、 题型分布与分值

  • 单选题 (30分)15×215 \times 2',包括程序代码选择 5 题
  • 判断题 (10分)10×110 \times 1'
  • 简答题 (30分)5×65 \times 6'
  • 综合计算题 (30分)3×103 \times 10',典型题型包括:
    • 画线算法:中点画线算法、Bresenham 画线算法的基本思想、判别式递推及画点位置计算。
    • 多边形填充:改进的活动边表(AET)算法,手动补充或构建 ET 表与 AET 表。
    • 裁剪算法:Liang-Barsky 算法裁剪直线段的参数计算与执行过程。

第 1 章 绪论

  • 计算机图形学的定义

    • 计算机图形学(Computer Graphics, 简称 CG)是研究如何利用计算机将数学模型几何数据转换为图形/图像并在显示设备上显示的学科。
  • 主要研究内容

    • 建模 (Modeling):如何在计算机中表示和存储三维物体的几何形状(如多边形网格、曲面、实体表示)。
    • 渲染 (Rendering):如何根据光照、材质、视角计算物体的颜色和阴影,生成具有真实感的图像。
    • 动画 (Animation):如何模拟物体随时间变化的位置、形状和外观。
    • 人机交互 (Interaction):用户与图形系统进行实时交互的软硬件技术。
  • 与相关学科之间的关联与区别

    学科名称输入内容输出内容典型任务与研究方向
    计算机图形学 (CG)几何模型/描述数据图像场景渲染、游戏开发、动画制作
    数字图像处理 (DIP)图像图像图像增强、去噪、滤波、图像分割
    计算机视觉 (CV)图像/视频物理场景的描述/三维模型目标检测、人脸识别、三维重建
    计算几何 (CGGeo)几何问题描述几何算法/数据结构碰撞检测、网格剖分、凸包计算
    模式识别 (PR)图像/特征数据类别标签/决策判断字符识别、分类器设计、数据分析
  • 学科流向示意图

    graph TD
        Model["几何模型 (数学描述)"] -->|计算机图形学 CG| Image["图像 (像素阵列)"]
        Image -->|计算机视觉 CV / 模式识别 PR| Model
        Image -->|图像处理 DIP| Image2["处理后的图像"]
  • 计算机图形学的核心目标

    • 逼真度 (Realism):生成与真实世界难以区分的图像。
    • 交互性 (Interactivity):系统对用户操作的实时响应能力(通常要求达到 30 fps30\text{ fps} 以上)。
    • 计算效率 (Efficiency):在有限的时间与硬件资源内完成图形的生成与渲染。
  • 计算机图形学的应用领域

    • 计算机辅助设计与制造 (CAD/CAM):飞机、汽车、建筑物的结构设计。
    • 科学计算可视化:将复杂的数据(医学 MRI、气象风向、物理仿真)以直观图形展现。
    • 虚拟现实 (VR) 与增强现实 (AR):构建沉浸式交互场景。
    • 数字娱乐与影视游戏:电影特效、3D 游戏引擎开发。
    • 用户图形界面 (GUI):现代操作系统及应用的人机交互媒介。
  • 计算机图形学的发展历程

    • 矢量/画笔式显示时代:通过电子束在示波器上绘制线段,刷新率受限,不支持面填充。
    • 光栅扫描显示时代:引入帧缓存概念,逐像素扫描,支持复杂色彩与实体填充。
    • GPU 与硬件加速时代:专用图形芯片的出现,使得大规模并行矩阵计算与实时光追成为现实。

第 2 章 图形系统

  • 计算机图形系统的组成分类

    • 图形硬件系统:包括输入设备、输出设备、图形处理器(GPU)、系统内存以及帧缓存(Frame Buffer)。
    • 图形软件系统:包括图形应用软件(如 AutoCAD、Blender)和图形支撑软件/API(如 OpenGL、DirectX、Vulkan)。
  • 常见的图形输入、输出设备

    • 输入设备:键盘、二维鼠标、图形输入板/数位板(Tablet)、三维扫描仪、数据手套。
    • 输出设备:液晶显示器(LCD)、有机发光二极管显示器(OLED)、投影仪、阴极射线管显示器(CRT,历史)、绘图仪。
  • 光栅扫描显示系统的组成

    • 核心组件包括:系统 CPU系统内存图形处理器 (GPU)帧缓存 (Frame Buffer)视频控制器 (Video Controller) 以及 显示监视器
    • 视频控制器以固定的刷新频率(如 60Hz60\text{Hz})循环读取帧缓存中的像素值,通过数模转换(DAC)送往显示器显示。
  • 帧缓存的概念和大小的计算

    • 帧缓存 (Frame Buffer):用于存储屏幕上所有像素颜色或灰度值的专用内存区域。

    • 计算公式

      VM×N×log2KV \ge M \times N \times \lceil \log_2 K \rceil

      其中,M×NM \times N 为屏幕分辨率(列数 ×\times 行数),KK 为显示颜色的种类数(或灰度级数),log2K\lceil \log_2 K \rceil 为每个像素占用的位数(Bit Depth,位深)。

    • 注意单位换算

      • 1 Byte=8 bits1\text{ Byte} = 8\text{ bits}
      • 1 KB=1024 Bytes1\text{ KB} = 1024\text{ Bytes}
      • 1 MB=1024 KB=1024×1024 Bytes1\text{ MB} = 1024\text{ KB} = 1024 \times 1024\text{ Bytes}
    Important

    典型例题:若显示器的分辨率为 1024×7681024 \times 768,能显示 256256 级灰度。求所需的最小帧缓存容量。

    • 解答步骤
      1. 灰度级 K=256K = 256,则位深为 log2256=8 bits\log_2 256 = 8\text{ bits}(即 1 Byte1\text{ Byte})。

      2. 帧缓存总容量:

        V=1024×768×8 bits=786,432 BytesV = 1024 \times 768 \times 8\text{ bits} = 786,432\text{ Bytes}
      3. 换算为 KB/MB:

        V=786,4321024=768 KB=0.75 MBV = \frac{786,432}{1024} = 768\text{ KB} = 0.75\text{ MB}
  • 常见的图形应用软件和图形支撑软件

    • 支撑软件 (Graphics Library API):OpenGL、WebGL、Direct3D、Vulkan、Metal。
    • 应用软件:AutoCAD(工程设计)、Blender/3ds Max/Maya(3D建模与动画)、Photoshop(图像编辑)。
  • 图形流水线 (Graphics Pipeline) 的三个阶段及其作用

    graph LR
        AppStage["应用程序阶段<br>(Application)"] --> GeoStage["几何阶段<br>(Geometry)"]
        GeoStage --> RasterStage["光栅化与像素处理阶段<br>(Rasterization / Pixel Processing)"]
    • 应用程序阶段 (Application Stage)
      • 运行设备:CPU。
      • 主要作用:场景物理模拟、碰撞检测、视锥体粗选剔除、用户输入响应、加速判定算法执行,向几何阶段发送需要绘制的几何图元。
    • 几何阶段 (Geometry Stage)
      • 运行设备:GPU 顶点着色器(Vertex Shader)等。
      • 主要作用:进行顶点坐标变换(包括模型变换、观察变换、投影变换)、顶点光照计算与明暗处理、裁剪剔除视锥体外的非可见物体、最终的屏幕视口映射。
    • 光栅化与像素处理阶段 (Rasterization / Pixel Processing Stage)
      • 运行设备:GPU 片段着色器(Fragment/Pixel Shader)等。
      • 主要作用:将连续的三角形网格图元离散化为离散的片元/像素,在片元之间进行属性的线性插值(如纹理坐标、法向),执行纹理采样、光照模型逐像素计算,进行深度测试(Z-Buffer 消隐)、模板测试和 Alpha 混合,最终将颜色结果写入帧缓存供显示。

第 3 章 二维基本图形光栅化与裁剪

一、 直线段与圆弧光栅化算法

1. DDA (数值微分) 画线法

  • 基本思想:利用微分方程 yi+1=yi+kΔxy_{i+1} = y_i + k \cdot \Delta x,通过逐步累加斜率 kk 来计算下一个像素的坐标,并对结果取整。

  • 步长计算与更新规则

    • 当斜率 k1|k| \le 1 时,以 xx 为主步进方向,Δx=1\Delta x = 1

      {xi+1=xi+1yi+1=yi+k\begin{cases} x_{i+1} = x_i + 1 \\ y_{i+1} = y_i + k \end{cases}
    • 当斜率 k>1|k| > 1 时,以 yy 为主步进方向,Δy=1\Delta y = 1

      {yi+1=yi+1xi+1=xi+1k\begin{cases} y_{i+1} = y_i + 1 \\ x_{i+1} = x_i + \frac{1}{k} \end{cases}
  • 缺点:每次迭代都包含浮点数加法与四舍五入取整操作,硬件实现效率低。


2. Bresenham 画线算法

  • 基本思想:将线段离散化问题转化为寻找距离理想直线最近的网格点。通过逐步递推误差判定值,最终消除浮点数与乘除法运算,仅用整数加减和移位即可完成渲染。
  • 推导过程的三个演进阶段(以第一象限内、斜率 0k10 \le k \le 1 的直线为例,设起点为 (x0,y0)(x_0, y_0),终点为 (x1,y1)(x_1, y_1)Δx=x1x0\Delta x = x_1 - x_0Δy=y1y0\Delta y = y_1 - y_0,斜率 k=ΔyΔxk = \frac{\Delta y}{\Delta x}):

(1) Bresenham 原始算法(包含小数与 0.5 比较)

  • 核心逻辑: 设当前步已画点为 Pi(xi,yi)P_i(x_i, y_i),下一步 xi+1=xi+1x_{i+1} = x_i + 1 时,理想直线上的精确纵坐标为 y=k(xi+1x0)+y0y = k(x_i + 1 - x_0) + y_0。 我们需要在此处决策将像素点绘制在 yiy_i 还是 yi+1y_i + 1
    • 计算理想点与上下两个候选像素的垂直距离 d1d_1d2d_2

      d1=yyi=k(xi+1x0)+y0yid_1 = y - y_i = k(x_i + 1 - x_0) + y_0 - y_i d2=(yi+1)y=yi+1[k(xi+1x0)+y0]d_2 = (y_i + 1) - y = y_i + 1 - \left[ k(x_i + 1 - x_0) + y_0 \right]
    • 构造两者之差:

      d1d2=2y2yi1=2(yyi)1d_1 - d_2 = 2y - 2y_i - 1 = 2(y - y_i) - 1
    • 决策判定

      • d1d2<0    yyi<0.5d_1 - d_2 < 0 \implies y - y_i < 0.5,即理想点更靠近下方的 yiy_i,选择 yi+1=yiy_{i+1} = y_i
      • d1d20    yyi0.5d_1 - d_2 \ge 0 \implies y - y_i \ge 0.5,即理想点更靠近上方的 yi+1y_i+1,选择 yi+1=yi+1y_{i+1} = y_i + 1
  • 局限性:在每一步计算中,需要对每一个像素点计算理想的浮点坐标 yy,并与 0.50.5 比较,这包含了浮点数加法与乘法,性能开销较大。

(2) 改进算法 1:消除与 0.5 的比较(引入误差 e)

  • 核心逻辑: 与其每次计算绝对的 yy,不如使用递推的误差项 ee。 设误差 ee 表示理想直线 yy 坐标与当前选定像素 yiy_i 之间的相对偏差。从起点出发时,e0=0e_0 = 0。 每次 xx 步进 11,误差累加斜率 kk(即 etemp=ei+ke_{\text{temp}} = e_i + k):

    • ei+k<0.5e_i + k < 0.5,选择 yi+1=yiy_{i+1} = y_i,下一轮累积误差更新为:

      ei+1=ei+ke_{i+1} = e_i + k
    • ei+k0.5e_i + k \ge 0.5,说明相对偏差超过了一半像素,选择 yi+1=yi+1y_{i+1} = y_i + 1。由于像素坐标向上移动了 11,在此处需要做误差修正,使得误差项继续相对于新的像素线保持正确关系:

      ei+1=ei+k1e_{i+1} = e_i + k - 1
  • 消除 0.5: 为避免与常数 0.50.5 比较,令 ei=ei0.5e'_i = e_i - 0.5,将比较基准转换到 00

    • 初始值:

      e0=0.5e'_0 = -0.5
    • 每次更新 etemp=ei+ke'_{\text{temp}} = e'_i + k 并与 00 进行大小判断:

      • ei+k<0e'_i + k < 0,选 yi+1=yiy_{i+1} = y_i,更新 ei+1=ei+ke'_{i+1} = e'_i + k
      • ei+k0e'_i + k \ge 0,选 yi+1=yi+1y_{i+1} = y_i + 1,更新 ei+1=ei+k1e'_{i+1} = e'_i + k - 1
  • 局限性:虽然通过转换使得判断条件变成了与 00 比较,但由于斜率 k=ΔyΔxk = \frac{\Delta y}{\Delta x} 仍然是浮点数,且初始值 e0=0.5e'_0 = -0.5 也是浮点数,系统仍然需要依赖浮点运算。

(3) 改进算法 2:彻底摆脱浮点数(引入整型判别式 E)

  • 核心逻辑: 为了完全消除除法和浮点数,将改进算法 1 中的不等式和更新公式两边同乘以常数 2Δx2\Delta x(因为 Δx>0\Delta x > 0,这不会改变判定不等式的符号方向)。 定义全新的整型误差决策变量 Ei=2ΔxeiE_i = 2\Delta x \cdot e'_i

    • 初始值

      E0=2Δxe0=2Δx(0.5)=ΔxE_0 = 2\Delta x \cdot e'_0 = 2\Delta x \cdot (-0.5) = -\Delta x
    • 每次步进的增量变化

      • 原本递增的斜率项 kk 变为:

        2Δxk=2ΔxΔyΔx=2Δy2\Delta x \cdot k = 2\Delta x \cdot \frac{\Delta y}{\Delta x} = 2\Delta y
      • 原本溢出时的减 11 修正项变为:

        2Δx-2\Delta x
    • 最终纯整型递推公式 (Bresenham 标准形式): 令误差递增中间值 Etemp=Ei+2ΔyE_{\text{temp}} = E_i + 2\Delta y

      • Ei+2Δy<0E_i + 2\Delta y < 0,下一个像素为 (xi+1,yi)(x_i + 1, y_i),更新:

        Ei+1=Ei+2ΔyE_{i+1} = E_i + 2\Delta y
      • Ei+2Δy0E_i + 2\Delta y \ge 0,下一个像素为 (xi+1,yi+1)(x_i + 1, y_i + 1),更新:

        Ei+1=Ei+2Δy2ΔxE_{i+1} = E_i + 2\Delta y - 2\Delta x
  • 优势:在这个最终算法中,初始值和增量全部被转换为整数(Δx\Delta xΔy\Delta y 均为整数像素差值)。算法在主循环中仅执行整数加减法与乘 2 运算(乘 2 在硬件层面通过左移 1 位 << 1 极速完成),彻底排除了浮点数,执行效率极高。

(4) Bresenham 算法三大演进阶段核心要素独立总结

为了方便对比与快速查阅,以下将三个演进阶段的核心公式、基本思想、判定决策规则以及参数含义进行完全独立的汇总。每个阶段的计算体系均彼此独立,所有变量与公式均已展开,无需向前追溯或参考其他版本。

① Bresenham 原始算法(包含小数与 0.5 比较)
  • 基本思想:在每一步 xx 步进 11 时,跟踪理想直线与当前像素中心的高度偏差 dd。如果下一个临时偏差 d+kd + k 小于 0.50.5,说明理想点更靠近下方像素 yiy_i,纵坐标保持不变;若大于等于 0.50.5,说明理想点更靠近上方像素 yi+1y_i + 1,纵坐标加 1,并对偏差做减 1 修正。
  • 决策判别式与递推公式
    • 初始误差值d0=0d_0 = 0
    • 递推决策规则(若当前处于步骤 ii,已知像素点 (xi,yi)(x_i, y_i) 与偏差 did_i,在 xi+1=xi+1x_{i+1} = x_i + 1 时):
      • di+k<0.5d_i + k < 0.5yi+1=yiy_{i+1} = y_i di+1=di+kd_{i+1} = d_i + k
      • di+k0.5d_i + k \ge 0.5yi+1=yi+1y_{i+1} = y_i + 1 di+1=di+k1d_{i+1} = d_i + k - 1
  • 下一像素点位置
    • di+k<0.5d_i + k < 0.5:绘制像素点 (xi+1,yi)(x_i + 1, y_i)
    • di+k0.5d_i + k \ge 0.5:绘制像素点 (xi+1,yi+1)(x_i + 1, y_i + 1)
  • 各参数含义
    • xi,yix_i, y_i:当前步已画的像素点坐标。
    • did_i:第 ii 步时理想直线纵坐标与当前绘制像素 yiy_i 的相对偏差值(浮点数)。
    • k=ΔyΔxk = \frac{\Delta y}{\Delta x}:直线的斜率(浮点数,在 0k10 \le k \le 1 范围内)。
② 改进算法 1:消除与 0.5 的比较(引入相对误差 ee'
  • 基本思想:为了省去每步与 0.50.5 比较的浮点开销,将误差变量整体平移 0.50.5,定义 e=d0.5e' = d - 0.5。这样误差判定基准由“与 0.50.5 比较”转为“与 00 比较”,仅需判断代数式符号(正负)即可做出位置决策。
  • 决策判别式与递推公式
    • 初始误差值e0=0.5e'_0 = -0.5
    • 递推决策规则(在 xi+1=xi+1x_{i+1} = x_i + 1 时):
      • ei+k<0e'_i + k < 0yi+1=yiy_{i+1} = y_i ei+1=ei+ke'_{i+1} = e'_i + k
      • ei+k0e'_i + k \ge 0yi+1=yi+1y_{i+1} = y_i + 1 ei+1=ei+k1e'_{i+1} = e'_i + k - 1
  • 下一像素点位置
    • ei+k<0e'_i + k < 0:绘制像素点 (xi+1,yi)(x_i + 1, y_i)
    • ei+k0e'_i + k \ge 0:绘制像素点 (xi+1,yi+1)(x_i + 1, y_i + 1)
  • 各参数含义
    • xi,yix_i, y_i:当前步已画的像素点坐标。
    • eie'_i:第 ii 步平移后的相对偏差误差项(浮点数,初始值为 0.5-0.5)。
    • k=ΔyΔxk = \frac{\Delta y}{\Delta x}:直线的斜率(浮点数)。
③ 改进算法 2:彻底摆脱浮点数(引入整型判别式 EE
  • 基本思想:为了完全消除浮点数(包括斜率 kk 和初值 0.5-0.5),将改进算法 1 中的判别式两边同时乘以常数 2Δx2\Delta x。定义整型决策误差变量 Ei=2ΔxeiE_i = 2\Delta x \cdot e'_i。转换后,所有变量和步进增量均变为整数,算法主循环内仅需整数加减和移位运算,无任何浮点计算。
  • 决策判别式与递推公式
    • 初始误差值E0=ΔxE_0 = -\Delta x
    • 递推决策规则(在 xi+1=xi+1x_{i+1} = x_i + 1 时):
      • Ei+2Δy<0E_i + 2\Delta y < 0yi+1=yiy_{i+1} = y_i Ei+1=Ei+2ΔyE_{i+1} = E_i + 2\Delta y
      • Ei+2Δy0E_i + 2\Delta y \ge 0yi+1=yi+1y_{i+1} = y_i + 1 Ei+1=Ei+2Δy2ΔxE_{i+1} = E_i + 2\Delta y - 2\Delta x
  • 下一像素点位置
    • Ei+2Δy<0E_i + 2\Delta y < 0:绘制像素点 (xi+1,yi)(x_i + 1, y_i)
    • Ei+2Δy0E_i + 2\Delta y \ge 0:绘制像素点 (xi+1,yi+1)(x_i + 1, y_i + 1)
  • 各参数含义
    • xi,yix_i, y_i:当前步已画的像素点坐标。
    • EiE_i:第 ii 步的整型误差决策判定变量(整数,初始值为 Δx-\Delta x)。
    • Δx=x1x0\Delta x = x_1 - x_0:线段终点与起点之间的水平跨度(正整数,且 Δx>0\Delta x > 0)。
    • Δy=y1y0\Delta y = y_1 - y_0:线段终点与起点之间的垂直跨度(正整数)。
    • 2Δy2\Delta y:在 xx 步进 1 时,整型误差变量的默认增加量(整数)。
    • 2Δy2Δx2\Delta y - 2\Delta x:像素点向上移动时,整型误差变量的修正增加量(整数)。

Tip

经典实例演练:绘制从 P0(0,0)P_0(0,0)P1(5,2)P_1(5,2) 的直线段

已知起点为 (0,0)(0,0),终点为 (5,2)(5,2),则:

  • Δx=5\Delta x = 5Δy=2\Delta y = 2
  • 斜率 k=25=0.4k = \frac{2}{5} = 0.4
  • 终点像素为 (5,2)(5,2),需要在每一方向步进中决定下一个像素坐标。

以下使用上述三种演进阶段的算法依次进行完整的计算递推过程展示:

1. Bresenham 原始算法(包含小数与 0.5 比较)

Bresenham 原始算法演示: P₀(0,0) 到 P₁(5,2) [d 与 0.5 比较] y = 0.5 临界线 y = 1.5 临界线 (0,0) (1,0) (2,1) (3,1) (4,2) (5,2) X Y 0 1 2 3 4 5 6 1 2 3 理想直线段 0.5 误差阈值边界线 Bresenham选中的离散像素
  • 初始化:当前点 (x0,y0)=(0,0)(x_0, y_0) = (0, 0),误差偏移量初始值 d=0d = 0
  • 状态更新规则
    • 每次步进计算临时值 dtemp=di+kd_{\text{temp}} = d_i + k
    • dtemp0.5    yd_{\text{temp}} \ge 0.5 \implies y 递增 11,且做修正 di+1=dtemp1d_{i+1} = d_{\text{temp}} - 1
    • dtemp<0.5    yd_{\text{temp}} < 0.5 \implies y 保持不变,且 di+1=dtempd_{i+1} = d_{\text{temp}}
步数 (xx)当前绘制点误差项更新 (d=d+0.4d = d + 0.4)判断d0.5d \ge 0.5下一步纵坐标yy
00(0,0)(0, 0)d=0+0.4=0.4d = 0 + 0.4 = 0.4否 (0.4<0.50.4 < 0.5)y=0y = 0
11(1,0)(1, 0)d=0.4+0.4=0.8d = 0.4 + 0.4 = 0.8是 (0.80.50.8 \ge 0.5),更新 d=0.81=0.2d = 0.8 - 1 = -0.2y=1y = 1
22(2,1)(2, 1)d=0.2+0.4=0.2d = -0.2 + 0.4 = 0.2否 (0.2<0.50.2 < 0.5)y=1y = 1
33(3,1)(3, 1)d=0.2+0.4=0.6d = 0.2 + 0.4 = 0.6是 (0.60.50.6 \ge 0.5),更新 d=0.61=0.4d = 0.6 - 1 = -0.4y=2y = 2
44(4,2)(4, 2)d=0.4+0.4=0d = -0.4 + 0.4 = 0否 (0<0.50 < 0.5)y=2y = 2
55(5,2)(5, 2)(已到达终点)--

2. 改进算法 1:消除与 0.5 的比较(引入误差变量代换 ee

Bresenham 改进算法1演示: 消除0.5比较 [误差变量代换 e] e = 0 决策临界线 e = 0 决策临界线 X Y 0 1 2 3 4 5 1 2 理想直线 e = 0 零点分界线 选中的像素点(基于 e 符号判断)
  • 初始化:通过 e=d0.5e = d - 0.5,误差偏置量初始值 e0=0.5e_0 = -0.5
  • 状态更新规则
    • 每次步进计算临时值 etemp=ei+ke_{\text{temp}} = e_i + k
    • etemp0    ye_{\text{temp}} \ge 0 \implies y 递增 11,且做修正 ei+1=etemp1e_{i+1} = e_{\text{temp}} - 1
    • etemp<0    ye_{\text{temp}} < 0 \implies y 保持不变,且 ei+1=etempe_{i+1} = e_{\text{temp}}
步数 (xx)当前绘制点误差项更新 (e=e+0.4e = e + 0.4)判断e0e \ge 0下一步纵坐标yy
00(0,0)(0, 0)e=0.5+0.4=0.1e = -0.5 + 0.4 = -0.1否 (0.1<0-0.1 < 0)y=0y = 0
11(1,0)(1, 0)e=0.1+0.4=0.3e = -0.1 + 0.4 = 0.3是 (0.300.3 \ge 0),更新 e=0.31=0.7e = 0.3 - 1 = -0.7y=1y = 1
22(2,1)(2, 1)e=0.7+0.4=0.3e = -0.7 + 0.4 = -0.3否 (0.3<0-0.3 < 0)y=1y = 1
33(3,1)(3, 1)e=0.3+0.4=0.1e = -0.3 + 0.4 = 0.1是 (0.100.1 \ge 0),更新 e=0.11=0.9e = 0.1 - 1 = -0.9y=2y = 2
44(4,2)(4, 2)e=0.9+0.4=0.5e = -0.9 + 0.4 = -0.5否 (0.5<0-0.5 < 0)y=2y = 2
55(5,2)(5, 2)(已到达终点)--

3. 改进算法 2:彻底摆脱浮点数(引入整型判别式 EE

Bresenham 改进算法2演示: 纯整数标量运算 [整型判别式 E] E = 0 整数分界轴 E = 0 整数分界轴 (0,0) E0=-5 (1,0) E1=-1 (2,1) E2=3 (3,1) E3=-3 (4,2) E4=1 (5,2) E5=-5 X Y 0 1 2 3 4 5 1 2 理想直线 E = 0 整数分界轴 纯整型硬件渲染点
  • 初始化:通过 E=e2ΔxE = e \cdot 2\Delta x 进行整体放大,已知 2Δx=102\Delta x = 102Δy=42\Delta y = 4
  • 状态更新规则
    • 每次步进累加 2Δy2\Delta y 即计算临时值 Etemp=Ei+4E_{\text{temp}} = E_i + 4
    • Etemp0    yE_{\text{temp}} \ge 0 \implies y 递增 11,且做整型修正 Ei+1=Etemp2ΔxE_{i+1} = E_{\text{temp}} - 2\Delta x(即减去 1010)。
    • Etemp<0    yE_{\text{temp}} < 0 \implies y 保持不变,且 Ei+1=EtempE_{i+1} = E_{\text{temp}}
步数 (xx)当前绘制点误差项更新 (E=E+4E = E + 4)判断E0E \ge 0下一步纵坐标yy
00(0,0)(0, 0)E=5+4=1E = -5 + 4 = -1否 (1<0-1 < 0)y=0y = 0
11(1,0)(1, 0)E=1+4=3E = -1 + 4 = 3是 (303 \ge 0),更新 E=310=7E = 3 - 10 = -7y=1y = 1
22(2,1)(2, 1)E=7+4=3E = -7 + 4 = -3否 (3<0-3 < 0)y=1y = 1
33(3,1)(3, 1)E=3+4=1E = -3 + 4 = 1是 (101 \ge 0),更新 E=110=9E = 1 - 10 = -9y=2y = 2
44(4,2)(4, 2)E=9+4=5E = -9 + 4 = -5否 (5<0-5 < 0)y=2y = 2
55(5,2)(5, 2)(已到达终点)--

归纳总结: 无论采用何种形式,其内部判定基准的数学逻辑完全等价,最终渲染产生的离散像素点序列也完全相同:

(0,0)(1,0)(2,1)(3,1)(4,2)(5,2)(0,0) \to (1,0) \to (2,1) \to (3,1) \to (4,2) \to (5,2)

3. 中点画线法

  • 基本思想:构造直线的隐式方程 F(x,y)=Ax+By+C=0F(x, y) = Ax + By + C = 0(其中 A=ΔyA = - \Delta y, B=ΔxB = \Delta x, C=ΔxbC = \Delta x \cdot b)。

  • 每次步进 xi+1=xi+1x_{i+1} = x_i + 1,计算中点 M(xi+1,yi+0.5)M(x_i + 1, y_i + 0.5) 代入方程的值:

    di=F(xi+1,yi+0.5)=A(xi+1)+B(yi+0.5)+Cd_i = F(x_i + 1, y_i + 0.5) = A(x_i + 1) + B(y_i + 0.5) + C
    • di<0d_i < 0,中点在直线下方,说明直线上方距离像素点更近,选右上方的像素点 (xi+1,yi+1)(x_i + 1, y_i + 1)
    • di0d_i \ge 0,中点在直线上方,选右下方的像素点 (xi+1,yi)(x_i + 1, y_i)
  • 递推公式 (整数优化形式)

    • 初始值:d0=2A+Bd_0 = 2A + B(即 Δx2Δy\Delta x - 2\Delta y)。
    • di<0d_i < 0,选右上点 (xi+1,yi+1)(x_i+1, y_i+1),则下一轮判别式 di+1=di+2A+2Bd_{i+1} = d_i + 2A + 2B(即 di+2Δx2Δyd_i + 2\Delta x - 2\Delta y)。
    • di0d_i \ge 0,选右下点 (xi+1,yi)(x_i+1, y_i),则下一轮判别式 di+1=di+2Ad_{i+1} = d_i + 2A(即 di2Δyd_i - 2\Delta y)。
Tip

经典实例演练:使用中点画线法绘制从 P0(0,0)P_0(0,0)P1(5,2)P_1(5,2) 的直线段

已知起点为 (0,0)(0,0),终点为 (5,2)(5,2),则:

中点画线法绘制实例演示: P₀(0,0) 到 P₁(5,2) M₁ M₂ M₃ M₄ (0,0) (1,0) (2,1) (3,1) (4,2) (5,2) X Y 0 1 2 3 4 5 6 1 2 3 理想直线 (y = 0.4x) 光栅化选择的像素点 中点判别位置 (M)
  • Δx=5\Delta x = 5Δy=2\Delta y = 2
  • 斜率 k=25=0.4k = \frac{2}{5} = 0.4

以下分别使用改进前(含小数)和改进后(纯整型)两种中点判别式递推展示计算过程:

1. 改进前(基于斜率 kk 的小数运算)

  • 初始化:初始判别式 d0=0.5k=0.50.4=0.1d_0 = 0.5 - k = 0.5 - 0.4 = 0.1
  • 状态更新规则
    • di0d_i \ge 0(中点在直线上方),选择右下方的点,即 yy 保持不变,并更新:

      di+1=dik=di0.4d_{i+1} = d_i - k = d_i - 0.4
    • di<0d_i < 0(中点在直线下方),选择右上方的点,即 yy 递增 11,并更新:

      di+1=di+1k=di+0.6d_{i+1} = d_i + 1 - k = d_i + 0.6
步数 (xx)当前绘制点当前判别式did_i判断di0d_i \ge 0下一步纵坐标yy下一步判别式di+1d_{i+1} 更新
00(0,0)(0, 0)0.10.1是 (0\ge 0)y=0y = 0d=0.10.4=0.3d = 0.1 - 0.4 = -0.3
11(1,0)(1, 0)0.3-0.3否 (<0< 0)y=1y = 1d=0.3+0.6=0.3d = -0.3 + 0.6 = 0.3
22(2,1)(2, 1)0.30.3是 (0\ge 0)y=1y = 1d=0.30.4=0.1d = 0.3 - 0.4 = -0.1
33(3,1)(3, 1)0.1-0.1否 (<0< 0)y=2y = 2d=0.1+0.6=0.5d = -0.1 + 0.6 = 0.5
44(4,2)(4, 2)0.50.5是 (0\ge 0)y=2y = 2d=0.50.4=0.1d = 0.5 - 0.4 = 0.1
55(5,2)(5, 2)-(已到达终点)--

2. 改进后(纯整数运算,令 D=2dΔxD = 2d \cdot \Delta x

  • 参数计算:已知 2Δx=10,2Δy=42\Delta x = 10, 2\Delta y = 4。 初始判别式为:

    D0=2d0Δx=2(0.5k)Δx=Δx2Δy=54=1D_0 = 2d_0 \cdot \Delta x = 2(0.5 - k)\Delta x = \Delta x - 2\Delta y = 5 - 4 = 1
  • 状态更新规则

    • Di0D_i \ge 0(中点在直线上方),选择右下方的点,即 yy 保持不变,并更新:

      Di+1=Di2Δy=Di4D_{i+1} = D_i - 2\Delta y = D_i - 4
    • Di<0D_i < 0(中点在直线下方),选择右上方的点,即 yy 递增 11,并更新:

      Di+1=Di+2Δx2Δy=Di+6D_{i+1} = D_i + 2\Delta x - 2\Delta y = D_i + 6
步数 (xx)当前绘制点当前判别式DiD_i判断Di0D_i \ge 0下一步纵坐标yy下一步判别式Di+1D_{i+1} 更新
00(0,0)(0, 0)11是 (0\ge 0)y=0y = 0D=14=3D = 1 - 4 = -3
11(1,0)(1, 0)3-3否 (<0< 0)y=1y = 1D=3+6=3D = -3 + 6 = 3
22(2,1)(2, 1)33是 (0\ge 0)y=1y = 1D=34=1D = 3 - 4 = -1
33(3,1)(3, 1)1-1否 (<0< 0)y=2y = 2D=1+6=5D = -1 + 6 = 5
44(4,2)(4, 2)55是 (0\ge 0)y=2y = 2D=54=1D = 5 - 4 = 1
55(5,2)(5, 2)-(已到达终点)--

归纳总结: 对比可以清楚地看到,改进后的判别式 DD 的符号变化轨迹(133151 \to -3 \to 3 \to -1 \to 5)与改进前的 dd0.10.30.30.10.50.1 \to -0.3 \to 0.3 \to -0.1 \to 0.5)完全对应一致,最终绘制出的点列序列也完全相同,但整个主循环中没有出现任何浮点数。


4. 中点画圆法

  • 基本思想:利用圆的 8 对称性,只需计算八分之一圆弧(0xy0 \le x \le y)。构造圆的隐式方程 F(x,y)=x2+y2R2=0F(x, y) = x^2 + y^2 - R^2 = 0
  • 判别式与递推公式
    • 从起点 (0,R)(0, R) 开始,步进 xi+1=xi+1x_{i+1} = x_i + 1,评估中点 M(xi+1,yi0.5)M(x_i + 1, y_i - 0.5)

    • 初始值:

      d0=1.25R(整数优化中常记为 d0=1R)d_0 = 1.25 - R \quad (\text{整数优化中常记为 } d_0 = 1 - R)
    • 递推规则:

      • di<0d_i < 0,选正右方点 (xi+1,yi)(x_i + 1, y_i),更新:

        di+1=di+2xi+3d_{i+1} = d_i + 2x_i + 3
      • di0d_i \ge 0,选斜下方点 (xi+1,yi1)(x_i + 1, y_i - 1),更新:

        di+1=di+2(xiyi)+5d_{i+1} = d_i + 2(x_i - y_i) + 5
Tip

经典实例演练:使用中点画圆法计算半径 R=5R=5 的 1/8 圆弧

已知半径 R=5R=5,初始起点为 (0,5)(0, 5)。我们只计算 xyx \le y 范围内的 1/8 圆弧像素序列。

以下分别对比优化前(含小数)和优化后(整型)两种中点判别式递推的详细计算过程:

1. 优化前(含小数运算)

  • 初始化:初始判别式 d0=1.25R=1.255=3.75d_0 = 1.25 - R = 1.25 - 5 = -3.75
  • 状态更新规则
    • di<0d_i < 0(中点在圆内),选择正右方点 (xi+1,yi)(x_i + 1, y_i),更新:

      di+1=di+2xi+3d_{i+1} = d_i + 2x_i + 3
    • di0d_i \ge 0(中点在圆外),选择斜下方点 (xi+1,yi1)(x_i + 1, y_i - 1),更新:

      di+1=di+2(xiyi)+5d_{i+1} = d_i + 2(x_i - y_i) + 5
步数当前绘制点(x,y)(x, y)当前判别式did_i判断di0d_i \ge 0下一步di+1d_{i+1} 更新计算下一步绘制点
00(0,5)(0, 5)3.75-3.75否 (<0<0)d=3.75+2(0)+3=0.75d = -3.75 + 2(0) + 3 = -0.75(1,5)(1, 5)
11(1,5)(1, 5)0.75-0.75否 (<0<0)d=0.75+2(1)+3=4.25d = -0.75 + 2(1) + 3 = 4.25(2,5)(2, 5)
22(2,5)(2, 5)4.254.25是 (0\ge 0)d=4.25+2(25)+5=3.25d = 4.25 + 2(2 - 5) + 5 = 3.25(3,4)(3, 4)
33(3,4)(3, 4)3.253.25是 (0\ge 0)d=3.25+2(34)+5=6.25d = 3.25 + 2(3 - 4) + 5 = 6.25(4,3)(4, 3)

2. 优化后(纯整数运算)

优化原理:在圆的光栅化中,由于每次的步进增量 2xi+32x_i+32(xiyi)+52(x_i-y_i)+5 均为整数,初始值中的 0.250.25 在与 00 判定大小的循环链中,不会改变判别式正负号的方向。因此可令新判别式 d=dold0.25d = d_{\text{old}} - 0.25,得到纯整数初始值,完全摆脱浮点数运算。

  • 初始化:初始判别式 d0=1R=15=4d_0 = 1 - R = 1 - 5 = -4
  • 状态更新规则:与优化前一致,仅初始值不同。
步数当前绘制点(x,y)(x, y)当前判别式did_i判断di0d_i \ge 0下一步di+1d_{i+1} 更新计算下一步绘制点
00(0,5)(0, 5)4-4否 (<0<0)d=4+2(0)+3=1d = -4 + 2(0) + 3 = -1(1,5)(1, 5)
11(1,5)(1, 5)1-1否 (<0<0)d=1+2(1)+3=4d = -1 + 2(1) + 3 = 4(2,5)(2, 5)
22(2,5)(2, 5)44是 (0\ge 0)d=4+2(25)+5=3d = 4 + 2(2 - 5) + 5 = 3(3,4)(3, 4)
33(3,4)(3, 4)33是 (0\ge 0)d=3+2(34)+5=6d = 3 + 2(3 - 4) + 5 = 6(4,3)(4, 3)

对比结论

  • 算完第 3 步后,下一步的待绘制坐标变成了 (4,3)(4, 3)。此时由于 x>yx > y4>34 > 3),超出了 xyx \le y 的循环控制条件,这 1/8 圆弧的计算至此宣告结束。

  • 优化前后判别式的正负号变化轨迹完全一致(负 \to\to\to 正),计算出的点列也完全相同:

    (0,5)(1,5)(2,5)(3,4)(0,5) \to (1,5) \to (2,5) \to (3,4)
    中点画圆法 1/8圆弧绘制实例 (R = 5) (0,5) (1,5) (2,5) (3,4) (4,3) 终止 y = x 边界线 M₁ M₂ M₃ M₄ X Y 0 1 2 3 4 5 6 1 2 3 4 5 理想圆弧 (R=5) 选中的像素点 中点判别位置 (M) y = x 对角边界

    算法在实际运行中,只需计算出这 4 个坐标点,再利用圆的八分对称性即可直接绘制出整个完整的圆。


二、 区域填充算法

1. 包含性测试 (In-Out Test)

  • 射线法 (Ray-Casting Method)
    • 从测试点 PP 向任意方向发射一条射线,计算该射线与多边形边界的交点个数。
    • 若交点个数为奇数,则点 PP 位于多边形内部;若为偶数,则位于外部。
    • 特例处理:当射线恰好穿过顶点或切于边时,需进行退化判定(通常规定“左开右闭”或仅计算单向相交)。
      • X-扫描线算法——顶点配对: 当扫描线与多边形的顶点相交时:
        • 若共享顶点的两条边分别落在扫描线的两边,交点只算一个;
        • 若共享顶点的两条边在扫描线的同一边,这时交点作为两个;
        • 对于多边形的水平边,不计它与扫描线的交点。

        直观记忆口诀:

        • 路过拐角(一上一下): 算作 1 个交点。
        • 切到尖峰/谷底(同上同下): 算作 2 个交点。
        • 切到水平躺平 the 边: 直接无视,算 0 个。
        x y 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3 4 5 6 7 8 9 10 11 12
  • 环绕数/弧长法 (Winding Number Method)
    • 计算测试点 PP 沿多边形边界绕行一周时,边界边绕点 PP 的净旋转角之和。若旋转角之和非零,则点在内部。

    环绕数/弧长法是怎么运作的?

    这个方法非常直观。想象你站在要测试的 P 点上,目光盯着多边形的边界,看着一个人沿着多边形边缘走完整整一圈。

    • 如果 P 点在外部:你的目光会跟着这个人来回摆动(比如先往左看30度,最后又往右看30度)。当他走回起点时,你目光转动的“净角度”(正负相互抵消后的代数和)将是 0度。
    • 如果 P 点在内部:因为你被边界包围了,为了看着他走完一圈,你自己必须原地转整整一个圈。也就是说,你目光旋转的代数和将是 2π(也就是360度)。

    通过计算这个角度的总和是 0 还是 2π,就能精准判断点到底在外面还是里面。


2. 多边形扫描转换算法 (扫描线算法)

  • 核心目标:逐行扫描像素,利用多边形内部的连贯性进行区间快速面填充。
  • 边表 (Edge Table, ET) 的构建
    • 按照边的最小 YY 值进行分类归档(桶排序)。

    • ET 表节点结构:

      ymaxxyminΔxnext\begin{array}{|c|c|c|c|} \hline y_{\max} & x_{\text{ymin}} & \Delta x & \text{next} \\ \hline \end{array}

      其中,ymaxy_{\max} 是边的最大 YY 坐标,xyminx_{\text{ymin}} 是边在最小 YY 坐标处对应的 XX 值,Δx\Delta x 是边的斜率倒数(即 1k\frac{1}{k})。

    Tip

    参数可能会出简答题

    • 注意:若边水平(Δy=0\Delta y = 0),则无需加入 ET 表。为了防止顶点处重复相交,若某边与邻边在顶点处单调递增或递减,需将上端点的高度算作 ymax1y_{\max}-1 进行区间缩短。
  • 活动边表 (Active Edge Table, AET) 的创建与维护步骤
    • AET 表存储与当前扫描线相交的所有边,并按 XX 坐标从小到大排序。
    • 算法执行步骤
      1. 初始化扫描线 y=yminy = y_{\min}
      2. 将 ET 表中对应当前 yy 的边链表移入 AET。
      3. 对 AET 中的边按照当前 XX 进行升序排序。
      4. 对排好序的 AET 链表,奇偶配对填充像素(即 x0x_0x1x_1, x2x_2x3x_3 之间的像素)。
      5. 从 AET 中剔除当前扫描线已达到最大值的边(即 y=ymaxy = y_{\max} 的节点)。
      6. 将 AET 中剩余边节点的 XX 递增更新:xnew=xold+Δxx_{\text{new}} = x_{\text{old}} + \Delta x
      7. 递增扫描线 y=y+1y = y + 1,循环第 2 步直至 AET 和 ET 均为空。
Tip

期末大题演练:多边形扫描转换与有效边表(ET/AET)计算

【题目描述】 已知多边形有 6 个顶点,其局部网格坐标为:A(2,1)A(2, 1)B(6,1)B(6, 1)C(6,5)C(6, 5)D(4,3)D(4, 3)E(2,5)E(2, 5)F(1,4)F(1, 4)。 规定有效边节点的物理存储结构为:[ y_max | x_ymin | 1/k | next ]。 请构建该多边形的边表(ET),并写出扫描线在 y=1y=1y=2y=2y=3y=3 时的活动边表(AET)及其填充区间。

【多边形网格示意图】

x y 0 1 2 3 4 5 6 1 2 3 4 5 A(2,1) B(6,1) C(6,5) D(4,3) E(2,5) F(1,4)

1. 计算所有有效非水平边的参数

水平边 ABABy=1y=1 时两端点高度一致)对扫描线无穿插变化贡献,直接舍弃。对其余 5 条有效边计算其边界特征值:

  • BCBC:下端点 ymin=1y_{\min}=1,上端点 ymax=5y_{\max}=5,下端点对应 x=6x=6。 斜率倒数:

    1k=xCxByCyB=6651=0\frac{1}{k} = \frac{x_C - x_B}{y_C - y_B} = \frac{6 - 6}{5 - 1} = 0
  • FAFA:下端点 ymin=1y_{\min}=1,上端点 ymax=4y_{\max}=4,下端点对应 x=2x=2。 斜率倒数:

    1k=xFxAyFyA=1241=13\frac{1}{k} = \frac{x_F - x_A}{y_F - y_A} = \frac{1 - 2}{4 - 1} = -\frac{1}{3}
  • CDCD:下端点 ymin=3y_{\min}=3,上端点 ymax=5y_{\max}=5,下端点对应 x=4x=4。 斜率倒数:

    1k=xCxDyCyD=6453=1\frac{1}{k} = \frac{x_C - x_D}{y_C - y_D} = \frac{6 - 4}{5 - 3} = 1
  • DEDE:下端点 ymin=3y_{\min}=3,上端点 ymax=5y_{\max}=5,下端点对应 x=4x=4。 斜率倒数:

    1k=xExDyEyD=2453=1\frac{1}{k} = \frac{x_E - x_D}{y_E - y_D} = \frac{2 - 4}{5 - 3} = -1
  • EFEF:下端点 ymin=4y_{\min}=4,上端点 ymax=5y_{\max}=5,下端点对应 x=1x=1。 斜率倒数:

    1k=xExFyEyF=2154=1\frac{1}{k} = \frac{x_E - x_F}{y_E - y_F} = \frac{2 - 1}{5 - 4} = 1

2. 构建边表 (Edge Table, ET)

将各条边按照其下端点的纵坐标 yminy_{\min} 归档入对应的扫描桶中。在同一个桶链表中,按照端点 xx 坐标递增排序,若 xx 相同,则按 1k\frac{1}{k} 递增排序:

  • y=1y=1:挂入 FAFA 边与 BCBC 边。因为 FAFAx=2x=2 小于 BCBCx=6x=6,因此链表顺序为:FABCFA \to BC
  • y=2y=2:无新起点边,桶为空(NULL)。
  • y=3y=3:挂入 DEDE 边与 CDCD 边。两者的 x=4x=4 相同,但 DEDE1k=1\frac{1}{k}=-1 小于 CDCD1k=1\frac{1}{k}=1,因此链表顺序为:DECDDE \to CD
  • y=4y=4:挂入 EFEF 边。

构建完的静态 ET 表结果如下

  • y=1y=1‘[4 | 2 | -1/3]‘(FA)‘[5 | 6 | 0]‘(BC)\to \text{`[4 | 2 | -1/3]`(FA)} \to \text{`[5 | 6 | 0]`(BC)}
  • y=2y=2NULL\to \text{NULL}
  • y=3y=3‘[5 | 4 | -1]‘(DE)‘[5 | 4 | 1]‘(CD)\to \text{`[5 | 4 | -1]`(DE)} \to \text{`[5 | 4 | 1]`(CD)}
  • y=4y=4‘[5 | 1 | 1]‘(EF)\to \text{`[5 | 1 | 1]`(EF)}

3. 活动边表 (Active Edge Table, AET) 的递推更新

演示扫描线 y=1,2,3y = 1, 2, 3 时的活动边表动态更新与像素区间配对:

(1) 当扫描线 y=1y = 1

  • y=1y=1 桶中的新边并入当前为空的 AET并排序。

  • 当前 AET 状态

    AET‘[4 | 2 | -1/3]‘(FA)‘[5 | 6 | 0]‘(BC)\text{AET} \to \text{`[4 | 2 | -1/3]`(FA)} \to \text{`[5 | 6 | 0]`(BC)}
  • 交点配对与填充区间: 两交点为 x=2x=2x=6x=6。对两交点之间的像素区间 [2,6][2, 6] 实施色彩填充。

(2) 当扫描线 y=2y = 2

  • 剔除失效边:当前 AET 中无最大高度 ymax=2y_{\max}=2 的边,不执行剔除。

  • 递增更新 XX 坐标(xnew=xold+1kx_{\text{new}} = x_{\text{old}} + \frac{1}{k}):

    • FAFA 边:x=2+(13)=531.67x = 2 + (-\frac{1}{3}) = \frac{5}{3} \approx 1.67
    • BCBC 边:x=6+0=6x = 6 + 0 = 6
  • 并入新边:y=2y=2 桶的 ET 为空,无新边并入。对 AET 重新排序。

  • 当前 AET 状态

    AET‘[4 | 5/3 | -1/3]‘(FA)‘[5 | 6 | 0]‘(BC)\text{AET} \to \text{`[4 | 5/3 | -1/3]`(FA)} \to \text{`[5 | 6 | 0]`(BC)}
  • 交点配对与填充区间: 两交点为 x1.67x \approx 1.67x=6x=6。由于填充像素网格通常取整,该处奇偶配对区间为 [1.67,6][1.67, 6],实际着色区间仍为 [2,6][2, 6]

(3) 当扫描线 y=3y = 3

  • 剔除失效边:当前 AET 中无最大高度 ymax=3y_{\max}=3 的边,不执行剔除。

  • 递增更新 XX 坐标:

    • FAFA 边:x=53+(13)=431.33x = \frac{5}{3} + (-\frac{1}{3}) = \frac{4}{3} \approx 1.33
    • BCBC 边:x=6+0=6x = 6 + 0 = 6
  • 并入新边:有 y=3y=3 桶中的新边 DEDECDCD 并入,并对 AET 链表中所有边按最新 xx 重排(四个交点 xx 坐标值分别为:43\frac{4}{3}444466):

  • 当前 AET 状态

    AET‘[4 | 4/3 | -1/3]‘(FA)‘[5 | 4 | -1]‘(DE)‘[5 | 4 | 1]‘(CD)‘[5 | 6 | 0]‘(BC)\text{AET} \to \text{`[4 | 4/3 | -1/3]`(FA)} \to \text{`[5 | 4 | -1]`(DE)} \to \text{`[5 | 4 | 1]`(CD)} \to \text{`[5 | 6 | 0]`(BC)}
  • 交点配对与填充区间: 两两奇偶配对可得到两个独立区间:[43,4][\frac{4}{3}, 4][4,6][4, 6]。 像素化填充时,区间 1 填充 [2,4][2, 4],区间 2 填充 [4,6][4, 6],最终合并填充区间为 [2,6][2, 6]


3. 种子填充算法

  • 简单种子填充法 (递归法)
    • 基本思想:从给定的种子像素 (x,y)(x, y) 开始,判断其颜色。若既非边界色(边界表示法)也未被着色成填充色,则将其涂为新色,并以此为基础向四个方向(4-邻接)或八个方向(8-邻接)递归调用自身。
    • 缺点:由于采用逐像素递归的深度优先搜索,递归调用栈深度巨大,在填充大面积区域时极易引发系统调用栈溢出,性能低下。
  • 扫描线种子填充法
    • 优化原理:通过以“水平像素线段”为基础填充单元,大大减少压栈和出栈次数,效率极高,适用于大面积区域填充
    • 核心步骤
      1. 给定初始种子点,向左右两个方向水平扩展,填充当前扫描线上所有未填充的连续像素,记录此区间的左右端点 [xleft,xright][x_{\text{left}}, x_{\text{right}}]
      2. 在相邻的上下两条扫描线(y+1y+1y1y-1)的 [xleft,xright][x_{\text{left}}, x_{\text{right}}] 区间内,从左到右搜索未填充的像素。
      3. 找到该区间的每个子连通区段最右侧的像素,作为新种子点压入栈中。
      4. 弹出栈顶种子点,重复上述步骤,直到栈为空。

三、 字符表示与处理

  • 点阵字符 (Bitmap Font)
    • 字符形状通过二进制位图表示(1 表示有墨色,0 表示背景)。
    • 特点:显示速度极快,但缩放或旋转时会出现严重的锯齿与失真。
  • 矢量字符 (Vector Font)
    • 字符轮廓用一组数学曲线(如 Bézier 曲线)或折线段描述。
    • 特点:能够无损缩放、旋转,字体美观清晰,但渲染时需要实时进行多边形转换与像素填充,开销较大。

四、 走样与反走样 (Aliasing & Anti-aliasing)

  • 走样现象:在对连续的几何图形进行离散采样时,由于采样频率不满足奈奎斯特-香农(Shannon)采样定理而引发的信号畸变与高频分量混叠。
    • 具体表现
      1. 阶梯状/锯齿状边界 (Jaggies):直线或圆弧边缘呈现不平滑的锯齿。
      2. 细节失真 (Moiré Patterns):在细密网格或复杂纹理区域出现条纹状杂光混叠干扰。
      3. 细小物体在扫描线间闪烁丢失 (Temporal Aliasing):当物体移动时,微小图元交替落入或漏出采样点,导致画面闪烁不稳。
  • 常见反走样技术
    • 提高分辨率 / 超采样 (Super-sampling, SSAA):在更高的虚拟分辨率下进行像素渲染,然后经过平滑滤波器下采样回显示设备的原分辨率。局限:显存开销与光栅化计算开销成倍暴增,硬件代价极高。
    • 简单区域采样 (Unweighted Area Sampling / Box Filter):像素颜色仅由覆盖该像素的多边形相交面积比例决定,不考虑覆盖区域距离像素中心的具体位置。
    • 加权区域采样 (Weighted Area Sampling):除了考虑覆盖面积比例,还根据覆盖区域到像素中心的距离进行加权计算。通常采用圆锥形/高斯形等加权滤波器,越靠近中心点的相交部分对像素亮度的贡献权重越大。

五、 裁剪算法

1. Cohen-Sutherland 编码裁剪算法 (直线的线段裁剪)

  • 区域编码设计: 将裁剪窗口的四条边延长,将整个平面划分为 9 个区域。每个区域用一个 4 位二进制码(CTCBCRCLC_T C_B C_R C_L)表示:

    1001 | 1000 | 1010
    -----|------|-----
    0001 | 0000 | 0010  (0000 为窗口内部)
    -----|------|-----
    0101 | 0100 | 0110
    窗口 (0000) 1001 1000 1010 0001 0010 0101 0100 0110 编码规则: [上(T) 下(B) 右(R) 左(L)]
    Tip

    编码记忆口诀“上下右左”(TBRL)

    这 4 位二进制码像四个方向的开关,从高位到低位(从左到右,即从第 1 位到第 4 位)依次判断点的位置:

    • 第 1 位 (T):是否在窗口方 (Top)
    • 第 2 位 (B):是否在窗口方 (Bottom)
    • 第 3 位 (R):是否在窗口侧 (Right)
    • 第 4 位 (L):是否在窗口侧 (Left)

    编码直接拼写规律:

    1. 窗口内部:四个方向均不越界,各二进制位全为 0,即 0000
    2. 正方向(四边外侧):只有对应方向的开关为 1。例如:正上方是 1000,正左侧是 0001
    3. 四个斜角:将相交的两个方向的 1 进行叠加(按位或/相加)。例如:“左下方”既在窗口下方(0100)又在窗口左侧(0001),叠加后为 0100 + 0001 = 0101

    ⚠️ 避坑警示(求交裁剪顺序的差异): 在进行“求交裁剪判定”时,对于在斜角区域的端点(如编码为 1001 的左上角),由于其同时处于两个边界的外侧,需要依次判断与哪个边界求交。不同教材或 PPT 代码中的求交边界判定顺序可能存在差异:

    • 常见顺序 1:优先按照 上、下、右、左(TBRL) 的顺序依次判断并求交。例如对 1001 先判定并计算与上边界的交点。
    • 常见顺序 2(如部分 PPT 代码):优先按照 左、右、下、上(LRBT) 的顺序依次判断并求交。例如对 1001 先判定并计算与左边界的交点。
    • 注意:虽然两种顺序最终裁剪出的线段完全一致,但中间迭代的求交步骤和产生的交点坐标会不同。在做题、考试或编写代码时,务必注意题目要求的求交判定顺序。
  • 算法执行过程

    1. 计算直线段两端点 P1,P2P_1, P_2 的编码 code1,code2code_1, code_2
    2. 完全保留判定:若 code1=0 且 code2=0code_1 = 0 \text{ 且 } code_2 = 0,则线段完全在窗口内,接收。
    3. 完全舍弃判定:若 code1  &amp;  code20code_1 \;\&amp;\; code_2 \neq 0(按位与非零),说明两点同在某条边界外侧,直接拒绝。
    4. 求交裁剪判定:若上述两项均不满足,则选择一个位于窗口外的端点(编码非零),将其与窗口的边界(按 Top, Bottom, Right, Left 顺序)求交,原端点替换为交点,重新计算编码,返回第一步循环。

2. Liang-Barsky 裁剪算法 (参数化线段裁剪)

  • 基本思想:将线段写为参数方程形式 x=x1+uΔxx = x_1 + u\Delta x, y=y1+uΔyy = y_1 + u\Delta y(其中 0u10 \le u \le 1)。将复杂的几何裁剪问题,转化为求解一元一次不等式组的代数问题。

  • 参数的物理与几何含义详解

    • 参数 uu
      • 几何上,它表示线段上的点到起点 P1P_1相对距离比例
      • u=0u=0 对应起点 P1P_1u=1u=1 对应终点 P2P_20<u<10 < u < 1 对应线段内部的点。
    • 参数 pip_i (投影位移量/方向判定因子)
      • 物理上,它代表线段在相应坐标轴上的投影位移量(即运动方向在边界垂直法线上的投影)。
      • 左边界 (i=1i=1)p1=Δxp_1 = -\Delta x(即线段向左运动的位移大小)
      • 右边界 (i=2i=2)p2=Δxp_2 = \Delta x(即线段向右运动的位移大小)
      • 下边界 (i=3i=3)p3=Δyp_3 = -\Delta y(即线段向下运动的位移大小)
      • 上边界 (i=4i=4)p4=Δyp_4 = \Delta y(即线段向上运动的位移大小)
      • pip_i 的符号意义
        • pi<0p_i < 0:线段从边界外侧内侧移动(穿入过程)。
        • pi>0p_i > 0:线段从边界内侧外侧移动(穿出过程)。
        • pi=0p_i = 0:线段平行于该边界。
    • 参数 qiq_i (初始边界距离/容差因子)
      • 物理上,它代表线段起点 P1P_1 到对应裁剪边界的有向距离。如果 qi0q_i \ge 0,表示起点在边界内侧(或边界上);如果 qi<0q_i < 0,表示起点在边界外侧。
      • 左边界 (i=1i=1)q1=x1xwminq_1 = x_1 - x_{\text{wmin}}(起点偏离左边界的距离)
      • 右边界 (i=2i=2)q2=xwmaxx1q_2 = x_{\text{wmax}} - x_1(右边界到起点的距离)
      • 下边界 (i=3i=3)q3=y1ywminq_3 = y_1 - y_{\text{wmin}}(起点偏离下边界的距离)
      • 上边界 (i=4i=4)q4=ywmaxy1q_4 = y_{\text{wmax}} - y_1(上边界到起点的距离)
    • 比值 ri=qipir_i = \frac{q_i}{p_i} (交点参数值)
      • 几何上,它是线段无限延长后,与第 ii 条边界所在直线相交时的参数 uu
      • pi<0p_i < 0 时,它是线段穿入ii 条边界的时刻;
      • pi>0p_i > 0 时,它是线段穿出ii 条边界的时刻。
    • 区间的更新策略 (u1u_1u2u_2)
      • u1u_1(起点参数):记录线段最晚进入所有边界的时刻。因为线段必须进入所有边界内侧才可见,所以 u1=max({0}{ripi<0})u_1 = \max\left(\{0\} \cup \{r_i \mid p_i < 0\}\right)
      • u2u_2(终点参数):记录线段最早离开任意边界的时刻。因为线段只要离开其中任意一个边界就不可见了,所以 u2=min({1}{ripi>0})u_2 = \min\left(\{1\} \cup \{r_i \mid p_i > 0\}\right)
      • u1>u2u_1 > u_2,表示线段在“进入所有边界”之前就已经“离开了某个边界”,即线段完全在窗口外,应予以拒绝。
  • 将窗口范围 xwminx1+uΔxxwmaxx_{\text{wmin}} \le x_1 + u\Delta x \le x_{\text{wmax}} 转化为通用不等式:

    upkqk,k=1,2,3,4u \cdot p_k \le q_k, \quad k = 1, 2, 3, 4
  • 裁剪求解流程

    • pk=0p_k = 0qk<0q_k < 0,线段平行于边界且在外侧,直接拒绝。
    • 对于 pk0p_k \neq 0
      • pk<0p_k < 0,计算交点参数 rk=qkpkr_k = \frac{q_k}{p_k},更新起点参数: u1=max(0,rk)u_1 = \max(0, r_k)
      • pk>0p_k > 0,计算交点参数 rk=qkpkr_k = \frac{q_k}{p_k},更新终点参数: u2=min(1,rk)u_2 = \min(1, r_k)
    • 若最终得到 u1>u2u_1 > u_2,说明线段完全在窗口外,舍弃;否则,裁剪后的线段对应参数区间为 [u1,u2][u_1, u_2]
Tip

期末大题演练:使用 Liang-Barsky 算法裁剪直线段

【题目描述】 已知裁剪窗口边界为:xwmin=0x_{\text{wmin}} = 0xwmax=2x_{\text{wmax}} = 2ywmin=0y_{\text{wmin}} = 0ywmax=2y_{\text{wmax}} = 2。直线段的起点坐标为 P0(1,1)P_0(1, -1),终点坐标为 P1(2,3)P_1(2, 3)。请用 Liang-Barsky 算法求出该线段在窗口内部的裁剪后端点坐标值。

【裁剪几何示意图】

X Y 0 1 2 3 -1 -1 1 2 3 Window P0(1,-1) P1(2,3) I0(1.25,0) I1(1.75,2)

1. 参数分析与计算准备

  • 线段起点 P0(x1,y1)=(1,1)P_0(x_1, y_1) = (1, -1),终点 P1(x2,y2)=(2,3)P_1(x_2, y_2) = (2, 3)

  • 计算线段的变化率:

    Δx=x2x1=21=1,Δy=y2y1=3(1)=4\Delta x = x_2 - x_1 = 2 - 1 = 1, \quad \Delta y = y_2 - y_1 = 3 - (-1) = 4
  • 直线的参数方程形式为:

    {x=1+u(1)y=1+u(4)(0u1)\begin{cases} x = 1 + u \cdot (1) \\ y = -1 + u \cdot (4) \end{cases} \quad (0 \le u \le 1)
  • 窗口边界参数:xwmin=0x_{\text{wmin}} = 0xwmax=2x_{\text{wmax}} = 2ywmin=0y_{\text{wmin}} = 0ywmax=2y_{\text{wmax}} = 2

2. 计算各边界对应的不等式参数 pk,qk,rkp_k, q_k, r_k

利用公式 upkqku \cdot p_k \le q_k,依次计算四个边界的参数特征:

  • 左边界 (k=1k=1)

    p1=Δx=1(<0)p_1 = -\Delta x = -1 \quad (<0) q1=x1xwmin=10=1    r1=q1p1=1q_1 = x_1 - x_{\text{wmin}} = 1 - 0 = 1 \implies r_1 = \frac{q_1}{p_1} = -1
  • 右边界 (k=2k=2)

    p2=Δx=1(>0)p_2 = \Delta x = 1 \quad (>0) q2=xwmaxx1=21=1    r2=q2p2=1q_2 = x_{\text{wmax}} - x_1 = 2 - 1 = 1 \implies r_2 = \frac{q_2}{p_2} = 1
  • 下边界 (k=3k=3)

    p3=Δy=4(<0)p_3 = -\Delta y = -4 \quad (<0) q3=y1ywmin=10=1    r3=q3p3=0.25q_3 = y_1 - y_{\text{wmin}} = -1 - 0 = -1 \implies r_3 = \frac{q_3}{p_3} = 0.25
  • 上边界 (k=4k=4)

    p4=Δy=4(>0)p_4 = \Delta y = 4 \quad (>0) q4=ywmaxy1=2(1)=3    r4=q4p4=0.75q_4 = y_{\text{wmax}} - y_1 = 2 - (-1) = 3 \implies r_4 = \frac{q_4}{p_4} = 0.75

3. 确定最终参数区间 [u1,u2][u_1, u_2]

根据方向穿入(pk<0p_k < 0)与穿出(pk>0p_k > 0)的原则,分别筛选取最大和最小值:

  • 由外向内穿入点参数最大值 u1u_1

    u1=max({0}{rkpk<0})=max(0,r1,r3)=max(0,1,0.25)=0.25u_1 = \max\left(\{0\} \cup \{r_k \mid p_k < 0\}\right) = \max(0, r_1, r_3) = \max(0, -1, 0.25) = 0.25
  • 由内向外穿出点参数最小值 u2u_2

    u2=min({1}{rkpk>0})=min(1,r2,r4)=min(1,1,0.75)=0.75u_2 = \min\left(\{1\} \cup \{r_k \mid p_k > 0\}\right) = \min(1, r_2, r_4) = \min(1, 1, 0.75) = 0.75

因为 u1=0.25<u2=0.75u_1 = 0.25 < u_2 = 0.75,说明线段与裁剪窗口有相交部分,裁剪有效区间对应参数范围为 [0.25,0.75][0.25, 0.75]

4. 代入参数方程求解裁剪后的物理端点坐标

  • 起点交点(u=0.25u = 0.25

    {Xstart=1+0.25×1=1.25Ystart=1+0.25×4=0\begin{cases} X_{\text{start}} = 1 + 0.25 \times 1 = 1.25 \\ Y_{\text{start}} = -1 + 0.25 \times 4 = 0 \end{cases}

    交点 1 坐标为 (1.25,0)(1.25, 0)

  • 终点交点(u=0.75u = 0.75

    {Xend=1+0.75×1=1.75Yend=1+0.75×4=2\begin{cases} X_{\text{end}} = 1 + 0.75 \times 1 = 1.75 \\ Y_{\text{end}} = -1 + 0.75 \times 4 = 2 \end{cases}

    交点 2 坐标为 (1.75,2)(1.75, 2)

结论: 裁剪后的线段有效部分处于窗口内部,其两个端点坐标分别为 (1.25,0)(1.25, 0)(1.75,2)(1.75, 2)


3. Sutherland-Hodgeman 算法 (多边形裁剪)

  • 基本思想:采用分治法逐边裁剪思想。把多边形裁剪问题分解为用裁剪窗口的单条边界依次对输入的多边形顶点序列进行裁剪,每一次处理完的输出顶点序列,将作为下一次裁剪的输入顶点序列,具有流式流水线处理的特征。

  • 内/外判定(可见侧与不可见侧定义): 在裁剪过程中,每条裁剪边界将平面划分为两个区域:

    • 内 (Inside):等价于可见一侧 (Visible Side)。
    • 外 (Outside):等价于不可见一侧 (Invisible Side)。

    不同窗口类型下的内/外判定规则:

    1. 标准矩形窗口
      • 左边界 (x=xwminx = x_{\text{wmin}}):xxwminx \ge x_{\text{wmin}} 为内,否则为外。
      • 右边界 (x=xwmaxx = x_{\text{wmax}}):xxwmaxx \le x_{\text{wmax}} 为内,否则为外。
      • 下边界 (y=ywminy = y_{\text{wmin}}):yywminy \ge y_{\text{wmin}} 为内,否则为外。
      • 上边界 (y=ywmaxy = y_{\text{wmax}}):yywmaxy \le y_{\text{wmax}} 为内,否则为外。
    2. 任意凸多边形窗口(使用有向有向边遍历与叉乘判断):
      • 若顶点序列按顺时针 (CW) 顺序连接,则有向边右侧为内 (可见),左侧为外。
      • 若顶点序列按逆时针 (CCW) 顺序连接,则有向边左侧为内 (可见),右侧为外。
  • 边界求交的输入与输出判定 (从起点 SS 到终点 PP)

    边与顶点的相对位置关系是否输出交点 II是否输出终点 PP
    S 内 (可见) \to P 内 (可见)是 (输出 PP)
    S 内 (可见) \to P 外 (不可见)是 (输出 II)
    S 外 (不可见) \to P 外 (不可见)否 (不输出)
    S 外 (不可见) \to P 内 (可见)是 (输出 II)是 (输出 PP)
  • 缺点:只适用于凸多边形裁剪。如果裁剪凹多边形,可能会产生多余的退化连接线。


4. Weiler-Atherton 多边形裁剪算法

  • 基本思想:可用于任意多边形(包括凹多边形、带孔多边形)的裁剪。
  • 顺时针排列主多边形和裁剪多边形的顶点,建立双向循环链表,求出所有交点,标记为“入点”(由外进入窗口)或“出点”(由窗口内出来)。
  • 遍历规则
    • 遇到入点,沿主多边形顶点顺时针遍历;
    • 遇到出点,跳转至裁剪多边形,沿裁剪多边形边界顺时针遍历,直至回到起点形成闭合裁剪区域。

5. 裁剪算法特性横向对比

裁剪算法裁剪对象核心优势局限性/缺点
Cohen-Sutherland线段编码快速,特别适合绝大部分线段处于完全保留或完全舍弃的场景频繁迭代求交时效率降低
Liang-Barsky线段参数化计算,减少了乘除法的次数仅限矩形窗口
Sutherland-Hodgeman多边形流水线结构简单,易于硬件流水线实现凹多边形裁剪可能会产生冗余连接线
Weiler-Atherton多边形支持任意复杂的凹多边形和内孔裁剪数据结构十分复杂,涉及较多链表跳转

第 4 章 图形几何变换

一、 齐次坐标 (Homogeneous Coordinates)

  • 概念:用 n+1n+1 维向量来表示 nn 维空间中的点。对于二维平面上的点 (x,y)(x, y),其齐次坐标表示为 (hx,hy,h)(hx, hy, h),其中 h0h \neq 0 是缩放因子。通常令 h=1h = 1,即标准齐次坐标为 (x,y,1)(x, y, 1)

  • 引入齐次坐标的目的

    • 将图形学中原本属于非线性的平移操作(向量加法),统一化为矩阵乘法。
    • 将平移、旋转、缩放等多种操作统一写成相同的矩阵乘法形式,从而支持多级复合矩阵的连续连乘乘积,大幅提升图形硬件管线的执行效率。
  • 齐次坐标向普通坐标的转换

    (xh,yh,w)    (xhw,yhw)(x_h, y_h, w) \implies \left( \frac{x_h}{w}, \frac{y_h}{w} \right)

二、 几何变换通式及其分块含义

引入齐次坐标后,图形的几何变换可以表示为矩阵乘法。下面分别给出二维与三维几何变换矩阵的通式及其物理含义:

1. 二维齐次变换通式 (3×33 \times 3 矩阵)

T3×3=[abpxcdpylms]=[abpxcdpylms]T_{3 \times 3} = \begin{bmatrix} a & b & p_x \\ c & d & p_y \\ l & m & s \end{bmatrix} = \left[ \begin{array}{cc|c} a & b & p_x \\ c & d & p_y \\ \hline l & m & s \end{array} \right]
  • 左上角 2×22 \times 2 矩阵 [abcd]\begin{bmatrix} a & b \\ c & d \end{bmatrix}(线性变换项)
    • 控制二维空间中的旋转、缩放、反射对称和错切
    • 比例缩放 (Scaling):由对角线上的元素 a,da, d 控制。
      • 拉伸/放大:若 a>1a > 1(或 d>1d > 1),则沿 XX 轴(或 YY 轴)方向放大。
      • 压缩/缩小:若 0<a<10 < a < 1(或 0<d<10 < d < 1),则在对应轴方向上缩小。
      • 无缩放:当 a=1,d=1a = 1, d = 1 时。
      • 反射/对称镜像 (Mirror Reflection):若对角线元素为负数。例如,若 a=1,d=1a = -1, d = 1,则图形关于 YY 轴反射对称;若 a=1,d=1a = 1, d = -1,关于 XX 轴对称;若 a=1,d=1a = -1, d = -1,关于原点对称。
    • 旋转 (Rotation):当矩阵表现为 [cosθsinθsinθcosθ]\begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} 时,代表绕原点逆时针旋转角度 θ\theta。它改变 x,yx, y 的坐标值使其绕原点圆周运动,但保持点到原点的距离不变。
    • 错切 (Shear):由非对角线上的 b,cb, c 控制。其中 bb 产生沿 XX 方向的错切,cc 产生沿 YY 方向的错切。
  • 右上角 2×12 \times 1 向量 [pxpy]\begin{bmatrix} p_x \\ p_y \end{bmatrix}(平移变换项)
    • 控制图形沿 X,YX, Y 方向的平移位移量
    • 在齐次坐标最后一位 w=1w = 1 的情况下,平移项 px,pyp_x, p_y 相当于直接累加到原坐标上(x=ax+by+px1x' = ax + by + p_x \cdot 1)。若 w1w \neq 1,平移产生的实际位移为 px/wp_x/wpy/wp_y/w
  • 左下角 1×21 \times 2 向量 [lm]\begin{bmatrix} l & m \end{bmatrix}(透视投影项)
    • 用于二维空间中的透视投影变换,控制视线并非平行投射时的汇聚形变(即产生灭点)。
  • 右下角 1×11 \times 1 标量 [s][s](全局比例因子)
    • 控制图形的全局等比例统一缩放
    • 在将齐次坐标转换为普通笛卡尔坐标时,所有分量都需要除以齐次项(此时 w=sw' = s),这会导致普通坐标变为原先的 1s\frac{1}{s}
      • 0<s<10 < s < 1:图形整体等比放大
      • s>1s > 1:图形整体等比缩小
      • s=1s = 1:图形保持原大小。

2. 三维齐次变换通式 (4×44 \times 4 矩阵)

T4×4=[abcpxdefpyghipzlmns]=[abcpxdefpyghipzlmns]T_{4 \times 4} = \begin{bmatrix} a & b & c & p_x \\ d & e & f & p_y \\ g & h & i & p_z \\ l & m & n & s \end{bmatrix} = \left[ \begin{array}{ccc|c} a & b & c & p_x \\ d & e & f & p_y \\ g & h & i & p_z \\ \hline l & m & n & s \end{array} \right]
  • 左上角 3×33 \times 3 矩阵(线性变换项)
    • 控制三维空间中的旋转、缩放、反射对称和错切
    • 比例缩放 (Scaling):由主对角线上的 a,e,ia, e, i 控制(分别对应 sx,sy,szs_x, s_y, s_z)。
      • 因子 >1> 1 代表沿对应轴拉伸,处于 0011 之间代表压缩
      • 镜像反射:若有对角线项为负值,则沿相应的平面镜像。例如 i=1i = -1 时,物体的 zz 坐标反转,发生关于 XYXY 平面的镜像反射。
    • 旋转 (Rotation):旋转通过整个 3×33 \times 3 矩阵的联合变化实现。对于纯旋转,该子矩阵必须是正交矩阵(各行、各列向量正交且模为1),且行列式值为 1。
      • 绕三个不同的坐标轴旋转时,改变的矩阵元素各有不同,但旋转轴对应的坐标分量保持不变:
        • 绕 Z 轴旋转:改变左上角 2×22 \times 2a,b,d,ea, b, d, e 元素(即 X,YX, Y 坐标发生变化,而 ZZ 坐标不变,此时对角线上的 i=1i = 1)。
        • 绕 X 轴旋转:改变右下角 2×22 \times 2e,f,h,ie, f, h, i 元素(即 Y,ZY, Z 坐标发生变化,而 XX 坐标不变,此时对角线上的 a=1a = 1)。
        • 绕 Y 轴旋转:改变四个角上的 a,c,g,ia, c, g, i 元素(即 X,ZX, Z 坐标发生变化,而 YY 坐标不变,此时对角线上的 e=1e = 1)。
    • 错切 (Shear):由非对角线上的 6 个元素控制。
  • 右上角 3×13 \times 1 向量 [pxpypz]\begin{bmatrix} p_x \\ p_y \\ p_z \end{bmatrix}(平移变换项)
    • 控制三维物体沿 X,Y,ZX, Y, Z 三个方向的空间平移距离。在 w=1w=1 下,平移分量直接作为常数相加。
  • 左下角 1×31 \times 3 向量 [lmn]\begin{bmatrix} l & m & n \end{bmatrix}(透视投影项)
    • 控制空间几何物体在进行透视投影时产生的近大远小的投影形变。
  • 右下角 1×11 \times 1 标量 [s][s](全局比例因子)
    • 控制三维物体的整体全局等比放缩。由于三维空间坐标在齐次归一化时都要除以 ss,因此当 s>1s > 1 时,物体的尺寸变为原来的 1s\frac{1}{s},而物体的物理体积则缩小为原来的 1s3\frac{1}{s^3}

三、 基本变换矩阵 (2D 与 3D 矩阵全集)

1. 二维基本齐次变换矩阵 (3×33 \times 3)

  • 平移变换 (Translation)

    T(tx,ty)=[10tx01ty001]T(t_x, t_y) = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1 \end{bmatrix}
  • 比例缩放 (Scaling)

    S(sx,sy)=[sx000sy0001]S(s_x, s_y) = \begin{bmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \end{bmatrix}
  • 旋转变换 (Rotation,绕原点逆时针旋转角度 θ\theta)

    R(θ)=[cosθsinθ0sinθcosθ0001]R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}
  • 对称反射变换 (Reflection)

    • 关于 XX 轴反射

      Mx=[100010001]M_x = \begin{bmatrix} 1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & 1 \end{bmatrix}
    • 关于 YY 轴反射

      My=[100010001]M_y = \begin{bmatrix} -1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}
    • 关于原点对称反射

      Morigin=[100010001]M_{\text{origin}} = \begin{bmatrix} -1 & 0 & 0 \\ 0 & -1 & 0 \\ 0 & 0 & 1 \end{bmatrix}
    • 关于直线 y=xy=x 反射

      My=x=[010100001]M_{y=x} = \begin{bmatrix} 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix}
    • 关于直线 y=xy=-x 反射

      My=x=[010100001]M_{y=-x} = \begin{bmatrix} 0 & -1 & 0 \\ -1 & 0 & 0 \\ 0 & 0 & 1 \end{bmatrix}
  • 错切变换 (Shear)

    • 沿 XX 方向错切

      SHx(shx)=[1shx0010001]SH_x(sh_x) = \begin{bmatrix} 1 & sh_x & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}
    • 沿 YY 方向错切

      SHy(shy)=[100shy10001]SH_y(sh_y) = \begin{bmatrix} 1 & 0 & 0 \\ sh_y & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}

2. 三维基本齐次变换矩阵 (4×44 \times 4)

  • 平移变换

    T(tx,ty,tz)=[100tx010ty001tz0001]T(t_x, t_y, t_z) = \begin{bmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix}
  • 比例缩放

    S(sx,sy,sz)=[sx0000sy0000sz00001]S(s_x, s_y, s_z) = \begin{bmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
  • 绕三个主坐标轴的旋转矩阵

    • 绕 Z 轴旋转 θ\theta

      Rz(θ)=[cosθsinθ00sinθcosθ0000100001]R_z(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 & 0 \\ \sin\theta & \cos\theta & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
    • 绕 X 轴旋转 θ\theta

      Rx(θ)=[10000cosθsinθ00sinθcosθ00001]R_x(\theta) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta & 0 \\ 0 & \sin\theta & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
    • 绕 Y 轴旋转 θ\theta

      Ry(θ)=[cosθ0sinθ00100sinθ0cosθ00001]R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta & 0 \\ 0 & 1 & 0 & 0 \\ -\sin\theta & 0 & \cos\theta & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
  • 对称反射变换 (Reflection)

    • 关于 XYXY 平面反射 (zzz \to -z)

      Mxy=[1000010000100001]M_{xy} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
    • 关于 YZYZ 平面反射 (xxx \to -x)

      Myz=[1000010000100001]M_{yz} = \begin{bmatrix} -1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
    • 关于 ZXZX 平面反射 (yyy \to -y)

      Mzx=[1000010000100001]M_{zx} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
  • 错切变换 (Shear,以沿 Z 轴错切为例)

    • 错切量由 ZZ 坐标的大小决定,使 X,YX, Y 坐标发生线性错切偏移:

      SHz(shx,shy)=[10shx001shy000100001]SH_z(sh_x, sh_y) = \begin{bmatrix} 1 & 0 & sh_x & 0 \\ 0 & 1 & sh_y & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}

四、 复合变换 (Composite Transformations)

  • 乘法顺序非交换性:由于矩阵乘法不满足交换律(即 ABBAA \cdot B \neq B \cdot A),多个变换连续作用时,矩阵连乘的顺序至关重要。

  • 典型推导:关于任意点 (xf,yf)(x_f, y_f) 的旋转: 为了让物体绕任意指定点 F(xf,yf)F(x_f, y_f) 旋转 θ\theta,可拆解为三步操作:

    1. 平移物体,使点 FF 与坐标原点重合:T(xf,yf)T(-x_f, -y_f)
    2. 绕原点进行标准旋转R(θ)R(\theta)
    3. 反向平移物体,使原点回到点 FF 的原始位置:T(xf,yf)T(x_f, y_f)

    复合变换矩阵表达为(右乘列向量的顺序):

步骤1: 平移使其与原点重合 X Y F(xf, yf) T(-xf, -yf) 步骤2: 绕原点旋转 θ X Y R(θ) 步骤3: 反向平移回原位置 X Y F(xf, yf) T(xf, yf)

复合变换矩阵表达为(右乘列向量的顺序):

M=T(xf,yf)R(θ)T(xf,yf) M = T(x_f, y_f) \cdot R(\theta) \cdot T(-x_f, -y_f)

矩阵各部分的具体定义与参数分析

  • 平移到原点矩阵 T(xf,yf)T(-x_f, -y_f)T(xf,yf)=[10xf01yf001]T(-x_f, -y_f) = \begin{bmatrix} 1 & 0 & -x_f \\ 0 & 1 & -y_f \\ 0 & 0 & 1 \end{bmatrix}
    • 作用:将旋转中心点 F(xf,yf)F(x_f, y_f) 平移到坐标原点。参数中的平移增量 tx=xft_x = -x_fty=yft_y = -y_f,使得后续的旋转可以利用“绕原点旋转”的标准公式来执行。
  • 绕原点标准旋转矩阵 R(θ)R(\theta)R(θ)=[cosθsinθ0sinθcosθ0001]R(\theta) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix}
    • 作用:控制物体绕当前的坐标原点逆时针旋转 θ\theta 角(弧度制)。
  • 反向平移回原处矩阵 T(xf,yf)T(x_f, y_f)T(xf,yf)=[10xf01yf001]T(x_f, y_f) = \begin{bmatrix} 1 & 0 & x_f \\ 0 & 1 & y_f \\ 0 & 0 & 1 \end{bmatrix}
    • 作用:这是第一个平移矩阵的逆矩阵。负责在完成原点旋转后,将整个物体连同旋转中心一起还原,向正方向平移 tx=xft_x = x_fty=yft_y = y_f 返回最初的位置。

逐步乘积展开计算过程

  1. 计算右侧两个矩阵相乘 R(θ)T(xf,yf)R(\theta) \cdot T(-x_f, -y_f)R(θ)T(xf,yf)=[cosθsinθ0sinθcosθ0001][10xf01yf001]=[cosθsinθxfcosθ+yfsinθsinθcosθxfsinθyfcosθ001]R(\theta) \cdot T(-x_f, -y_f) = \begin{bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & -x_f \\ 0 & 1 & -y_f \\ 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix} \cos\theta & -\sin\theta & -x_f\cos\theta + y_f\sin\theta \\ \sin\theta & \cos\theta & -x_f\sin\theta - y_f\cos\theta \\ 0 & 0 & 1 \end{bmatrix}
  2. 左乘最左侧的平移矩阵 T(xf,yf)T(x_f, y_f)M=T(xf,yf)[R(θ)T(xf,yf)]=[10xf01yf001][cosθsinθxfcosθ+yfsinθsinθcosθxfsinθyfcosθ001]M = T(x_f, y_f) \cdot \left[ R(\theta) \cdot T(-x_f, -y_f) \right] = \begin{bmatrix} 1 & 0 & x_f \\ 0 & 1 & y_f \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} \cos\theta & -\sin\theta & -x_f\cos\theta + y_f\sin\theta \\ \sin\theta & \cos\theta & -x_f\sin\theta - y_f\cos\theta \\ 0 & 0 & 1 \end{bmatrix} =[cosθsinθxfcosθ+yfsinθ+xfsinθcosθxfsinθyfcosθ+yf001]= \begin{bmatrix} \cos\theta & -\sin\theta & -x_f\cos\theta + y_f\sin\theta + x_f \\ \sin\theta & \cos\theta & -x_f\sin\theta - y_f\cos\theta + y_f \\ 0 & 0 & 1 \end{bmatrix}
  3. 整理矩阵第三列的代数常数项,最终得到任意点旋转复合矩阵通式: M=[cosθsinθxf(1cosθ)+yfsinθsinθcosθyf(1cosθ)xfsinθ001]M = \begin{bmatrix} \cos\theta & -\sin\theta & x_f(1-\cos\theta) + y_f\sin\theta \\ \sin\theta & \cos\theta & y_f(1-\cos\theta) - x_f\sin\theta \\ 0 & 0 & 1 \end{bmatrix}

五、 全局固定坐标模式与活动局部坐标模式 (必考综合计算理论)

  • 全局固定坐标模式 (Global Coordinate Mode / Left Multi-multiplication)

    • 视点:所有的空间变换(平移、旋转、缩放)都是相对于绝对的、静止的“世界坐标系”进行。

    • 数学运算顺序:采用矩阵左乘模式。若变换步骤为:先进行 AA,再进行 BB,则最终的变换矩阵连乘积为:

      M=BAM = B \cdot A

      即新矩阵左乘到累积矩阵链上,最先执行的变换 AA 紧贴在被乘的顶点向量 vv 左侧:Mv=B(Av)M \cdot v = B \cdot (A \cdot v)

  • 活动局部坐标模式 (Local Coordinate Mode / Right Multi-multiplication)

    • 视点:每一次空间变换都是相对于上一次变换后产生的新物体的“活动局部坐标系”进行(即坐标轴会随着变换一起运动)。

    • 数学运算顺序:采用矩阵右乘模式。若变换步骤为:先进行 AA,再进行 BB,则最终的变换矩阵连乘积为:

      M=ABM = A \cdot B

      即新矩阵右乘到累积矩阵链上,先写的变换矩阵反而被置于左侧,顶点的最终计算形式依然是:Mv=A(Bv)M \cdot v = A \cdot (B \cdot v),这在数学上等价于在世界坐标系下先执行 BB,再执行 AA

    Note

    重要考点:OpenGL 中的变换顺序与代码书写顺序

    • OpenGL 采用的是活动局部坐标系模式(右乘)
    • 在 OpenGL 代码中,先调用(写在上面)的变换函数矩阵位于乘积链的左侧,后调用(写在下面)的变换函数矩阵位于乘积链的右侧
    • 因此,变换对几何物体的实际生效顺序为:从下到上(即从右向左)执行。先写的变换后执行,后写的变换先执行。

六、 OpenGL 中的三类变换应用函数

  • glTranslatef(tx, ty, tz):平移当前矩阵。
  • glRotatef(angle, x, y, z):让物体绕指定方向向量 (x,y,z)(x, y, z) 旋转给定的角度 angle
  • glScalef(sx, sy, sz):沿三轴缩放当前矩阵。

第 5 章 三维观察

一、 三维观察的流程

三维物体在最终呈现在显示屏上之前,需要经历如下一系列空间坐标系的映射与变换流程:

graph TD
    MC["模型坐标系 (MC)<br>Model Coordinates"] -->|模型变换| WC["世界坐标系 (WC)<br>World Coordinates"]
    WC -->|观察变换 gluLookAt| VC["观察坐标系 (VC)<br>Viewing Coordinates"]
    VC -->|投影变换 glOrtho/glFrustum| CC["裁剪坐标系 (CC)<br>Clipping Coordinates"]
    CC -->|透视除法 /w| NDC["归一化设备坐标系 (NDC)<br>Normalized Device"]
    NDC -->|视口映射| DC["屏幕设备坐标系 (DC)<br>Device Coordinates"]

二、 投影分类

投影将高维几何体降维投射至低维平面,主要分为平行投影透视投影两大类:

graph TD
    Projection["投影分类"]
    Projection --> Parallel["平行投影 (Parallel)"]
    Projection --> Perspective["透视投影 (Perspective)"]

    Parallel --> Ortho["正投影 (Orthographic)"]
    Parallel --> Oblique["斜投影 (Oblique)"]

    Ortho --> ThreeView["三视图 (Front, Top, Side)"]
    Ortho --> Axonometric["正轴测 (正等测、正二测、正三测)"]

    Oblique --> ObliqueEtc["斜投影 (斜等测/Cavalier、斜二测/Cabinet)"]

    Perspective --> OnePoint["一点透视 (1-Point)"]
    Perspective --> TwoPoint["两点透视 (2-Point)"]
    Perspective --> ThreePoint["三点透视 (3-Point)"]

三、 平行投影

  • 基本特点:投影线互相平行。物体的投影大小不随物体的距离改变而改变,能够保持物体各部分的真实几何比例与平行性。
  • 正投影 (Orthographic Projection):投影线与投影面相互垂直。
    • 三视图:投影面与某个坐标轴垂直(主视图、俯视图、侧视图)。
    • 正轴测:投影面与三个坐标轴倾斜,根据倾斜角不同,坐标轴收缩率不同:
      • 正等测:三个轴的缩放比例完全相等。
      • 正二测:两个轴的缩放比例相等,第三个不等。
      • 正三测:三个轴的缩放比例互不相等。
  • 斜投影 (Oblique Projection):投影线与投影面成倾斜角。
    • 斜等测 (Cavalier):投影线与投影面成 4545^\circ,投影面上的倾斜边长度保持原长不变。
    • 斜二测 (Cabinet):投影线与投影面成约 63.463.4^\circ,投影面上倾斜轴的长度缩减为原长的一半。

四、 透视投影

  • 基本特点:投影线汇聚于单点(视点/投影中心),产生“近大远小”的逼真视觉效果,但无法维持平行的比例。

  • 透视投影矩阵 (以投影平面位于 z=dz=d, 视点在原点为例)

    Mpers=[100001000010001d0]M_{\text{pers}} = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & \frac{1}{d} & 0 \end{bmatrix}

    作用于齐次坐标 [x,y,z,1]T[x, y, z, 1]^T 后得到 [x,y,z,zd]T[x, y, z, \frac{z}{d}]^T,进行透视除法(归一化)后:

    x=xdz,y=ydzx' = \frac{x \cdot d}{z}, \quad y' = \frac{y \cdot d}{z}
  • 灭点 (Vanishing Point) 与主灭点 (Principal Vanishing Point)

    • 灭点:空间中不平行于投影平面的平行直线系在透视投影后相交的汇聚点。
    • 主灭点:空间中平行于世界坐标轴(XX 轴、YY 轴或 ZZ 轴)的直线系产生的灭点。
  • 透视的维数分类与识别判定

    • 一点透视 (One-Point Perspective)
      • 几何特征:投影面(视面)平行于物体的两个主坐标平面(即仅与某一个主轴垂直,例如仅垂直于 ZZ 轴)。
      • 主灭点数量:产生 1 个主灭点。
      • 如何辨别
        • 在投影图上,物体的两组主方向平行棱边(如水平边和垂直边)仍然保持互相平行,不产生交点;
        • 仅有第三个主轴方向(垂直于投影面的深度方向,如 ZZ 轴方向)的平行棱线向远方延伸并汇聚于屏幕上的单一点(即主灭点)。
    • 两点透视 (Two-Point Perspective / 成角透视)
      • 几何特征:投影面平行于物体的某一个主坐标轴(通常平行于铅垂轴 YY 轴),但与另外两个主轴(如 XX 轴和 ZZ 轴)倾斜相交。
      • 主灭点数量:产生 2 个主灭点。
      • 如何辨别
        • 物体的垂直方向棱线仍然保持相互平行且直立,在画面上没有灭点;
        • 物体水平方向的两组平行棱线(如长、宽方向的边)在投影图上分别向左、右下方延伸,汇聚于视平线上的左右两个不同的主灭点。
    • 三点透视 (Three-Point Perspective / 斜透视)
      • 几何特征:投影面与物体的三个主轴都倾斜相交(即不平行于任何一个坐标轴和主平面)。
      • 主灭点数量:产生 3 个主灭点。
      • 如何辨别
        • 物体的长、宽、高三个主轴方向的平行线在投影面上均发生汇聚,没有任何一组主轴棱线在画面上保持平行;
        • 三组平行棱线分别汇聚于三个主灭点,其中两个灭点通常在视平线上(左右分布),第三个灭点则位于视平线之上(仰视)或之下(俯视),常用于表现宏大高耸物体的视觉张力。
一点透视 (1个灭点) 灭点 VP1 X轴和Y轴平行,仅Z轴(深度)汇聚 两点透视 (2个灭点) VP1 VP2 Y轴(高度)平行垂直,X和Z轴汇聚 三点透视 (3个灭点) VP1 VP2 VP3 X、Y、Z轴均不平行,分别汇聚

五、 OpenGL 中的观察与投影函数

  • gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz):设置观察坐标系(相机位置、朝向和头顶方向向量)。
  • glOrtho(left, right, bottom, top, near, far):定义一个对称平行的立方体视锥体裁剪区。
  • glFrustum(left, right, bottom, top, near, far):定义一个透视投影的梯形截头体。
  • gluPerspective(fovy, aspect, zNear, zFar):通过垂直张角 fovy、宽高比 aspect 快速设置对称透视投影。

第 6 章 三维造型

  • 三维造型表示方法对比

    • 线框模型 (Wireframe Model):仅通过顶点和棱边表达物体轮廓。数据简单,但无法表达表面及内部属性,存在二义性漏洞。
    • 表面模型 (Surface Model):利用边线组成的网格面(如多边形面片)来模拟物体的外部边界。支持消隐和着色,但内部不含实体信息。
    • 实体模型 (Solid Model):不仅表达物体的三维空间轮廓,还能识别物体内部和外部空间,可计算体积、重心等物理量。
  • 实体表示的常用造型方法

    • 多边形网格 (Polygon Mesh):最常用的离散边界表示法,便于 GPU 并行硬件加速。
    • 参数曲线/曲面:使用 Bézier 曲面、B 样条(B-Spline)、NURBS 曲面实现极高精度的非均匀几何曲面建模。
    • 空间细分法——八叉树 (Octree)
      • 原理:将一个三维空间立方体不断递归均分为 8 个子块。
      • 属性标志:子块节点状态分为“空 (Empty)”、“满 (Full)”和“混合 (Mixed)”。若为混合节点则继续递归剖分,直至达到精度限制。
      • 应用:适合体素渲染与快速的碰撞检测。
  • 构造方法 (CSG & Sweep)

    • 构造实体几何法 (Constructive Solid Geometry, CSG)
      • 原理:通过基础实体基元(如立方体、球体、圆柱体)经过逻辑布尔集合运算(并 \cup、交 \cap、差 -)来生成复杂模型。
      • 数据结构:表示为一棵二叉树,叶子节点为基本体素,非叶子节点为布尔算子。
    • 扫描表示法 (Sweep Representation)
      • 将一个二维封闭平面图形沿空间的一条轨迹移动而生成三维实体的几何表示法。
      • 包括拉伸扫描(Translational Sweep)和旋转扫描(Rotational Sweep)。
  • 非规则对象的表示方法

    • 分形几何 (Fractal Geometry):用于模拟自然界中具有自相似特征的粗糙几何体,如海岸线、云朵、山脉。
    • 形状语法 (Shape Grammar):利用规则递推的生成文法建立几何模型。
    • 粒子系统 (Particle System):通过管理成千上万个生命周期有限的微小运动点(粒子)来模拟流体、火焰、烟雾、爆炸等无法用规则边界表示的模糊对象。

第 7 章 真实感图形技术

一、 消隐技术 (Hidden Surface Removal, 隐藏面消除)

  • 概念:判定并剔除在当前视点下被其他遮挡物遮挡的不可见线段或面片。
  • 消隐算法分类与对比
    • 按空间操作域分类

      • 对象空间算法 (Object-space algorithms):在三维世界坐标系下比较物体之间的相对几何关系。其算法复杂度与场景中多边形数量的平方相关 O(n2)O(n^2)。适用于精度要求极高的线框消隐。
      • 图像空间算法 (Image-space algorithms):在二维投影平面的像素级别上逐像素判断并比较各个物体的深度值。其算法复杂度通常为 O(np)O(n \cdot p),其中 nn 是多边形数量,pp 为屏幕总像素数。这是现代实时图形学(如 GPU 渲染)中最主流的消隐策略。
    • 常用消隐算法对比表 (考点指导:哪种场景用哪个更好)

      消隐算法空间域最优适用场景主要局限性 / 缺点
      深度缓存 (Z-Buffer)图像空间动态场景、极其复杂的 3D 场景,硬件 GPU 加速的实时渲染。内存开销大(与屏幕分辨率成正比);可能产生深度冲突 (Z-Fighting);无法直接处理半透明混合。
      画家算法 (Painter)图像空间静态场景、多边形数量少且无穿插的场景;软件渲染器中对半透明物体进行从后往前渲染。排序开销大 O(nlogn)O(n \log n);当多边形发生循环重叠或相互穿插时,必须进行昂贵的多边形分割。
      扫描线消隐 (Scan-Line)图像空间将消隐与多边形光栅化紧密结合的场景。能极大减少每像素的深度计算。数据结构设计极度复杂(需要维护活动边表和活动多边形表);难以用现代硬件高并行处理。
      光线投射 (Ray-Casting)图像空间静态、非实时的高质量离线渲染;小体积渲染。对屏幕上每个像素都需要做光线与几何体的求交,计算开销极其庞大。
      背面剔除 (Back-Face)对象空间闭合凸体模型的消隐预处理(可以直接作为第一步初筛剔除约 50% 的多边形)。仅能剔除朝向背对相机的表面,对相互遮挡的凹体或多体场景无效,必须配合其他消隐算法。

1. 深度缓存器 (Z-Buffer) 算法 (图像空间消隐)

  • 核心组成:需要两个与屏幕分辨率大小完全相同的二维数据缓存:
    • 帧缓存 (Frame Buffer / Color Buffer):记录当前像素点的 RGB 颜色。
    • 深度缓存 (Depth Buffer / Z-Buffer):记录当前像素点所关联的最靠近视点的物体深度 ZZ 值。
3D 场景空间 (视点看向物体) Camera (视点) 红三角形 (z=0.3) 蓝三角形 (z=0.6) 遮挡发生处 (红遮挡蓝) 帧缓存与深度缓存渲染结果 1.0 1.0 0.6 1.0 0.3 0.3 0.3 0.6 0.3 0.3 0.3 0.6 1.0 0.3 1.0 1.0 Frame:红 / Depth:0.3 Frame:蓝 / Depth:0.6 重叠区域 Z-Buffer 更新判定: 0.3 < 0.6 (红覆盖蓝)
  • 深度计算的数学原理与公式: 假设空间中多边形所在的平面方程为: Ax+By+Cz+D=0Ax + By + Cz + D = 0 由于深度 zz 是屏幕坐标 (x,y)(x, y) 的函数,则在点 (x,y)(x, y) 处的深度值计算公式为: z(x,y)=Ax+By+DC(C0)z(x, y) = -\frac{Ax + By + D}{C} \quad (C \neq 0)

    • 深度递推/增量计算公式 (扫描线算法核心,计算大题必考): 为了避免在每个像素位置都进行高开销的乘除法,可以利用空间的连续性进行增量计算:
      • 沿着水平扫描线向右移动一个像素(xx+1x \to x + 1z(x+1,y)=A(x+1)+By+DC=z(x,y)ACz(x+1, y) = -\frac{A(x+1) + By + D}{C} = z(x, y) - \frac{A}{C} 因此,水平相邻像素的深度递推公式为: z(x+1,y)=z(x,y)+Δzx,其中 Δzx=ACz(x+1, y) = z(x, y) + \Delta z_x, \quad \text{其中 } \Delta z_x = -\frac{A}{C}
      • 沿着垂直方向向下移动一行扫描线(yy1y \to y - 1: 若在行首的起点 xx 的偏移变化量为 Δx\Delta x(即在活动边表 AET 中跟随边斜率倒数发生的变化),则: z(x+Δx,y1)=z(x,y)+Δzy,其中 Δzy=AΔx+BCz(x+\Delta x, y-1) = z(x, y) + \Delta z_y, \quad \text{其中 } \Delta z_y = \frac{-A \cdot \Delta x + B}{C} 特别地,若 xx 方向无偏移(Δx=0\Delta x = 0,单纯垂直向下移动),则: z(x,y1)=z(x,y)+BCz(x, y-1) = z(x, y) + \frac{B}{C}
  • 算法计算执行过程

    1. 初始化 Z-Buffer 中所有像素的深度值为最大可能值(如 1.01.0),Frame Buffer 初始化为背景色。

    2. 遍历场景中的每一个多边形。

    3. 计算该多边形覆盖的每一个像素点 (x,y)(x, y) 处的深度值 z(x,y)z(x, y)

    4. 如果该点深度值满足:

      z(x,y)<DepthBuffer(x,y)z(x, y) < \text{DepthBuffer}(x, y)

      (假设视点在原点,越小越靠近相机),则更新数据:

      {DepthBuffer(x,y)=z(x,y)FrameBuffer(x,y)=Colorpolygon(x,y)\begin{cases} \text{DepthBuffer}(x, y) = z(x, y) \\ \text{FrameBuffer}(x, y) = \text{Color}_{\text{polygon}}(x, y) \end{cases}
    5. 重复处理,直到全部多边形光栅化完毕。

  • 优点:算法逻辑极简,容易由硬件电路高速实现,不需要对场景内的多边形进行全局深度预排序。


2. 画家算法 (Painter’s Algorithm / 深度排序)

  • 核心步骤
    1. 将场景中所有的多边形按其最远深度(zmaxz_{\max})进行降序排序。
    2. 按照由远及近(Back-to-Front)的顺序依次在帧缓存中绘制每个多边形,较近的图形自动覆盖先前画好的较远的物体。
  • 重叠判决冲突与分割
    • 当两个多边形的深度范围存在重叠、相交、或循环环绕时,画家算法必须对待绘制的表面进行切割分割,使其转化为互不穿插的独立面片,否则将产生错误的遮挡效果。

二、 常用颜色模型

  • RGB 颜色模型 (三基色模型)
    • 红 (Red)、绿 (Green)、蓝 (Blue) 三色叠加。
    • 属于相加/加色混合模型,主要应用在显示器、电视等发光呈像设备上。
  • CMY 颜色模型 (相减模型)
    • 青 (Cyan)、品红 (Magenta)、黄 (Yellow) 三色相减。

    • 属于相减/减色混合模型,主要应用在彩色印刷、绘图仪等反射光呈像的行业。

    • 与 RGB 之间的基础数学转换关系为:

      [CMY]=[111][RGB]\begin{bmatrix} C \\ M \\ Y \end{bmatrix} = \begin{bmatrix} 1 \\ 1 \\ 1 \end{bmatrix} - \begin{bmatrix} R \\ G \\ B \end{bmatrix}

三、 光照模型

1. 局部光照模型 (Phong 反射模型)

局部光照模型只考虑光源与物体表面本身的作用,忽略物体与物体之间的间接反射光(即把间接光照强行简化为一个均匀的环境光分量)。

  • 标准 Phong 反射模型完整公式I=Ie+Ia+Id+Is=E+IambientKa+jIpj[Kd(LjN)+Ks(RjV)n]I = I_e + I_a + I_d + I_s = E + I_{ambient} K_a + \sum_{j} I_{pj} \left[ K_d (L_j \cdot N) + K_s (R_j \cdot V)^n \right]

  • Blinn-Phong 改进反射模型完整公式 (使用半角向量代替反射向量)I=Ie+Ia+Id+Is=E+IambientKa+jIpj[Kd(LjN)+Ks(HjN)n]I = I_e + I_a + I_d + I_s = E + I_{ambient} K_a + \sum_{j} I_{pj} \left[ K_d (L_j \cdot N) + K_s (H_j \cdot N)^n \right]

(注:上述公式中的 j\sum_j 代表对场景中所有发射光的点光源进行光强累加,其中每个分量的详细定义如下)

  • 公式中各分量及物理量含义详解
    • IeI_e(自发光分量 / Emissive Component)
      • 英文全称: Emissive Light / Self-Emission
      • 子公式: Ie=EI_e = E (通常为一个表征自发光强度的常数)
      • 物理意义: 描述物体自身发光的光照表现。它完全不依赖于外部光源和材质的反射属性。如果物体本身并非光源,则此项为 0。
    • IaI_a(环境光分量 / Ambient Component)
      • 英文全称: Ambient Light
      • 子公式: Ia=IambientKaI_a = I_{ambient} \cdot K_a
      • 物理意义: 模拟光线在环境中经过无数次漫反射后,达到完全均匀散射状态的无方向性背景光照。它用于均匀照亮场景中的所有物体(包括背光面),防止背光处出现绝对的纯黑。其中 IambientI_{ambient} 为环境光强,KaK_a 为材质的环境光反射系数。
    • IdI_d(漫反射分量 / Diffuse Component)
      • 英文全称: Diffuse Reflection
      • 子公式: Id=IlightKd(LN)=IlightKdcosθI_d = I_{light} \cdot K_d \cdot (L \cdot N) = I_{light} \cdot K_d \cdot \cos\theta
      • 物理意义: 描述粗糙表面向空间各个方向均匀散射的光照表现,遵循朗伯余弦定律 (Lambert’s Cosine Law)。漫反射的光强与观察者的视线方向无关,仅取决于光源入射角(即光源方向 LL 与表面法线 NN 的夹角 θ\theta 的余弦值)。当夹角 θ>90\theta > 90^\circ(即 LN<0L \cdot N < 0)时,漫反射分量计算结果为 0。其中 IlightI_{light} 为光源光强,KdK_d 为材质的漫反射系数。
    • IsI_s(镜面反射分量 / Specular Component)
      • 英文全称: Specular Reflection
      • 子公式:
        • 标准 Phong 模型: Is=IlightKs(RV)n=IlightKscosnαI_s = I_{light} \cdot K_s \cdot (R \cdot V)^n = I_{light} \cdot K_s \cdot \cos^n\alphaα\alpha 为反射光向量 RR 与视线向量 VV 的夹角)
        • Blinn-Phong 模型: Is=IlightKs(HN)n=IlightKscosnβI_s = I_{light} \cdot K_s \cdot (H \cdot N)^n = I_{light} \cdot K_s \cdot \cos^n\betaβ\beta 为半角向量 HH 与法向量 NN 的夹角)
      • 物理意义: 描述光滑表面对光线的方向性反射,从而在特定观察视角下产生高亮光斑(高光,Specular Highlight)。其中 KsK_s 为镜面反射系数,nn 为高光反射指数(Shininess,控制高光的集中度和粗糙度。nn 越大,表面越光滑,高光光斑越小而越亮)。
    • 关键向量定义(参见下方示意图):
      • NN:物体表面交点处的单位法向量 (Unit Normal Vector)
      • LL:从物体表面交点指向点光源的单位入射光向量 (Unit Light Vector)
      • VV:从物体表面交点指向相机/眼睛的单位视线向量 (Unit View Vector)
      • RR:入射光线 LL 关于法线 NN单位反射向量 (Unit Reflection Vector),计算公式为 R=2(LN)NLR = 2(L \cdot N)N - L
      • HH:入射光向量 LL 和视线向量 VV单位半角向量 (Unit Halfway Vector),计算公式为: H=L+VL+VH = \frac{L + V}{\|L + V\|}
P N L R V H
  • 公式中各分量及物理量含义
    • II:计算出的表面最终合成反射光强度。

    • IaI_a:环境光(Ambient Light)分量。

    • KaK_a:物体表面的环境光反射系数(0Ka10 \le K_a \le 1)。

    • IpI_p(即 IpjI_{pj}):点光源入射光强。

    • KdK_d:漫反射(Diffuse Reflection)系数。

    • LL:从物体表面交点指向点光源的单位方向向量

    • NN:物体表面的单位法向量

    • KsK_s:镜面反射(Specular Reflection)系数。

    • HH:半角向量(Half-way Vector),是入射光向量 LL 和视线向量 VV 的中间平分单位向量,计算方式为:

      H=L+VL+VH = \frac{L + V}{\|L + V\|}
    • nn:高光反射指数(Shininess),控制镜面反射光束的集中程度。nn 越大,表面越光滑,高光区域越小。


2. 环境光、漫反射、镜面反射与自发光的物理机制与判定

  • 环境光 (Ambient Light)

    • 物理机制:模拟光线在场景中经过无数次漫反射后,达到完全均匀散射状态的无方向性背景光照。主要作用是均匀照亮场景中的所有物体表面(包括不受直射的背光面),防止背光处出现绝对的纯黑。
    • 现实实例:阴天室外的散射自然光、拉上厚窗帘的暗室里微弱的背景漫射光。
    • 光照判定:物体表面任何位置、任何法线方向受到的环境光强度都是完全均匀一致的,与光源位置和观察者(眼睛/相机)位置均完全无关
  • 漫反射 (Diffuse Reflection)

    • 物理机制:光线射向粗糙表面时,表面将光线均匀地向空间各个方向反射的物理现象。其反射光强遵循朗伯余弦定律 (Lambert’s Cosine Law),光强仅取决于光源入射方向与物体表面法线的夹角。
    • 现实实例:石膏像、粉笔、粗糙的木头表面、哑光纸张、粘土、红砖墙。
    • 光照判定
      • 反射光的强度与观察者的视线方向无关(从任何视角看去,同一位置的亮度都相同)。
      • 反射光的强度与光源入射方向密切相关(光源垂直入射时最亮,斜射时变暗,入射角 90\ge 90^\circ 时为 0)。
  • 镜面反射 (Specular Reflection)

    • 物理机制:光线射向光滑表面时,表面将光线以接近反射角(入射角 = 反射角)的有方向性反射现象,在反射方向附近观察会看到明亮的高光斑点(Specular Highlight)。
    • 现实实例:平面镜、磨光金属、玻璃球、打蜡抛光的地板、光滑的塑料球。
    • 光照判定
      • 反射光的强度与观察者的视线方向极度相关(只有当视线向量接近反射光向量时才能看到亮斑)。
      • 反射光的强度与光源位置及材质粗糙度(高光指数 nn)相关nn 越大表示表面越光滑,产生的高光斑点越小越亮;nn 较小时高光斑点较大而暗淡)。
  • 自发光 (Self-Emission / Emissive Light)

    • 物理机制:物体自身产生并发射出的光线,不依赖任何外部光源和材质反射属性。
    • 现实实例:点燃的蜡烛、通电的 LED 灯管、发光的电子屏幕、发光的萤光物质。
    • 光照判定:即使在完全黑暗的密闭场景中(无环境光,且外部光源强度均为 0),物体本身依然能够被看见并呈现其自身的颜色,且其亮度不随外部光源的移动或关闭而改变。
  • 如何判断物体表面呈现的是何种反射光(判定方法对比表)

    实验/观察操作环境光 (Ambient) 的表现漫反射 (Diffuse) 的表现镜面反射 (Specular) 的表现自发光 (Self-Emission) 的表现
    移动观察者位置 (视线 VV)物体表面亮度无任何变化物体表面亮度无任何变化物体表面的高光光斑会随之移动或消失物体表面亮度无任何变化
    移动光源位置 (入射光 LL)物体表面亮度无任何变化物体表面的明暗分布/分界线发生改变物体表面的高光光斑会移动并改变亮度物体表面亮度无任何变化(不受光源影响)
    关闭所有外部直射光源物体背光面或暗部依然微弱可见物体表面完全变黑(无直射)物体表面完全没有高光物体依然保持自身亮度发光
    材质参数特征材质环境光系数 KaK_a 占主导材质漫反射系数 KdK_d 远大于镜面反射系数 KsK_s材质镜面反射系数 KsK_s 占主导,且高光指数 nn 较大材质自发光强度常数 E>0E > 0

3. Whitted 整体光照模型

整体光照模型在此基础上引入了光线在场景中不断折射、镜面反射产生的间接光强。

I=IaKa+IpKd(LN)+IpKs(HN)n+ItKt+IsKsI = I_a K_a + I_p K_d (L \cdot N) + I_p K_s (H \cdot N)^n + I_t K_t' + I_s K_s'
  • 参数含义
    • ItI_t:经由其他透明介质折射/透射(Transmission)传入本表面的间接光强;KtK_t' 为对应的折射贡献参数。
    • IsI_s:经由其他镜面反射(Reflection)照进本表面的间接光强;KsK_s' 为对应的镜面间接反射贡献参数。

四、 三种多边形着色 (Shading) 算法

在计算多边形表面各处色彩时,有如下三种插值方案:

Flat Shading (恒定着色) 逐多边形计算颜色,呈块状 Gouraud Shading (顶点插值) 逐顶点计算光照,颜色线性插值 Phong Shading (法向插值) 逐像素插值法向并计算光照
Gouraud Shading (双线性光强插值) V1 (颜色 I1) V2 (颜色 I2) V3 (颜色 I3) 扫描线 A (插值颜色 Ia) B (插值颜色 Ib) 像素 P (插值颜色 Ip) 插值顺序:顶点颜色 → 边界交点颜色 → 内部像素颜色 缺点:无法产生正确镜面高光 (产生“高光失真”) Phong Shading (双线性法向插值) N1 N2 N3 扫描线 Na Nb Np (插值法线) 插值顺序:顶点法线 → 边界交点法线 → 像素法线 Np 优点:在像素 P 处用 Np 计算光照,完美呈现高光

1. Flat Shading (恒定着色)

  • 执行步骤
    • 对于给定的多边形,只取其中一个顶点(或多边形中心点)的法向量,结合光照模型算出一个统一的颜色。整个多边形内所有像素均填充此颜色。
  • 优缺点
    • 优点:计算速度极快,计算开销极低。
    • 缺点:物体表面呈块状拼接,会产生由于生理视觉限制引起的“马赫带 (Mach Band)”边界效应,过渡极不自然。

2. Gouraud Shading (双线性光强插值)

  • 执行步骤

    1. 计算多边形各个顶点的平均法向量。
    2. 根据光照模型,利用顶点的法向量算出各个顶点处的颜色光强值
    3. 在多边形扫描转换光栅化时,利用顶点光强沿扫描线进行双线性插值,算出多边形内部任意像素的颜色。
  • 插值计算公式: 如图,对于扫描线与多边形边相交得到的端点 PP,若多边形两顶点为 A,BA, B,其 yy 坐标分别为 yA,yBy_A, y_B,对应的颜色光强为 IA,IBI_A, I_B

    IP=yByPyByAIA+yPyAyByAIBI_P = \frac{y_B - y_P}{y_B - y_A} I_A + \frac{y_P - y_A}{y_B - y_A} I_B
  • 优缺点

    • 优点:消除了多边形拼接处的颜色突变,物体外观平滑连续。
    • 缺点:无法完美呈现细小的高光区域(镜面反射)。若高光区域处于多边形内部而非顶点上,插值后会被完全抹平。同时在光强导数变化剧烈处仍会有较淡的马赫带。

3. Phong Shading (双线性法向插值)

  • 执行步骤

    1. 计算多边形各个顶点的法向量。
    2. 在扫描转换过程中,不是插值颜色,而是利用顶点的法向量进行双线性插值,求出每个像素网格点对应的法向量
    3. 对每个像素插值出的法向量进行归一化处理
    4. 利用该像素的法向量和光照模型,逐像素重新计算其颜色值。
  • 插值计算公式: 若已知多边形顶点 A,BA, B 的法向量为 NA,NBN_A, N_B,相交处像素点 PP 的法向量 NPN_P 计算为:

    NP=normalize(yByPyByANA+yPyAyByANB)N_P = \text{normalize}\left( \frac{y_B - y_P}{y_B - y_A} N_A + \frac{y_P - y_A}{y_B - y_A} N_B \right)
  • 优缺点

    • 优点:能够极其准确地计算并绘制镜面高光反射,高光区边缘清晰细腻,画面最为逼真。
    • 缺点:因为需要对每一个像素单独计算光照方程,包含大量的求交和法向量归一化开销,计算负荷远大于 Gouraud 着色。

五、 简单透明与阴影的处理方式

  • 简单透明处理

    • 采用插值混色公式。设透明物体的光强为 IobjI_{\text{obj}},其后方背景的折射光强为 IbgI_{\text{bg}},定义透光率系数为 KtK_t0Kt10 \le K_t \le 1),则该像素点的最终合成光强为:

      I=(1Kt)Iobj+KtIbgI = (1 - K_t) I_{\text{obj}} + K_t I_{\text{bg}}
  • 阴影的处理方式

    • 阴影图法 (Shadow Mapping)
      • 第一遍渲染:将视点移至光源处,渲染场景深度图,生成 Z-Buffer(记录哪些点对光源可见)。
      • 第二遍渲染:以正常相机视角渲染,将待绘制点的坐标转换回光源视角,对比其深度。若深度值大于第一遍记录的值,说明被挡住,处于阴影中。
    • 阴影椎体法 (Shadow Volume):根据光源与遮挡物几何体生成伸展的退化几何体(锥体),对射线穿过的次数进行统计(利用模板缓存计数),奇偶法确定是否在阴影内。

六、 光线跟踪算法 (Ray Tracing)

  • 基本思想
    • 从相机(视点)出发,向屏幕上的每一个像素发射一条初始射线(视线/Primary Ray)。
    • 计算射线与场景中物体的最近交点。
    • 在交点处发射次级光线(Secondary Rays):
      • 反射光线:顺着镜面反射方向追踪,计算周围物体的反射贡献。
      • 折射光线:若物体为半透明,顺着折射方向穿过物体继续追踪。
      • 阴影测试光线 (Shadow Ray):从交点连线指向各点光源。若途中被遮挡,则该光源对该点无直接贡献(该点处于阴影中)。
  • 跟踪的终止条件
    1. 射线没有碰撞到场景中的任何物体(逃逸出场景边界,射入背景)。
    2. 射线的反射/折射次数达到了预设的最大递归追踪深度(Depth Limit)。
    3. 射线累积的能量/强度贡献值已经衰减到了指定的阈值下限(衰减极小,可忽略不计)。

七、 纹理映射 (Texture Mapping)

  • 概念:将二维的图样(图像)粘贴到三维物体的几何表面上,以在不增加物体网格面数(几何复杂度)的前提下,实现极高细节的复杂图样外观效果。
  • 纹理映射的分类
    1. 颜色纹理映射 (Color Texture Mapping):最基本的方式。将二维图片的 RGB 像素值映射为物体的漫反射系数,改变表面外观颜色。
    2. 凹凸映射 (Bump Mapping / Normal Mapping):不改变几何体表面高度,而是利用纹理扰动多边形表面的法向量方向,从而改变局部光照明暗,创造假的小凹凸、划痕等立体质感。
    3. 环境映射 (Environment Mapping / Reflection Mapping):将周围环境绘制在一张立方体或球形贴图上。计算物体的反射光线去采样贴图,用以模拟高反射率物体(如镜子、光滑金属)的镜面反射场景。
    4. 三维/空间纹理 (Solid Texture):将纹理定义为三维空间坐标 (x,y,z)(x, y, z) 的函数(如木纹、大理石纹),物体任意位置的颜色直接由其空间三维坐标决定,适合雕刻实体模型。

OpenGL 专项高频考点辨析 (选择/程序设计题必考)

在期末考试中,通常包含 5 道关于 OpenGL 核心 API 与矩阵变换的代码分析选择题(占 10 分)。以下为核心高频考点解析:

一、 复合变换的代码书写顺序与顶点实际作用顺序

  • 核心理论:活动局部坐标系模式

    • OpenGL 固定管线在内部采用的是活动局部坐标系模式,矩阵运算采用右乘模式
    • 每一个矩阵变换函数都会将其相应的矩阵右乘到当前的矩阵堆栈顶部。
  • 书写与生效规律

    • 代码书写顺序(从上到下):

      glLoadIdentity();
      glRotatef(30.0f, 0.0f, 0.0f, 1.0f);   // 旋转 A
      glTranslatef(2.0f, 0.0f, 0.0f);      // 平移 B
      glScalef(1.5f, 1.5f, 1.0f);          // 缩放 C
      drawPolygon();                       // 绘制几何体
    • 矩阵相乘顺序(从左到右):

      M=IRATBSCM = I \cdot R_A \cdot T_B \cdot S_C
    • 几何物体顶点的实际生效顺序从下到上(从右向左)。 也就是:先进行缩放 C \to 再进行平移 B \to 最后进行旋转 A

    Warning

    避坑警示:考试选择题往往会给出一段 OpenGL 几何变换的顺序代码,问其等价的几何操作流程。请记住核心规则:代码里写在下方的变换最先作用于物体顶点,写在最上方的变换最后作用。


二、 三维观察与投影核心函数解析

在 OpenGL 渲染流程中,视图与投影变换是通过以下几个关键函数来定义视景体(Viewing Volume)的:

1. gluLookAt() —— 设置相机视点变换

  • 函数原型
    void gluLookAt(
        GLdouble eyex, GLdouble eyey, GLdouble eyez,        // 视点/相机位置 (Eye)
        GLdouble centerx, GLdouble centery, GLdouble centerz, // 观察参考点/焦点 (Center)
        GLdouble upx, GLdouble upy, GLdouble upz             // 相机向上向量 (Up)
    );
  • 核心作用
    • 定义相机(视点)在三维世界空间的位置和指向方向,把世界坐标系 (WC) 中的物体坐标转换到观察参考坐标系 (VC)。
    • up 向量决定了相机的倾斜角度(如 (0,1,0)(0,1,0) 表示相机头顶朝向正 YY 轴)。

2. glOrtho() —— 设置正交(平行)投影

  • 函数原型
    void glOrtho(
        GLdouble left, GLdouble right,    // 左右截面 X 坐标限制
        GLdouble bottom, GLdouble top,    // 下上截面 Y 坐标限制
        GLdouble nearVal, GLdouble farVal // 近远截面 Z 距离限制
    );
  • 核心作用
    • 定义一个正交(平行)投影的六面体视景体。
    • 特点:投影线平行,不产生近大远小的透视收缩效果。常用于二维地图、CAD 制图或 UI 界面的绘制。

3. gluPerspective()glFrustum() —— 设置透视投影

  • gluPerspective()(通过张角与比例定义):
    • 函数原型
      void gluPerspective(
          GLdouble fovy,   // 垂直视角(Y方向张角,单位:度)
          GLdouble aspect, // 宽高比(视口的宽除以高)
          GLdouble zNear,  // 近裁剪面到相机的距离(必须为正数,且 > 0)
          GLdouble zFar    // 远裁剪面到相机的距离(必须为正数,且 > 0)
      );
    • 应用特点:符合人类日常视觉习惯(近大远小),定义了一个对称的四棱台截头体视景体,最易于设置。
  • glFrustum()(通过截面坐标定义):
    • 函数原型
      void glFrustum(
          GLdouble left, GLdouble right,
          GLdouble bottom, GLdouble top,
          GLdouble nearVal, GLdouble farVal
      );
    • 应用特点:通过直接指定近裁剪面上各边界的坐标来定义视景体,支持设置非对称的斜视透视投影截头体。

4. glViewport() —— 设置视口映射

  • 函数原型
    void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
  • 核心作用
    • 决定了归一化设备坐标 (NDC) 的 [1,1][-1, 1] 范围最终如何映射到屏幕窗口上的物理像素区域(以窗口左下角为原点 (x,y)(x, y),定义渲染区域的宽和高)。
Profile Image of the Author
Sonder
好想要技术
这是公告标题
这只是一个公告
分类
标签
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.16.7
文章许可
CC BY-NC-SA 4.0
1
计算机图形学期末复习提纲与考点详析 (2026_review_Sonder9999)
2
考试基本信息
一、 考试范围与重点章节
二、 题型分布与分值
3
第 1 章 绪论
4
第 2 章 图形系统
5
第 3 章 二维基本图形光栅化与裁剪
一、 直线段与圆弧光栅化算法
1. DDA (数值微分) 画线法
2. Bresenham 画线算法
3. 中点画线法
4. 中点画圆法
二、 区域填充算法
1. 包含性测试 (In-Out Test)
2. 多边形扫描转换算法 (扫描线算法)
3. 种子填充算法
三、 字符表示与处理
四、 走样与反走样 (Aliasing & Anti-aliasing)
五、 裁剪算法
1. Cohen-Sutherland 编码裁剪算法 (直线的线段裁剪)
2. Liang-Barsky 裁剪算法 (参数化线段裁剪)
3. Sutherland-Hodgeman 算法 (多边形裁剪)
4. Weiler-Atherton 多边形裁剪算法
5. 裁剪算法特性横向对比
6
第 4 章 图形几何变换
一、 齐次坐标 (Homogeneous Coordinates)
二、 几何变换通式及其分块含义
1. 二维齐次变换通式 (3×33 \times 33×3 矩阵)
2. 三维齐次变换通式 (4×44 \times 44×4 矩阵)
三、 基本变换矩阵 (2D 与 3D 矩阵全集)
1. 二维基本齐次变换矩阵 (3×33 \times 33×3)
2. 三维基本齐次变换矩阵 (4×44 \times 44×4)
四、 复合变换 (Composite Transformations)
五、 全局固定坐标模式与活动局部坐标模式 (必考综合计算理论)
六、 OpenGL 中的三类变换应用函数
7
第 5 章 三维观察
一、 三维观察的流程
二、 投影分类
三、 平行投影
四、 透视投影
五、 OpenGL 中的观察与投影函数
8
第 6 章 三维造型
9
第 7 章 真实感图形技术
一、 消隐技术 (Hidden Surface Removal, 隐藏面消除)
1. 深度缓存器 (Z-Buffer) 算法 (图像空间消隐)
2. 画家算法 (Painter’s Algorithm / 深度排序)
二、 常用颜色模型
三、 光照模型
1. 局部光照模型 (Phong 反射模型)
2. 环境光、漫反射、镜面反射与自发光的物理机制与判定
3. Whitted 整体光照模型
四、 三种多边形着色 (Shading) 算法
1. Flat Shading (恒定着色)
2. Gouraud Shading (双线性光强插值)
3. Phong Shading (双线性法向插值)
五、 简单透明与阴影的处理方式
六、 光线跟踪算法 (Ray Tracing)
七、 纹理映射 (Texture Mapping)
10
OpenGL 专项高频考点辨析 (选择/程序设计题必考)
一、 复合变换的代码书写顺序与顶点实际作用顺序
二、 三维观察与投影核心函数解析
1. gluLookAt() —— 设置相机视点变换
2. glOrtho() —— 设置正交(平行)投影
3. gluPerspective() 与 glFrustum() —— 设置透视投影
4. glViewport() —— 设置视口映射
文章目录
1
计算机图形学期末复习提纲与考点详析 (2026_review_Sonder9999)
2
考试基本信息
一、 考试范围与重点章节
二、 题型分布与分值
3
第 1 章 绪论
4
第 2 章 图形系统
5
第 3 章 二维基本图形光栅化与裁剪
一、 直线段与圆弧光栅化算法
1. DDA (数值微分) 画线法
2. Bresenham 画线算法
3. 中点画线法
4. 中点画圆法
二、 区域填充算法
1. 包含性测试 (In-Out Test)
2. 多边形扫描转换算法 (扫描线算法)
3. 种子填充算法
三、 字符表示与处理
四、 走样与反走样 (Aliasing & Anti-aliasing)
五、 裁剪算法
1. Cohen-Sutherland 编码裁剪算法 (直线的线段裁剪)
2. Liang-Barsky 裁剪算法 (参数化线段裁剪)
3. Sutherland-Hodgeman 算法 (多边形裁剪)
4. Weiler-Atherton 多边形裁剪算法
5. 裁剪算法特性横向对比
6
第 4 章 图形几何变换
一、 齐次坐标 (Homogeneous Coordinates)
二、 几何变换通式及其分块含义
1. 二维齐次变换通式 (3×33 \times 33×3 矩阵)
2. 三维齐次变换通式 (4×44 \times 44×4 矩阵)
三、 基本变换矩阵 (2D 与 3D 矩阵全集)
1. 二维基本齐次变换矩阵 (3×33 \times 33×3)
2. 三维基本齐次变换矩阵 (4×44 \times 44×4)
四、 复合变换 (Composite Transformations)
五、 全局固定坐标模式与活动局部坐标模式 (必考综合计算理论)
六、 OpenGL 中的三类变换应用函数
7
第 5 章 三维观察
一、 三维观察的流程
二、 投影分类
三、 平行投影
四、 透视投影
五、 OpenGL 中的观察与投影函数
8
第 6 章 三维造型
9
第 7 章 真实感图形技术
一、 消隐技术 (Hidden Surface Removal, 隐藏面消除)
1. 深度缓存器 (Z-Buffer) 算法 (图像空间消隐)
2. 画家算法 (Painter’s Algorithm / 深度排序)
二、 常用颜色模型
三、 光照模型
1. 局部光照模型 (Phong 反射模型)
2. 环境光、漫反射、镜面反射与自发光的物理机制与判定
3. Whitted 整体光照模型
四、 三种多边形着色 (Shading) 算法
1. Flat Shading (恒定着色)
2. Gouraud Shading (双线性光强插值)
3. Phong Shading (双线性法向插值)
五、 简单透明与阴影的处理方式
六、 光线跟踪算法 (Ray Tracing)
七、 纹理映射 (Texture Mapping)
10
OpenGL 专项高频考点辨析 (选择/程序设计题必考)
一、 复合变换的代码书写顺序与顶点实际作用顺序
二、 三维观察与投影核心函数解析
1. gluLookAt() —— 设置相机视点变换
2. glOrtho() —— 设置正交(平行)投影
3. gluPerspective() 与 glFrustum() —— 设置透视投影
4. glViewport() —— 设置视口映射