优化3D场景 - 实例化渲染百万级数据

1,507 阅读5分钟

优化 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 示例

instanced rendering.gif

示例是使用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的不同啦。