渲染管线
GPU 渲染的完整流程——顶点着色器 → 光栅化 → 片段着色器 → 后处理。
概念
渲染管线 (Rendering Pipeline) 是将 3D 场景数据 (顶点、纹理、光照) 转换为 2D 屏幕像素的完整流程。现代 GPU 的管线是高度并行的——每个顶点和每个像素 (片段) 都由独立的着色器程序处理。理解渲染管线相当于理解”如何高效利用 GPU 的大规模并行能力”。
核心组件
| 组件 | 职责 | 硬件实现 |
|---|---|---|
| 顶点着色器 (Vertex Shader) | 将模型空间的顶点变换到裁剪空间 | 每个顶点并行执行 |
| 曲面细分 (Tessellation) | 动态细分曲面增加几何细节 | 可选, 硬件曲面细分单元 |
| 几何着色器 (Geometry Shader) | 生成/销毁图元 (点、线、三角形) | 可选 |
| 光栅化 (Rasterizer) | 将图元转化为屏幕像素 (片段) | 固定功能硬件 |
| 片段着色器 (Fragment Shader) | 计算每个片段的颜色 | 每个片段并行执行 |
| 深度/模板测试 (Depth/Stencil) | 隐藏面消除 (Z-buffer) | 固定功能硬件 |
| 后处理 (Post-Process) | 全屏特效: bloom, HDR tone mapping, SSAO | 片段着色器实现 |
渲染管线全流程
mermaid
graph TD
VBO["顶点缓冲区 (VBO)<br/>positions, normals, UVs"] --> VS["顶点着色器<br/>MVP 变换: model→world→view→clip"]
VS --> TESS["曲面细分<br/>动态几何细节"]
TESS --> GS["几何着色器<br/>图元操作"]
GS --> CLIP["裁剪 + 透视除法<br/>clip → NDC → window"]
CLIP --> RAST["光栅化<br/>三角形遍历, 生成片段"]
RAST --> FS["片段着色器<br/>纹理采样 + 光照计算"]
FS --> DS["深度/模板测试<br/>Z-buffer 隐藏面消除"]
DS --> BLEND["混合<br/>半透明, alpha blending"]
BLEND --> FB["帧缓冲 (Framebuffer)"]
FB --> POST["后处理<br/>bloom, tone mapping, SSAO"]
POST --> SWAP["Swapchain<br/>呈现到屏幕"]
style VS fill:#9cf,stroke:#333
style FS fill:#fc9,stroke:#333
style RAST fill:#f99,stroke:#333
GPU 资源生命周期
GPU 资源的典型生命周期:
纹理 (Texture):
1. 从磁盘加载图像 → 解压缩 → CPU 内存中的像素数组
2. glCreateTexture / vkCreateImage → 在 GPU 显存中分配
3. glTexImage2D / vkCmdCopyBufferToImage → 上传到 GPU
4. 绑定到纹理单元 / descriptor set → 片段着色器采样
5. 不再使用时释放 (glDeleteTexture / vkDestroyImage)
网格 (Mesh):
1. 顶点数据 (positions, normals, UVs, tangents) → CPU 内存
2. 创建 VBO (Vertex Buffer Object) → GPU 显存
3. 创建 IBO (Index Buffer Object) → 可选索引缓冲
4. 绑定 VAO (Vertex Array Object) → 描述顶点布局
5. glDrawElements / vkCmdDrawIndexed → 提交绘制
着色器 (Shader):
1. GLSL/HLSL 源码 → 编译为 SPIR-V 字节码
2. 上传到 GPU, 编译为 GPU 特定指令
3. 绑定到渲染管线的各个阶段
场景图与视锥剔除
场景图 (Scene Graph):
World
├── Room
│ ├── Table
│ │ ├── Leg1 (Mesh: "leg.obj", Transform: translate(+1,0,+1))
│ │ ├── Leg2 (Mesh: "leg.obj", Transform: translate(-1,0,+1))
│ │ ├── Leg3 (Mesh: "leg.obj", Transform: translate(+1,0,-1))
│ │ ├── Leg4 (Mesh: "leg.obj", Transform: translate(-1,0,-1))
│ │ └── Top (Mesh: "tabletop.obj")
│ └── Chair (子节点 ...)
└── Outdoor
└── Tree (子节点 ...)
视锥剔除 (Frustum Culling):
对于每个场景节点:
计算节点的包围盒 (AABB / Bounding Sphere)
6 个裁剪平面 (左、右、上、下、近、远)
IF 包围盒在视锥外:
SKIP → 该节点及其子树都不渲染
ELIF 包围盒与视锥相交或完全在内部:
递归检查子节点
// 加速结构: BVH、八叉树、四叉树优化剔除查询