渲染架构概览
目的与范围
本文档提供 Three.js 渲染子系统的架构概览,涵盖场景如何从场景图表示转换为屏幕上的像素。渲染架构包含 WebGL 和 WebGPU 后端、着色器程序管理、状态缓存和资源协调。
有关特定子系统的详细信息:
- 渲染循环和帧执行:见WebGL 渲染管线
- 着色器编译和管理:见着色器程序与 ShaderLib
- WebGL 状态和资源缓存:见状态与资源管理
- 阴影渲染通道:见阴影映射
- WebGPU 后端和节点材质:见WebGPU 与节点材质
有关场景图结构和对象层次:见场景图与 Object3D
渲染器架构概览
Three.js 提供两个主要渲染后端,实现为独立类。WebGLRenderer 类(自 r163 起使用,仅 WebGL 2)作为主要生产渲染器,而 WebGPU 渲染器代表下一代图形 API 支持。
高层渲染器结构
渲染子系统组织
WebGLRenderer 将专门任务委托给模块化子系统,每个子系统管理渲染管线的特定方面。
| 子系统 | 主要类 | 职责 |
|---|---|---|
| 着色器管理 | WebGLPrograms | 程序选择、编译、缓存 |
| 状态缓存 | WebGLState | GL 状态变更跟踪、去重 |
| 几何体上传 | WebGLGeometries | VBO 创建、属性绑定 |
| 纹理管理 | WebGLTextures | 纹理上传、参数缓存 |
| 渲染协调 | WebGLRenderLists | 对象排序(不透明/透明) |
| 光照设置 | WebGLRenderStates | 每场景光照累积 |
| 阴影渲染 | WebGLShadowMap | 阴影图生成、过滤 |
| 能力检测 | WebGLCapabilities | GPU 限制、扩展可用性 |
| 资源跟踪 | WebGLInfo | 绘制调用计数、内存统计 |
帧渲染流
渲染过程遵循从场景遍历到最终像素输出的明确定义序列。WebGLRenderer.render() 方法编排这个多阶段管线。
渲染方法执行流
着色器程序管线
着色器程序是转换顶点和计算片元颜色的已编译 GPU 代码。WebGLPrograms 子系统基于材质属性和场景上下文管理程序选择、编译和缓存。
程序选择与编译流
内置着色器库
ShaderLib 为所有标准材质类型提供模板着色器。每个条目包含 uniform 定义、顶点着色器源代码和片元着色器源代码。这些着色器由可重用的 ShaderChunk 模块组成。
ShaderLib 材质类型
| ShaderLib 键 | 材质类型 | 光照模型 |
|---|---|---|
| basic | MeshBasicMaterial | 无光照 |
| lambert | MeshLambertMaterial | Lambertian 漫反射 |
| phong | MeshPhongMaterial | Blinn-Phong 镜面反射 |
| standard | MeshStandardMaterial | PBR(金属度/粗糙度) |
| physical | MeshPhysicalMaterial | PBR + 清漆/透射 |
| toon | MeshToonMaterial | 卡通着色 |
| matcap | MeshMatcapMaterial | Matcap 纹理 |
| points | PointsMaterial | 点精灵 |
| dashed | LineDashedMaterial | 虚线 |
| depth | MeshDepthMaterial | 深度编码 |
| normal | MeshNormalMaterial | 法线可视化 |
| distance | MeshDistanceMaterial | 距点的距离 |
使用 ShaderChunk 的着色器组合
状态管理与缓存
WebGLState 类包装所有 WebGL 状态变更调用以最小化冗余 GPU 命令。它跟踪当前状态,仅当期望状态与缓存状态不同时发出 GL 调用。
缓存状态类别
资源上传与缓存
几何体和纹理数据必须在渲染前上传到 GPU 内存。渲染器维护单独的子系统来管理这些资源并进行智能缓存。
资源管理子系统
| 类 | 上传目标 | 缓存策略 |
|---|---|---|
| WebGLAttributes | 顶点缓冲区对象(VBO) | 按 BufferAttribute.uuid |
| WebGLGeometries | 完整几何体 | 按 BufferGeometry.id + 属性版本 |
| WebGLTextures | 纹理数据 | 按 Texture.id + 源版本 + 参数 |
| WebGLRenderTarget | 帧缓冲区对象(FBO) | 按渲染目标实例 |
| WebGLCubeMaps | 立方体环境贴图 | 按纹理实例与 PMREMGenerator |
| WebGLCubeUVMaps | 立方体UV环境贴图 | 按纹理实例,管理生命周期 |
纹理上传流
渲染列表与排序
渲染前必须遍历场景图以构建可渲染对象列表。WebGLRenderLists 系统将对象组织为不透明和透明组,然后对它们进行排序以获得正确的渲染顺序。
渲染列表填充
排序策略
| 对象类型 | 主要排序 | 次要排序 | 方向 |
|---|---|---|---|
| 不透明 | renderOrder 然后 material.id | z(深度) | 从前到后(优化) |
| 透明 | renderOrder | z(深度) | 从后到前(正确性) |
透明对象必须从后到前渲染以获得正确的 alpha 混合。不透明对象从前到后渲染以利用早期深度测试并减少过度绘制。
后端对比:WebGL vs WebGPU
Three.js 支持两种不同架构的渲染后端。WebGL 后端成熟且可用于生产,而 WebGPU 代表具有计算着色器支持的下一代 GPU API。
架构差异
| 方面 | WebGLRenderer | WebGPU 渲染器 |
|---|---|---|
| API 版本 | 仅 WebGL 2.0(自 r163) | WebGPU(Chrome 113+) |
| 着色器语言 | GLSL ES 3.0 | WGSL |
| 材质系统 | 传统属性 | 基于节点的材质(TSL) |
| 状态管理 | 全局状态机(缓存) | 命令编码器(无状态) |
| 计算着色器 | 不支持 | 完全支持 |
| 构建输出 | three.module.js | three.webgpu.js, three.tsl.js |
| 坐标系 | Y 向上,右手系 | 可配置 |
WebGPU 架构(简要,详见WebGPU 与节点材质)
WebGPU 后端使用根本不同的方法:
- 节点材质:通过节点图而非简单属性定义材质属性
- 渲染束:重复绘制的预录制命令序列
- 计算通道:用于物理、粒子、后处理的 GPU 计算着色器
- 多渲染目标:原生支持同时渲染到多个纹理
初始化与上下文创建
渲染器必须在开始渲染前获取 WebGL 上下文并初始化所有子系统。此过程包括能力检测、扩展加载和子系统实例化。
渲染器初始化序列
上下文属性
渲染器在构造时请求具有特定属性的 WebGL2 上下文:
// 来自 WebGLRenderer 构造函数
const contextAttributes = {
alpha: true,
depth: true,
stencil: false,
antialias: false,
premultipliedAlpha: true,
preserveDrawingBuffer: false,
powerPreference: 'default',
failIfMajorPerformanceCaveat: false,
};材质到着色器映射
不同材质类型需要不同着色器程序。WebGLPrograms 系统分析材质属性和场景上下文以生成适当的着色器代码。
材质类型到 ShaderLib 映射
着色器变体生成
对于每个材质类型,可能基于以下条件生成数百种着色器变体:
- 纹理使用(map、normalMap、roughnessMap 等)
- 光照配置(光源数量和类型)
- 特性标志(雾效、阴影、形态目标、蒙皮)
- 材质属性(透明度、双面等)
MeshStandardMaterial 的参数组合示例:
// 在 WebGLPrograms.getParameters() 中生成
{
map: true,
normalMap: true,
roughnessMap: true,
metalnessMap: true,
envMap: true,
lights: true,
shadowMapEnabled: true,
numDirLights: 2,
numPointLights: 3,
// ... 更多参数
}每个唯一组合产生不同的已编译着色器程序。
渲染目标系统
渲染目标允许渲染到离屏纹理而非画布。这支持多通道渲染、后处理效果、阴影图和环境贴图生成。
WebGLRenderTarget 结构
渲染目标包含:
- 一个或多个颜色纹理(附件)
- 可选深度缓冲区(渲染缓冲区或纹理)
- 可选模板缓冲区
- 尺寸和像素格式规范
渲染目标使用模式
常见渲染目标应用
| 用例 | 配置 | 消费者 |
|---|---|---|
| 阴影图 | 深度纹理,单通道 | WebGLShadowMap 生成,材质采样 |
| 后处理 | RGBA 颜色纹理 | 效果读取前一帧输出 |
| 反射贴图 | 立方体渲染目标(6面) | 材质上的环境映射 |
| 拾取 | 对象 ID 的整数格式 | 鼠标交互/选择 |
| 多重采样 | MSAA 采样 > 1 | 无后处理的抗锯齿 |
性能监控
WebGLInfo 对象跟踪对性能分析和调试有用的渲染统计。它计数绘制调用、几何体上传、纹理上传和着色器编译。
WebGLInfo 统计
// 通过 renderer.info 访问
{
memory: {
geometries: 42, // 已上传的 BufferGeometry 数量
textures: 18 // GPU 上的 Texture 数量
},
render: {
calls: 156, // 此帧的绘制调用数量
triangles: 84320, // 渲染的总三角形数
points: 0,
lines: 0,
frame: 0 // 帧计数器
},
programs: [...] // 已编译 WebGLPrograms 数组
}通过监控 render.calls 和 render.triangles,开发者可以识别性能瓶颈。高绘制调用计数表明场景过度碎片化,而高三角形计数表明几何体复杂性。
总结
Three.js 渲染架构组织为协作将场景图转换为渲染像素的模块化子系统:
- WebGLRenderer 编排整体渲染过程并拥有所有子系统
- WebGLPrograms 基于材质/场景参数管理着色器选择、编译和缓存
- WebGLState 包装 GL 状态变更以最小化冗余 GPU 命令
- WebGLGeometries 和 WebGLTextures 处理资源上传和缓存
- WebGLRenderLists 组织对象以进行具有适当排序的高效渲染
- WebGLRenderStates 累积每场景/相机的光照信息
- WebGLShadowMap 通过仅深度渲染通道实现阴影映射
此架构实现高性能渲染,同时为多样材质类型和渲染技术保持灵活性。缓存和状态管理层确保即使在复杂场景中也能最小化 GPU 开销。
有关每个子系统的实现细节,见子页面:WebGL 渲染管线、着色器程序与 ShaderLib、状态与资源管理、阴影映射和WebGPU 与节点材质。