渲染管线

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、八叉树、四叉树优化剔除查询