WebGL 渲染管线(Rendering Pipeline)是一系列将 3D 顶点数据转换为 2D 屏幕像素的处理阶段。理解渲染管线对于优化 WebGL 应用性能至关重要。
渲染管线的各个阶段
1. 顶点处理阶段(Vertex Processing)
顶点着色器(Vertex Shader)
-
输入:顶点位置、颜色、纹理坐标、法线等属性
-
处理:
- 坐标变换(模型矩阵、视图矩阵、投影矩阵)
- 顶点光照计算
- 纹理坐标变换
-
输出:裁剪空间坐标(Clip Space Coordinates)
glsl// 顶点着色器示例 attribute vec3 a_position; attribute vec2 a_texCoord; uniform mat4 u_modelViewProjectionMatrix; varying vec2 v_texCoord; void main() { gl_Position = u_modelViewProjectionMatrix * vec4(a_position, 1.0); v_texCoord = a_texCoord; }
2. 图元装配阶段(Primitive Assembly)
- 将顶点组装成图元(点、线、三角形)
- 执行裁剪(Clipping):移除视锥体外的图元
- 执行透视除法(Perspective Division):将裁剪坐标转换为标准化设备坐标(NDC)
3. 光栅化阶段(Rasterization)
- 将图元转换为片段(Fragments)
- 片段是潜在的像素,包含颜色、深度等信息
- 确定哪些像素被图元覆盖
- 进行插值计算:颜色、纹理坐标、法线等属性在片段间的插值
4. 片段处理阶段(Fragment Processing)
片段着色器(Fragment Shader)
-
输入:插值后的顶点属性
-
处理:
- 纹理采样
- 光照计算
- 颜色混合
-
输出:最终像素颜色
glsl// 片段着色器示例 precision mediump float; varying vec2 v_texCoord; uniform sampler2D u_texture; void main() { gl_FragColor = texture2D(u_texture, v_texCoord); }
5. 逐片段操作阶段(Per-Fragment Operations)
深度测试(Depth Testing)
- 比较片段深度值与深度缓冲区
- 决定是否丢弃片段
模板测试(Stencil Testing)
- 使用模板缓冲区进行掩码操作
混合(Blending)
- 将片段颜色与帧缓冲区已有颜色混合
- 实现透明效果
抖动(Dithering)
- 减少颜色量化带来的色带
WebGL 渲染流程图
shell顶点数据 → 顶点着色器 → 图元装配 → 裁剪 → 透视除法 → 视口变换 ↓ 帧缓冲区 ← 逐片段操作 ← 片段着色器 ← 光栅化/插值 ← 屏幕映射
性能优化要点
- 减少绘制调用:合并网格,使用实例化渲染
- 优化顶点着色器:避免复杂计算
- 减少片段着色器复杂度:特别是移动端
- 合理使用深度测试:从前到后绘制不透明物体
- 避免过度绘制:使用遮挡查询
WebGL 1.0 vs WebGL 2.0 管线差异
| 特性 | WebGL 1.0 | WebGL 2.0 |
|---|---|---|
| 变换反馈 | 不支持 | 支持 |
| 多重渲染目标 | 需要扩展 | 原生支持 |
| 3D 纹理 | 需要扩展 | 原生支持 |
| 实例化渲染 | 需要扩展 | 原生支持 |