优化 3D 场景 - 实例化渲染
引言
在现代 3D 图形渲染中,性能和效率是关键因素。尤其是在处理大量对象的场景时,如何有效地利用图形技术进行优化成为了重要课题。本文将渐进式地介绍实例化渲染技术,结合三大渲染引擎探讨如何实现高效的 3D 场景渲染。
1. 实例化渲染
1.1 什么是实例化渲染?
实例化渲染(Instanced Rendering)是一种图形渲染技术,用于高效地渲染大量相同的对象。它通过减少重复的绘制调用(draw calls)和数据传输,显著提高渲染性能。这种技术在需要渲染大量相同或相似对象的场景中非常有用,例如森林中的树木、城市中的建筑物、粒子系统等。
1.2 实例化渲染的优势
- 减少 Draw Calls: 通过一次绘制调用渲染多个实例,显著减少 GPU 的渲染开销。
- 利用 GPU 内存: 将实例化数据(如变换矩阵)存储在 GPU 内存中,避免频繁的数据传输。
- 批处理实例: 将多个实例的渲染任务批处理在同一渲染帧中,进一步减少 Draw Calls。
- 共享几何数据: 所有实例化对象共享同一个几何数据,避免为每个对象重复传输相同的数据。
- 独立的变换矩阵: 每个实例有独立的变换矩阵,使得相同几何数据的对象可以在场景中不同的位置和姿态显示。
2. WebGL实例化渲染
2.1 WebGL1 中的实例化技术
WebGL1 的实例化技术依赖于 ANGLE_instanced_arrays 扩展,允许在同一绘制调用中渲染多个实例。
- vertexAttribDivisorANGLE: 设置顶点属性的实例间隔。
- drawArraysInstancedANGLE / drawElementsInstancedANGLE: 发起实例化绘制调用。
在webgl2环境中,实例化渲染技术已经内置, 无需通过扩展去获取相应的API。
2.2 实例化渲染示例
下面是一个使用 WebGL 实例化渲染技术的示例,展示了如何通过 ANGLE_instanced_arrays 扩展在 WebGL 中高效渲染50万个三角形。
3. glTF 实例化 - EXT_mesh_gpu_instancing
3.1 EXT_mesh_gpu_instancing 扩展
该扩展允许在 GPU 上高效地实例化大量相同的模型。与传统的 CPU 实例化不同,它将实例数据(如变换矩阵)存储在 GPU 内存中,从而减少 CPU 和 GPU 之间的数据传输量。
3.2 如何使用 EXT_mesh_gpu_instancing 扩展
EXT_mesh_gpu_instancing扩展通过 glTF 文件中的 extensions 部分定义, 以下是一个示例,展示了如何在 glTF 文件中定义实例化数据:
{
"nodes":[
{
"mesh":0,
"extensions": {
"EXT_mesh_gpu_instancing": {
"attributes": {
"TRANSLATION": 3,
"ROTATION": 4,
"SCALE": 5
}
}
},
"name":"cube_instance"
}
]
}
上面示例对 mesh0 添加扩展 EXT_mesh_gpu_instancing, attributes添加了 位移,旋转和缩放三个属性, 每个属性指向对应的访问器.
3.3 使用 EXT_mesh_gpu_instancing 示例
示例是使用cesium加载了一个gltf, 通过EXT_mesh_gpu_instancing扩展实例化了200万个立方体, 从加载完毕到渲染可以看出是很快的, CPU运算也保持在20%以内
4. cesium 里 primitive
4.1. 高性能渲染
- 批处理:
Primitive可以批处理大量几何体实例,减少绘制调用(Draw Calls),从而提高渲染性能。 - GPU 加速: 充分利用 GPU 的并行处理能力,将计算和渲染任务从 CPU 转移到 GPU。
4.2. 实例化渲染
- 几何体实例: 使用
GeometryInstance类,可以高效地创建和管理多个几何体实例,每个实例可以有不同的变换矩阵和属性。 - 颜色和属性: 每个实例可以有独立的颜色和其他自定义属性,通过
PerInstanceColorAppearance类实现。
4.3. 适用于大规模数据
- 支持大数据集: 设计用于处理和渲染大规模的 3D 数据集,适用于城市模型、点云、地形等应用场景。
- 内存管理: 高效的内存管理,支持动态加载和卸载几何体数据。
代码示例
下面是使用 primitive 创建了 100万 个立方体例子:
5. Babylon里的 Thin Instance
- 轻量级: 使用较少的内存和 CPU 资源,因为它们不需要为每个实例创建独立的对象,不同于InstancedMesh。
- 高效渲染: Thin Instances 利用 GPU 的并行处理能力,可以高效地渲染大量相同的对象。
- 独立变换: 每个 Thin Instance 可以有独立的变换矩阵(位置、旋转和缩放),从而实现灵活的场景布局。
代码示例
这个示例展示了Babylon.js利用实例化渲染技术渲染100万个立方体
6. Three里的 InstancedMesh
Three.js 的 InstancedMesh 提供了一种高效的实例化渲染方式,适合渲染大量相同或相似的对象。
代码示例
100万个Box形成一个颜色带
总结
1. 实例化渲染的核心优势
实例化渲染是一种高效的渲染技术,能够显著减少绘制调用(draw calls),优化 GPU 性能。这对于需要渲染大量相同或相似几何体的场景尤其重要,如森林、城市模型或粒子系统。
2. 不同技术和实现方式
在本文中,我们探讨了在多个 3D 渲染引擎中使用实例化渲染的实现方式:
- glTF实例化:
EXT_mesh_gpu_instancing扩展使gltf具备实例化渲染的能力, 不仅可以减小文件体积, 还可以对实例使用复杂的材质。 - Cesium: 通过
Primitive类实现实例化渲染,适用于大规模地理数据集的高效渲染。 - Babylon.js: 使用
Thin Instances提供了一种轻量级的实例化渲染方式,适合大规模实例化场景,并结合了高效的内存管理和动态更新机制。 - Three.js: 使用
InstancedMesh类,通过共享几何体和材质,并利用 GPU 加速,实现高效的实例化渲染。
渲染引擎的实例化都是对 webgl 实例化渲染 技术的封装, 了解了webgl的实例化, 使用渲染引擎只是API的不同啦。