渲染管线全景 — 从顶点到像素的旅程

欢迎来到着色器学习之旅的第一课。在你能写出第一个着色器之前,最重要的是先理解渲染管线的完整图景——一个 3D 物体是如何一步步变成屏幕上 2D 像素的。

🎯 本课目标 理解渲染管线的四个阶段、物体属性的基本概念、坐标空间的变换过程,以及 Forward 和 Deferred 两种渲染路径的区别。

1. 什么是渲染管线?

想象一个物体(比如一个球体)从你的 Unity 场景出发,“旅行”到你的显示器屏幕上。这条路径上的每一站都执行特定的计算——这就是渲染管线 (Render Pipeline)

💡 核心思想 渲染管线 = 一系列有序的阶段,将 3D 场景数据转化为 2D 图像。每个阶段处理前一阶段的输出,并传递给下一阶段。

在实时图形学中,渲染管线由四个主要阶段组成:

渲染管线流程: 应用阶段 (Application) → 几何处理 (Geometry) → 光栅化 (Rasterization) → 像素处理 (Pixel)

这四阶段是所有实时渲染管线的通用骨架——无论是 Unity 的 Built-in RP、URP、HDRP,还是 Godot、Unreal Engine,都遵循这个基本模型。

2. 阶段一:应用阶段 (Application Stage)

执行位置CPU
主要任务场景数据准备、碰撞检测、输入处理、视锥体裁剪
输出渲染图元(三角形、线段、顶点)

应用阶段在 CPU 上运行。它负责读取存储在内存中的数据(场景中的物体、灯光、摄像机位置等),进行粗粒度的可见性判断(视锥体裁剪 Frustum Culling——只保留摄像机视锥体内的物体),然后将需要渲染的图元数据发送到 GPU。

为什么这个阶段在 CPU 而不是 GPU 上执行?

—— 因为 CPU 擅长串行逻辑判断(如碰撞检测、场景管理),而 GPU 擅长并行数值计算。把场景管理交给 CPU、把大量顶点/像素计算交给 GPU,各司其职。

3. 阶段二:几何处理阶段 (Geometry Processing)

执行位置GPU
子阶段顶点着色 → 投影 → 裁剪 → 屏幕映射
主要任务顶点变换、坐标空间转换、裁剪不可见部分
关键程序顶点着色器 (Vertex Shader) — 我们最早接触的可编程阶段

3.1 顶点着色器 (Vertex Shader)

这是着色器程序员可以控制的第一个阶段。顶点着色器对每个输入顶点执行一次操作,主要做两件事:

  1. 计算顶点的位置(将顶点从 3D 空间变换到屏幕空间)
  2. 传递顶点的其他属性(法线、UV、颜色等)给下一阶段

3.2 坐标空间的变换 — 四重跳转

理解坐标空间变换是学习着色器的第一个认知门槛。一个顶点从 3D 场景到 2D 屏幕,经历了四次坐标空间转换:

坐标空间变换链:

  • 物体空间 → [模型矩阵 M] → 世界空间 (相对于场景原点)
  • 世界空间 → [视图矩阵 V] → 观察空间 (相对于摄像机)
  • 观察空间 → [投影矩阵 P] → 裁剪空间 (视锥体投影)
  • 裁剪空间 → [视口变换] → 屏幕坐标 (2D 像素位置)

Abstract

🔑 关键矩阵:UNITY_MATRIX_MVP 这是 Unity 中最重要的内置矩阵之一。 MVP = P × V × M 它的作用是将顶点一次性 从物体空间变换到裁剪空间。 注:在 HLSL 中通常写作 UnityObjectToClipPos(v.vertex)

Note

空间含义类比
物体空间 (Object)顶点相对于物体中心的坐标”我站在房间的哪个位置”
世界空间 (World)物体在场景中的位置”我在这座城市的哪里”
观察空间 (View)相对于摄像机的坐标”我在你眼中的位置”
裁剪空间 (Clip)透视投影后的标准化坐标”照片上的位置”

3.3 裁剪与屏幕映射

经过投影后,裁减 (Clipping) 会丢弃视锥体外的部分(比如半个球体在画面外,那半个就被丢弃了),然后屏幕映射 (Screen Mapping) 将 3D 坐标转换为 2D 窗口坐标。

4. 阶段三:光栅化阶段 (Rasterization)

执行位置GPU(固定功能单元)
主要任务将图元分解为像素(片元)
输出片元 (Fragments) — 潜在的像素

光栅化是从 3D 到 2D 的关键一步。经过几何处理后我们有了屏幕上的三角形,光栅化就是找出这些三角形覆盖了哪些像素。

它包含两个子过程:

  1. 三角形设置 (Triangle Setup) — 计算三角形的边界方程
  2. 三角形遍历 (Triangle Traversal) — 列出三角形覆盖的所有像素

💡 理解片元 (Fragment) 片元是光栅化产生的"候选像素"。一个片元包含该位置的颜色、深度等信息,但可能被遮挡而不会最终显示。简单理解:片元 = 待决定的像素

5. 阶段四:像素处理阶段 (Pixel Processing)

执行位置GPU(可编程阶段)
关键程序片元/像素着色器 (Fragment/Pixel Shader)
主要任务计算每个像素的最终颜色
输出颜色缓冲区 (Color Buffer)

这是着色器程序员可以控制的第二个阶段(也是最后一个)。像素着色器对每个片元执行一次,计算其在屏幕上的最终颜色。

在这个阶段,顶点着色器输出的顶点属性(位置、法线、UV 等)已经被插值 (Interpolated) 到每个像素上。也就是说,三个顶点的法线经过插值后,三角形内部的每个像素都有了自己的”平滑过渡的法线”。

🎬 顶点着色器 vs 像素着色器

  • 顶点着色器:逐顶点执行,关注位置变换 → “每个顶点去哪”
  • 像素着色器:逐像素执行,关注颜色计算 → “每个像素什么颜色”

6. 物体的基本属性

在开始写着色器之前,还需要了解一个 3D 物体携带哪些基本属性。着色器可以访问所有这些属性并加以利用。

属性类型在着色器中的语义说明
顶点 (Vertices)float3/float4: POSITION[n]定义物体表面的点,是物体的”骨架”
法线 (Normals)float3: NORMAL垂直于表面的向量,决定光照响应
切线 (Tangents)float4: TANGENT沿纹理 U 方向的向量,用于法线贴图
UV 坐标float2: TEXCOORD[n]纹理映射坐标,值域 [0, 1]
顶点颜色float4: COLOR每个顶点存储的颜色,默认白色 (1,1,1,1)

法线和切线有什么不同?

法线垂直于表面,决定”面朝哪”(用于光照计算)。切线沿着纹理的 U 方向,法线和切线的叉积得到副法线 (Binormal),三者构成 TBN 矩阵——这是后话,第 10 课会详细讲。

7. 渲染路径:Forward vs Deferred

渲染管线内部有不同的”路径”来处理光照,最常用的是两种:

Forward Rendering(前向渲染)

每个物体在每个光源下都走一遍完整的渲染管线。

  • 优点:兼容性好,支持 MSAA
  • 缺点:光源越多,Draw Call 越多
  • 公式:Draw Calls ≈ 物体数 × (1 + 光源数)
  • Unity 默认路径,URP 只支持 Forward

Deferred Shading(延迟渲染)

将几何和光照分离,先将几何信息存入 G-Buffer,再统一计算光照。

  • 优点:大量光源时性能好
  • 缺点:不支持 MSAA,硬件兼容性要求高
  • HDRP 支持此路径

⚠️ 关于 URP 的注意 Unity 的 Universal RP 仅支持 Forward 渲染路径。但本书也包含 URP 兼容的处理方法(第 4.0.6 节),我们后续会涉及。

8. 本课总结

概念一句话记忆
渲染管线将 3D 物体变为 2D 像素的四阶段流水线
应用阶段CPU 端场景准备和裁剪
几何处理GPU 端顶点变换+裁剪(顶点着色器在此)
光栅化把三角形变成像素(固定功能)
像素处理计算每个像素的颜色(像素着色器在此)
坐标空间Object → World → View → Clip → Screen
MVP 矩阵模型×视图×投影 — 物体空间到裁剪空间
Forward vs Deferred前者逐物体逐光源算,后者先存几何再算光照

9. 练习与回顾

读完后,试着用自己的话回答以下问题:

  1. 渲染管线四阶段的名字各是什么? 每个阶段在 CPU 还是 GPU 执行?
  2. 顶点着色器 vs 像素着色器: 各在什么阶段执行?各关注什么?
  3. 一个顶点从物体空间到屏幕经历了哪四次坐标变换? 对应的矩阵是什么?
  4. Forward 渲染和 Deferred 渲染的核心区别是什么? 各有什么优缺点?
  5. 物体有哪五个基本属性? 着色器中分别用什么语义访问?

💡 不需要写下来,在脑子里过一遍就行。不太确定的地方可以回去看对应的章节。

10. 下一步

下一课我们将学习 Shader 的类型与结构——理解 Unity 中 Surface Shader、Unlit Shader、Compute Shader 和 Ray Tracing Shader 的区别,拆解一个 .shader 文件的骨架。

你也可以随时问我任何不清楚的问题。着色器中很多概念是逐步叠加的,打好基础最为关键。

📖 教材对照

本课对应《The Unity Shaders Bible》第 1 章 (p.14–32) 和第 2 章开头 (p.33) 的内容。 推荐延伸阅读(英文):LearnOpenGL - Hello Triangle (用 OpenGL 的角度看渲染管线,加深理解)