开篇
- 目标:让三维场景更流畅、更稳定,面向无人机/数字孪生/GIS 场景
- 原则:减少渲染工作量、降低资源体积、按需加载与批处理;监控和度量贯穿始终
快速优化清单
- 只启用需要的功能:
scene3DOnly: true、关闭阴影与复杂后处理 - 按需渲染:开启
requestRenderMode,有变更时再渲染 - 控制 3D Tiles:降低
maximumScreenSpaceError 的精度需求、限制 maximumNumberOfLoadedTiles - 批量而非散点:大量几何用
Primitive + GeometryInstance 批渲染,少用成千上万 Entity - 资源压缩:模型用 glTF + Draco/KTX2,贴图降采样与压缩;影像切片与 CDN 加速
- 交互节流:高频交互(鼠标移动、实时数据)做节流与合并更新
深入优化
1)渲染模式与场景设置
const viewer = new Cesium.Viewer('container', {scene3DOnly: true,shadows: false,terrainProvider: Cesium.createWorldTerrain({ requestVertexNormals: true })
})
viewer.scene.requestRenderMode = true
viewer.scene.maximumRenderTimeChange = 0.0
function trigger() { viewer.requestRender() }
viewer.scene.globe.depthTestAgainstTerrain = false
viewer.scene.postProcessStages.fxaa.enabled = true
requestRenderMode:避免无意义的逐帧渲染;数据/相机/样式变化时手动触发scene3DOnly:剔除 2D/Columbus 模式相关开销- 关闭高成本:阴影、OIT(半透明排序)、部分后处理
2)3D Tiles 调优
const tileset = new Cesium.Cesium3DTileset({url: 'your/tileset.json',maximumScreenSpaceError: 2, maximumNumberOfLoadedTiles: 256, skipLevelOfDetail: true, baseScreenSpaceError: 1024,skipLevels: 1,dynamicScreenSpaceError: true
})
viewer.scene.primitives.add(tileset)
- LOD 策略:先粗后细(skip LOD),再在静止或重要区域提高精度
- 资源控制:上限
maximumNumberOfLoadedTiles,避免显存与内存爆炸 - 动态精度:
dynamicScreenSpaceError 随相机远近调整,提升整体流畅度
3)Entity vs Primitive(批渲染)
const instances = polygons.map(positions => new Cesium.GeometryInstance({geometry: new Cesium.PolygonGeometry({polygonHierarchy: new Cesium.PolygonHierarchy(positions)})
}))
const primitive = new Cesium.Primitive({geometryInstances: instances,appearance: new Cesium.PerInstanceColorAppearance({ flat: true }),asynchronous: true
})
viewer.scene.primitives.add(primitive)
- 原则:上千/上万要素用
Primitive 批量;Entity 适合业务少量对象与交互 - 文本/图标:大量
Billboard/Label 使用 DataSource.clustering 聚合,降低绘制数量
4)资源与纹理优化
- 模型:glTF 使用 Draco 网格压缩与 KTX2 纹理压缩(体积更小,GPU 更友好)
- 贴图:降采样与区域裁剪;尽量避免过大分辨率的贴图(尤其全屏背景)
- 影像:CDN + 切片缓存;只加载当前视域内瓦片
5)影像与地形的取舍
- 地形:
depthTestAgainstTerrain 在需要“贴地”精度时开启,否则关闭以提升性能 - 光照与阴影:多数业务场景关闭阴影;必要时限制阴影级别与范围
- 雾与特效:启用雾可改善远景表现与 LOD 感知,但过度特效会增加开销
6)交互、流与更新
- MQTT/实时数据:将高频更新合并为批次;只在数据变更后触发
viewer.requestRender() - 相机事件:节流相机移动事件,避免每个像素移动都触发重算
- 选择与拾取:限制拾取频率;复杂几何拾取可用“包围盒”近似以降低计算
7)调试与监控
viewer.scene.debugShowFramesPerSecond = true
viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin)
- 指标:FPS、内存、瓦片加载数量、网络并发与耗时、相机路径与停留点
- 方法:逐项开关与对照测试(A/B),保留最佳配置与参数
8)整体策略:先可见,后精致
- 打开场景时优先展示可用画面(skip LOD + 低精度),用户停留后再提高质量
- 热路径优化:用户常看的区域与功能做更高精度与缓存;冷路径保持轻量
常见误区
- 大量 Entity 直接渲染,导致 CPU/GPU 压力暴增
- 未开启
requestRenderMode,即使静止场景也在不断重渲染 - 3D Tiles 参数默认不管,瓦片无限加载占满内存与带宽
- 贴图与模型过大、不压缩,启动慢、卡顿严重
总结
- Cesium 性能优化的关键是“渲染策略 + 资源控制 + 批量化”,辅以监控与迭代
- 优先从渲染模式、3D Tiles 与实体批渲染入手,再逐步优化资源与交互
示例组合
const viewer = new Cesium.Viewer('container', { scene3DOnly: true, shadows: false })
viewer.scene.requestRenderMode = true
viewer.scene.maximumRenderTimeChange = 0.0
const tileset = new Cesium.Cesium3DTileset({url: 'your/tileset.json',maximumScreenSpaceError: 2,maximumNumberOfLoadedTiles: 256,skipLevelOfDetail: true,baseScreenSpaceError: 1024,skipLevels: 1,dynamicScreenSpaceError: true
})
viewer.scene.primitives.add(tileset)
viewer.requestRender()