Cesium 高级教程:性能优化与自定义扩展

WebGIS
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

Cesium 高级性能优化与自定义扩展的核心做法是:启用 requestRenderMode 让场景只在相机变化、数据加载或显式请求时渲染,把空闲 CPU 占用从约 25% 降到约 3%;同时调高 3D Tiles 的 maximumScreenSpaceError 等参数减少细节瓦片请求,并用 Custom Geometry(GeometryInstance 批处理)、CustomShader 与 Viewer Mixin 实现高性能静态几何和自定义着色。截至 2026 年 11 月,CesiumJS 最新版为 1.147(2026-11-02 发布),已包含多项视觉保真度与性能修复。掌握这些手段,城市级三维场景可在浏览器中稳定流畅运行,并按业务需求扩展视觉与交互能力。

Cesium 性能优化前后场景流畅度示意

如何用 requestRenderMode 降低空闲渲染开销

默认 Viewer 会持续渲染,即使相机静止、数据不再变化,CPU 仍维持较高占用。requestRenderMode(自 1.42 起支持)改为按需渲染:仅在相机移动、模拟时间变化超过阈值、地形/影像/3D Tiles/数据源加载、图层变更、场景模式切换或手动调用 requestRender 时才真正绘制。空闲时可接近 0 FPS。

  1. 创建 Viewer 时直接开启:传入 requestRenderMode: true 与 maximumRenderTimeChange: Infinity(忽略时间驱动的自动刷新)。
  2. 已有实例可事后设置:viewer.scene.requestRenderMode = true。
  3. 任何会改变画面的操作(添加/修改 Entity、更新属性、加载瓦片后)后,显式调用 viewer.scene.requestRender()。
  4. 区分事件:preUpdate/postUpdate 每帧都会触发,preRender/postRender 只在真正渲染时触发,便于挂接逻辑。

验收标准:静止场景下帧率接近 0、任务管理器中 Cesium 相关 CPU 显著下降;相机一动立即恢复渲染且无黑屏。动态 CallbackProperty 或持续动画可能导致仍频繁渲染,需评估是否保留 requestRenderMode。

3D Tiles 与场景参数怎么调才能流畅

城市级或百 GB 级 3D Tiles 最常见瓶颈是请求过多、内存暴涨与细节切换闪烁。优先调屏幕空间误差与缓存,再关闭不必要的后处理。硬件建议(社区汇总,非官方硬性指标):基础场景双核约 2 GHz CPU + 4 GB RAM + WebGL 2 集成显卡即可;城市级建议四核 3 GHz+、8 GB+ RAM、独立 GPU 2 GB+ VRAM、10 Mbps+ 网络。浏览器用最新 Chrome、Edge、Firefox、Safari(Firefox 一般需 115 或 ESR 以上),预构建目标为 ES2020,依赖 WebGL 2(可回退 WebGL 1 + 扩展)。

参数 默认/说明 调优方向
maximumScreenSpaceError 默认 16 调高(如 32 及以上)减少高细节瓦片,提升性能、降低质量
skipLevelOfDetail 默认关闭 开启可跳过中间 LOD、加速加载,可能出现短暂伪影
dynamicScreenSpaceError / preferLeaves / cullRequestsWhileMoving 按需 移动时减少请求、优先叶子节点
maximumMemoryUsage 或 cacheBytes 软限制 按设备内存上调或下调,避免 OOM
immediatelyLoadDesiredLevelOfDetail 按需 需要立刻看到目标细节时开启
  • 创建 Viewer 时加 scene3DOnly: true,去掉 2D/哥伦布视图开销。
  • 降低 resolutionScale(如 0.8),关闭阴影、FXAA、后处理与不必要的深度测试。
  • 大量静态几何优先用 Primitive + GeometryInstance 批处理,而不是海量 Entity。
  • 瓦片本身建议 Draco 压缩;复杂样式尽量在 GPU 侧评估,避免大量 JS conditions。

对于超大规模数据加载经验,可参考 海量 3D Tileset 加载讨论。验收:平移缩放时无明显卡顿、内存曲线平稳、目标区域细节在可接受时间内出现。

3D Tiles 屏幕空间误差与细节层次平衡示意

用 Custom Geometry 与 CustomShader 做高性能自定义

Entity 适合动态少量对象;大批量静态几何(道路网、建筑基底、标注面)应走 Primitive API:Geometry 描述结构,Appearance 描述着色与渲染状态,二者解耦后可用 GeometryInstance 做批处理,一次绘制上千实例,显著降 draw call。Appearance 需匹配 Geometry 的 vertexFormat;常用 PerInstanceColorAppearance 等。材质也可用 Fabric(JSON 描述 Color/Image/Checkerboard 等,或自定义 czm_getMaterial GLSL)挂到 Appearance。

  1. 准备 Geometry(如 PolygonGeometry、PolylineGeometry)与 Appearance。
  2. 为每个实例创建 GeometryInstance(可带 modelMatrix、attributes 颜色等)。
  3. 把多个 Instance 放入同一个 Primitive,加入 scene.primitives。
  4. 需要自定义片元/顶点逻辑时,对 Model、Cesium3DTileset 或 VoxelPrimitive 使用 CustomShader:注入 GLSL,支持 uniforms(FLOAT/VEC*/MAT*/SAMPLER_2D,TextureUniform 可从 URL 或 TypedArray)、varyings、mode(MODIFY_MATERIAL 默认或 REPLACE_MATERIAL)、lightingModel(PBR/UNLIT)与 translucencyMode。
  5. 创建后赋给 tileset 或 Model.fromGltfAsync 的 customShader 选项即可。

CustomShader 适合做高亮、热力、裁剪、风格化材质等,而无需改源码。静态数据批处理后,帧时间通常明显下降;动态频繁改几何时仍需评估是否回退 Entity 或定期重建 Primitive。

用 Mixin 扩展 Viewer 时要注意什么

viewer.extend(mixinFunction, options) 可把功能挂到 Viewer 上(添加属性、按钮、监听)。内置示例包括 viewerCesiumInspectorMixin、viewerPerformanceWatchdogMixin、viewerDragDropMixin 等。自定义 Mixin 就是一个接收 viewer 与 options 的函数,在内部注册事件、创建控件或暴露 API。

  • 保持幂等:重复 extend 不应重复绑定同一事件。
  • 与 requestRenderMode 配合:Mixin 内改场景后记得 requestRender()。
  • 生产构建可去掉 debug 代码;用 Webpack/Vite 时务必正确复制 Assets、Workers 等静态资源,否则离线或 worker 会失败。
  • 完全离线场景可换本地 NaturalEarthII 底图,并关掉 baseLayerPicker、geocoder 等在线控件(以官网 Offline Guide 为准)。

验收:扩展后原有交互不破坏,性能监控(如 PerformanceWatchdog)能正确报警,自定义按钮在按需渲染模式下点击仍立即生效。

常见问题

开启 requestRenderMode 后模型或实体不更新、加载不全?

变更后必须显式调用 scene.requestRender();检查是否有 CallbackProperty 等持续脏标记导致异常行为。历史相关渲染 bug 在近期版本已修复,建议升级到 1.147 验证。

提示“Browser supports WebGL, but initialization failed”怎么办?

先更新显卡驱动与浏览器、确认硬件加速已开、排除黑名单;硬件过旧或被禁用也会触发。更细排查步骤见 社区 WebGL 初始化失败讨论。

3D Tiles 闪烁、内存持续上涨或 stutter?

提高 maximumScreenSpaceError、合理设置 cacheBytes;可开 skipLevelOfDetail(接受可能伪影);检查瓦片 geometricError 与体积;复杂样式改为 evaluateColor 或 feature.color,避免海量 conditions 在 JS 侧计算。

成千上万 Entity 导致卡顿如何处理?

改为 Primitive + GeometryInstance 批处理静态部分;关闭阴影、FXAA 与后处理;必要时降低 resolutionScale。动画/蒙皮复杂的 glTF 也需检查结构,避免每帧过重计算。

先把 requestRenderMode 与 3D Tiles 的 SSE/缓存调通,用空闲 CPU 与平移流畅度做验收,再按需上 Custom Geometry、CustomShader 或 Mixin 做扩展;建议在 CesiumJS 1.147 下结合本机硬件实测,并以官网 changelog 与 API 文档核对最新行为。生产环境务必做 tree-shaking、移除 debug 并正确打包 Workers/Assets。