光栅化管线
图形管线(Graphics Pipeline)把 3D 模型变成屏幕上的像素——顶点处理→光栅化→片元处理→输出合并。GPU 就是专门加速这条管线的硬件
🏭 “3D 模型变屏幕像素”——工厂流水线
你有一个 3D 房间的模型——椅子、桌子、墙壁、灯光。你想在 2D 屏幕上显示”从人的视角看这个房间”。
这个过程就像工厂流水线:原材料(3D 顶点)从一端进入,经过一系列工序(各阶段),最终产出成品(像素的颜色)。
这个流水线就叫 图形管线(Graphics Pipeline)——也叫光栅化管线。GPU 就是专门加速这条管线的”工厂”。
📋 管线的四个阶段
顶点数据 片元着色器
(3D 模型) (算每个像素颜色)
↓ ↓
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐
│ 顶点着色器 │→│ 光栅化 │→│ 片元着色器 │→│ 输出合并 │→ 屏幕
└─────────┘ └──────────┘ └─────────┘ └──────────┘
↑ ↑
可编程(GLSL) 可编程(GLSL)
① 顶点着色器(Vertex Shader)——每个顶点算一次
输入:3D 顶点坐标(模型定义时确定的) 输出:裁剪坐标(经过 MVP 变换后)
// 顶点着色器——每个顶点执行一次
#version 330 core
layout (location = 0) in vec3 aPos; // 输入的顶点坐标
layout (location = 1) in vec3 aColor; // 顶点颜色
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 vertexColor; // 传递给片元着色器
void main() {
// MVP 变换:模型→视图→投影
gl_Position = projection * view * model * vec4(aPos, 1.0);
vertexColor = aColor;
}
💡 如果一个 3D 模型有 10 万个三角形(30 万个顶点)——顶点着色器要执行 30 万次。但 GPU 有几千个核心,并行完成。
② 光栅化(Rasterization)——三角形变成像素
输入:三个顶点的裁剪坐标(一个三角形) 输出:覆盖的所有像素位置(片元)
光栅化阶段是固定功能的——不能编程,由 GPU 硬件直接完成。
三个顶点定义了一个三角形:
A(100, 50)
B(200, 150)
C(50, 180)
光栅化:确定"哪些像素在这个三角形内部"
┌──┬──┬──┬──┬──┐
│ │ │ │ │ │
├──┼──┼──┼──┼──┤
│ │● │● │● │ │ ● = 被三角形覆盖的像素
├──┼──┼──┼──┼──┤
│ │● │● │● │ │
├──┼──┼──┼──┼──┤
│ │ │ │ │ │
└──┴──┴──┴──┴──┘
每个覆盖的像素(叫”片元”)都有自己的位置——插值得到的(不是单个顶点了)。
③ 片元着色器(Fragment Shader)——每个像素算一次
输入:插值后的片元数据(位置、法线、纹理坐标) 输出:像素的颜色
片元着色器可以编程——图形程序员在这里实现光照、纹理、阴影等效果。
// 片元着色器——每个覆盖的像素执行一次
#version 330 core
in vec3 vertexColor; // 从顶点着色器插值得到的颜色
in vec2 texCoord; // 纹理坐标
uniform sampler2D texture1; // 纹理
uniform vec3 lightPos; // 光源位置
out vec4 FragColor; // 最终颜色
void main() {
// 从纹理采样
vec4 texColor = texture(texture1, texCoord);
// 和顶点颜色混合
FragColor = texColor * vec4(vertexColor, 1.0);
}
💡 1920×1080 分辨率,渲染一个复杂的 3D 场景——片元着色器可能要执行数百万次。这就是为什么 GPU 有”数千个核心”——它们就是为了同时处理大量像素。
④ 输出合并(Output Merge)——谁的像素在前面?
最后一步决定:多个物体在同一个像素位置重叠时,谁在前面显示?
深度测试:近的挡住远的 → 前面物体的像素覆盖后面
模板测试:按模板裁剪 → 类似"用模板切出形状"
混合:半透明物体 → 前后颜色混合
🔧 可编程 vs 固定功能
| 阶段 | 可编程? | 做什么 |
|---|---|---|
| 顶点着色器 | ✅ 可编程 | 变换顶点、传递数据 |
| 细分/几何着色器 | ✅ 可编程 | 添加/修改几何 |
| 光栅化 | ❌ 固定 | 三角形→像素 |
| 片元着色器 | ✅ 可编程 | 算颜色(光照/纹理) |
| 深度/模板测试 | ⚠️ 可配置 | 可见性判断 |
这是现代 GPU 的关键特点:管线的两端可编程,中间固定。——你可以自由控制”怎么算顶点”和”怎么算颜色”,但”三角形转像素”这个步骤是硬件固定的(因为必须快)。
📝 小结
| 阶段 | 输入→输出 | 执行次数 |
|---|---|---|
| 顶点着色器 | 3D 顶点 → 裁剪坐标 | 每个顶点一次 |
| 光栅化 | 三角形 → 片元(像素候选) | 硬件自动 |
| 片元着色器 | 片元 → 颜色 | 每个像素一次 |
| 输出合并 | 深度测试/混合 | 每个像素一次 |
🎯 小练习:为什么光栅化是”固定功能”而不是可编程的?如果把它做成可编程的,会有什么问题?(提示:想想”性能”和”硬件的专业分工”)
为什么先学这个? 了解管线的整体结构后,深入各个阶段——三角形光栅化与深度缓冲。