Vertex_ModelSpace ⬇️ Model Matrix Vertex_WorldSpace ⬇️ View Matrix Vertex_CameraSpace ⬇️ Projection Matrix Vertex_ClipSpace ⬇️ /w(齐次除法) Vertex_NDC([-1, 1]) ⬇️ Viewport Mapping Screen Coordinate(屏幕像素坐标)

🧱 三种坐标系统 & 变换矩阵

变换阶段从哪里 → 到哪里矩阵名称常用 API 示例
模型变换模型坐标 → 世界坐标Model Matrixglm::translate/rotate/scale()
视图变换世界坐标 → 摄像机坐标View Matrixglm::lookAt()
投影变换摄像机坐标 → 屏幕空间(NDC)Projection Matrixglm::perspective() or glm::ortho()

🧩 模型变换(Model Matrix)

目的: 决定物体世界中的位置、朝向、大小。

常见操作:

  • 平移(Translate)

  • 旋转(Rotate)

  • 缩放(Scale)

矩阵结构:

Model = Translate × Rotate × Scale

示例:
一个小球本来在原点,要移动到 (5, 2, 0),旋转 45°,放大两倍,就要使用对应的模型矩阵进行变换。


👁️‍🗨️ 视图变换(View Matrix)

目的: 把世界场景“搬到”摄像机前,便于观察。
也可以理解为“模拟摄像机的位置与朝向”。

设置方法: glm::lookAt(eye, center, up)

参数含义
eye摄像机位置
center摄像机看向的目标点
up摄像机头顶的方向(通常是 Y 轴)

本质: 将整个场景进行一个逆变换(移动 & 旋转),以配合固定在原点的摄像机观察。


🎥 投影变换(Projection Matrix)

目的: 将摄像机坐标转换为屏幕上显示的二维图像,实现“透视”或“正交”效果。

类型效果使用函数
透视投影(Perspective)远小近大,真实世界效果glm::perspective(fov, aspect, near, far)
正交投影(Orthographic)物体无远近缩放,常用于UIglm::ortho(left, right, bottom, top, near, far)

透视投影效果:

  • 摄像机看到的是一个“视锥体”

  • 投影矩阵负责将这个锥体压缩成单位立方体(NDC)

🧮 1. Clip Space → NDC:齐次除法 (/w)

变换前:

顶点经过 MVP(Model × View × Projection)矩阵变换后,处于Clip Space,坐标是四维齐次坐标:
v_clip = (x, y, z, w)

变换后:

要得到三维的标准设备坐标(NDC),必须对前三个分量除以 w

v_ndc = (x / w, y / w, z / w)  

为什么这么做?

  • w 编码了透视信息;齐次除法体现“远小近大”的效果;

  • 透视投影会让远处的物体 z/w 更接近 -1,近处更接近 +1。

结果:

  • 得到的 NDC 坐标范围都是 [-1, 1]

    • X ∈ [-1, 1]:从左到右

    • Y ∈ [-1, 1]:从下到上

    • Z ∈ [-1, 1]:从近到远(用于深度测试)


🧭 2. NDC → Viewport Mapping(视口映射)

NDC 是 OpenGL 逻辑坐标,还要转换成 实际屏幕坐标(像素),才可以显示在屏幕上。

映射公式(以 OpenGL 为例):

screen_x = (ndc_x + 1) / 2 * viewport_width
screen_y = (ndc_y + 1) / 2 * viewport_height
  • 把 NDC 的 [-1,1] 映射为 [0, viewport size]

  • NDC 的中心点 (0,0) 映射为屏幕中心;

  • 上下、左右变为屏幕坐标的像素值。

示例:

  • NDC 坐标为 (-1, -1) → 映射为左下角 (0, 0)

  • NDC 坐标为 (1, 1) → 映射为右上角 (屏宽, 屏高)


🧾 3. Z值处理:深度缓冲与 Z-Buffer

  • z ∈ [-1, 1](OpenGL)或 [0, 1](DirectX)范围将被映射到深度缓冲;

  • 用于判断片元遮挡关系(Depth Test);

  • 近的物体覆盖远的物体。