Cesium 中优化 3D Tiles 性能的方式

1,814 阅读4分钟

“优化Cesium 3D Tiles主要从三方面入手:
1. 数据生产阶段:通过模型简化、精细LOD、纹理压缩和高效空间划分(如Octree)减少数据量;
2. 运行时策略:利用视锥剔除、动态LOD选择(调整maximumScreenSpaceError)、请求调度(限制并发请求)和缓存机制优化加载;
3. 渲染优化:启用实例化渲染、点云简化,并谨慎使用后期处理。
此外,使用Draco压缩、S2空间索引扩展和性能监控工具也是关键手段。”

一、数据生产阶段优化 (根本性优化)

  1. 模型简化与LOD (层次细节)

    • 几何简化:  使用工具(如 FME、Blender、专业BIM/GIS软件)减少非必要三角面数,在保持视觉保真度前提下降低几何复杂度。
    • 精细LOD设计:  确保每个瓦片有多个合理的细节层级。离相机近时加载精细模型,远时加载粗糙模型。工具如Cesium ionpy3dtilesFME支持LOD生成。
    • 分离静态/动态数据:  将静态背景(地形、建筑)与动态对象(车辆、人物)分开成不同瓦片集,动态对象可用更简单LOD或点云替代。
  2. 纹理优化

    • 分辨率控制:  为不同LOD层级使用合适分辨率的纹理,避免远处物体使用超大纹理。
    • 压缩格式:  使用GPU友好格式(如Basis UniversalKTX2DDS),支持硬件解码,减少显存占用和带宽。
    • 纹理集(Atlases):  将多个小纹理打包成大纹理集,减少Draw Call。
  3. 空间数据结构优化

    • 空间划分:  使用高效的树结构(如K-D TreeQuadtreeOctree)组织瓦片,确保快速空间查询。
    • 紧密包围盒:  为每个瓦片计算精确的包围球(boundingSphere)或包围盒(boundingVolume),提高剔除效率。
  4. 属性与元数据

    • 精简属性:  移除不必要属性,使用3DTILES_metadata扩展按需存储查询属性。
    • 外部存储:  将非渲染必需的大属性数据存于外部数据库(如Cesium ion属性存储),按需查询。

二、加载策略优化 (运行时核心)

  1. 视锥体剔除 (Frustum Culling)

    • 原理:  只加载和渲染在相机视锥体内的瓦片。Cesium自动进行,优化核心是精确的boundingVolume
  2. 细节层次选择 (LOD Selection)

    • 屏幕空间误差(SSE):  Cesium根据瓦片的几何误差与屏幕像素误差阈值决定加载哪个LOD层。调整maximumScreenSpaceError

      const tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
          url: 'path/to/tileset.json',
          maximumScreenSpaceError: 16, // 降低此值提高精度(增加负载),增大则提升性能
          skipLevelOfDetail: true, // 推荐开启,优化LOD过渡
      }));
      
  3. 动态屏幕误差调整

    • 根据设备性能动态调整SSE:

      function adjustSSE() {
          const fps = viewer.scene.frameState.framesPerSecond;
          if (fps < 30) tileset.maximumScreenSpaceError += 2; // 性能下降时降低精度
          else if (fps > 60 && tileset.maximumScreenSpaceError > 4) tileset.maximumScreenSpaceError -= 1;
      }
      viewer.scene.postUpdate.addEventListener(adjustSSE);
      
  4. 瓦片卸载与缓存

    • 卸载不可见瓦片:  设置tileCacheSize(内存缓存瓦片数)和maximumMemoryUsage(显存上限)。
    • 磁盘缓存:  使用Cesium.Resourcecache机制复用已下载瓦片。
  5. 请求调度优化

    • 优先级调度:  Cesium优先加载视野中心及低LOD瓦片。
    • 节流请求:  通过maximumRequests限制并发请求数,避免浏览器排队阻塞。

三、渲染优化 (减轻GPU压力)

  1. 实例化渲染 (Instancing)

    • 对重复结构(如树木、路灯)使用3DTILES_instancing扩展,单Draw Call渲染大量相同物体。
  2. 点云渲染优化

    • 着色优化:  使用简单材质(如color代替classification)。
    • 点大小控制:  通过pointSize/pointSizeScale减小远看点尺寸。
    • 裁剪:  设置clippingPlanes切除建筑内部点云。
  3. 后期处理优化

    • 谨慎使用SSAO、阴影等特效,必要时降低采样或分辨率:
      viewer.scene.postProcessStages.fxaa.enabled = false; // 关闭抗锯齿
      

四、高级技术与扩展

  1. 瓦片替换/聚合

    • 替代瓦片:  为远距离物体使用简化模型(如3DTILES_implicit_tiling)。
    • 点云聚合:  用点云代表建筑群(如Cesium ion的 Photogrammetry 分类)。
  2. 空间索引扩展

    • 使用3DTILES_bounding_volume_S2(基于S2几何)优化全球覆盖瓦集的裁剪。
  3. 渐进加载与压缩

    • Draco压缩:  使用EXT_mesh_draco压缩几何数据。
    • 量化:  对顶点、纹理坐标进行16位量化(KHR_mesh_quantization)。

五、调试与监控

  1. 调试面板

    viewer.scene.debugShowFramesPerSecond = true; // 显示帧率
    tileset.debugShowContentBoundingVolume = true; // 显示瓦片包围盒
    tileset.debugShowViewerRequestVolume = true; // 显示请求范围
    
  2. 性能分析

    • 使用Cesium3DTileset#statistics监控瓦片数、显存占用:

      console.log(tileset.statistics);
      

六、工程化优化

  1. CDN分发:  使用CDN加速全球瓦片加载。
  2. HTTP/2:  开启HTTP/2支持多路复用请求。
  3. Gzip/Brotli压缩:  压缩JSON和纹理资源。