Cesium场景优化思路整理
发表于:2025-10-28 | 分类: 前端
字数统计: 738 | 阅读时长: 3分钟 | 阅读量:

在 Cesium 可视化开发中,当场景复杂度提升或有定制化或者较高的场景展示需求时,需要考虑的一些调整与优化点整理:

  1. 如果是内网部署项目,首先在 new Viewer 时,设置 imageryProvider: false , 并使用 viewer.scene.globe.baseColor = Cesium.Color.fromCssColorString("#001d34") 按需设置空地球颜色

  2. 本地影像通过 nginx 挂载后,通过 UrlTemplateImageryProvider 新建 provider 并添加到 imageryLayers

  3. Cesium 的鼠标操作个人不是很习惯,并且鼠标中键控制 pitch 有一些不符合直觉,可以通过以下代码按需改动操作方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 以下设置为了使cesium地图鼠标控制符合mapbox习惯
    // 关闭双击事件
    viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
    );
    // 鼠标右键旋转
    viewer.scene.screenSpaceCameraController.tiltEventTypes = [
    Cesium.CameraEventType.RIGHT_DRAG,
    ];
    // 中键滚动缩放
    viewer.scene.screenSpaceCameraController.zoomEventTypes = [
    Cesium.CameraEventType.WHEEL,
    ];
    // 鼠标左键平移
    viewer.scene.screenSpaceCameraController.rotateEventTypes = [
    Cesium.CameraEventType.LEFT_DRAG,
    ];
  4. 3dtile 加载需求时,异步加载 3dtile
    const tileset = await Cesium.Cesium3DTileset.fromUrl('/Tileset/tileset.json');

    4.1. 在之前项目中,可能是建模问题导致的切出来 3dtile 默认加载高度不对,这时需要重新切或者前端处理一下:

    1
    2
    3
    4
    5
    6
    7
    const center = tileset.boundingSphere.center;
    const heightOffset = -425.1; // 高度偏移量
    const cartographic = Cesium.Cartographic.fromCartesian(center);
    const surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
    const offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
    const translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

    4.2. 当模型材质的金属度太高,粗糙度太低,可能会导致模型反光,且背光面太暗,这时需要手动修改材质,或者提升光强度。经过对比,最终还是添加一个 3dtile 全局的着色器效果比较好 - -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const unlitShader = new Cesium.CustomShader({
    lightingModel: Cesium.LightingModel.UNLIT,
    fragmentShaderText: `
    void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
    material.diffuse = material.diffuse * 1.5;
    }
    `
    });
    tileset.customShader = unlitShader;
  5. Cesium 场景加载后,为了提升展示效果,可以添加阴影和抗锯齿
    viewer.scene.shadowMap.softShadows = true // 更好效果的抗锯齿(比较吃配置)
    viewer.shadowMap.darkness = cesium_shadow_opacity // 透明度
    viewer.scene.shadowMap.size = cesium_shadow_size // 阴影大小 类似分辨率的概念

    viewer.scene.postProcessStages.fxaa.enabled = true

  6. 需要实时调试参数看效果时,我个人一般在控制台操作 viewer , 修改可以实时生效

    1
    2
    3
    4
    viewer.scene.light = new Cesium.DirectionalLight({
    direction: new Cesium.Cartesian3(0.2, -1.2, -0.5),
    intensity: 7,
    })
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    viewer.scene.camera.flyTo({
    // 经度 纬度 高度
    destination: Cesium.Cartesian3.fromDegrees(114.136356, 30.473618, 10000),
    // 朝向 仰角 倾斜
    orientation: {
    heading: Cesium.Math.toRadians(-90),
    pitch: Cesium.Math.toRadians(-90),
    roll: 0
    }
    })
  7. 加载大量单体化模型 entity 时,仅仅设置
    模型 distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, MAX_DISTANCE_FOR_MODELS)
    point 点 distanceDisplayCondition: new Cesium.DistanceDisplayCondition(MAX_DISTANCE_FOR_MODELS, Number.POSITIVE_INFINITY)
    是不够的

    因为虽然视角拉远不展示模型只展示点,但是本质上它还是 entity; 还是需要根据 level 或者相机高度 删除掉全部实体,只添加 PointPrimitiveCollection 来替换 entity , 这样做以后,在较高的相机地面距离来看,性能一般不会有瓶颈

上一篇:
记录一下手写PromiseAll
下一篇:
mapbox添加threejs原生实体