在 GPU 渲染管线中,**顶点着色器(Vertex Shader)和片元着色器(Fragment Shader)**是两个最核心的阶段。理解它们的关系和执行顺序,对于掌握 GLSL 或 Three.js/WebGL 编程至关重要。
1. 顶点着色器(Vertex Shader)概述
顶点着色器是 GPU 渲染管线的第一个可编程阶段,主要作用是处理每个顶点的坐标和属性:
-
输入:顶点位置、颜色、法线、UV 坐标等
-
输出:
- 必须写入
gl_Position,确定顶点在裁剪空间的位置 - 可通过
out/varying变量传递给片元着色器
- 必须写入
示例(GLSL 3.00 / WebGL2) :
out vec3 vColor; // 传递给片元 shader
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
void main() {
vColor = position; // 顶点属性插值的来源
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
注意:顶点着色器对每个顶点只执行一次,负责计算几何变换和传递属性。
2. 图元组装与光栅化
顶点着色器执行完成后,GPU 会进入图元组装阶段:
- 按渲染模式(如
GL_TRIANGLES)把顶点组合成三角形、线段或点。 - 三角形在逻辑上已经形成,但尚未映射到屏幕像素。
随后是光栅化阶段(Rasterization) :
- GPU 将三角形投影到屏幕像素网格上
- 对三角形内部的每个片元,计算顶点属性的插值值(颜色、UV、法线等)
- 生成的片元成为片元着色器的输入
片元 shader 执行前,三角形已经形成,但只是几何形状,颜色尚未确定。
3. 片元着色器(Fragment Shader)概述
片元着色器在光栅化阶段生成的每个**片元(Fragment)**上执行一次,用于计算最终颜色或深度:
- 输入:光栅化插值得到的顶点属性
- 输出:写入 framebuffer 的颜色或深度值
示例(GLSL 3.00 / WebGL2) :
precision highp float;
in vec3 vColor; // 来自顶点 shader 的插值
out vec4 FragColor; // 输出到 framebuffer
void main() {
FragColor = vec4(vColor, 1.0); // 输出颜色
}
每个片元 shader 执行一次,每个片元对应屏幕上的一个像素位置。
4. 顶点着色器与片元着色器的关系
| 特性 | 说明 |
|---|---|
| 执行顺序 | 先执行顶点 shader → 图元组装 → 光栅化 → 执行片元 shader |
| 数据传递 | 顶点 shader 的 out / varying 变量会被插值后传入片元 shader 的 in / varying 变量 |
| 作用分工 | 顶点 shader:处理几何位置和属性 片元 shader:处理颜色和像素级效果 |
| 依赖关系 | 片元 shader 必须依赖顶点 shader 的输出,无法单独计算片元颜色 |
5. 可视化理解
[顶点数据 Vertex] -> Vertex Shader (计算 gl_Position, out)
|
v
Primitive Assembly (组成三角形)
|
v
Rasterization (生成片元)
|
v
Fragment Shader (计算每个片元颜色)
|
v
Framebuffer (最终显示)
- 顶点 shader 每个顶点执行一次
- 三角形在图元组装阶段形成
- 光栅化阶段生成片元
- 片元 shader 每个片元执行一次,输出最终颜色
6. 总结
- 顶点 shader → 片元 shader 是 GPU 渲染管线的核心顺序。
- 顶点 shader 只处理顶点,片元 shader 才输出颜色。
- 光栅化阶段负责把顶点属性插值到每个片元。
- 理解这个关系有助于调试 shader、优化渲染和理解 GPU 内部工作原理。
实践建议:
- 在学习 GLSL 时,可以先写最小 shader(顶点传递 →
gl_Position,片元输出纯色),观察顶点属性如何在光栅化后影响片元颜色。- 使用
varying/out变量练习顶点到片元的插值机制。
本文部分内容借助 AI 辅助生成,并由作者整理审核。