mcpField
C
cesiumjs-models-particles

cesiumjs-models-particles

github.com/cesiumgs开发193220 次安装6 周前更新
代码仓库

关于 cesiumjs-models-particles

面向 CesiumJS 开发者的 glTF/GLB 模型与粒子效果技能指南,涵盖模型加载、动画、节点变换、样式设置和粒子系统配置。

主要功能

  1. 01加载并定位 glTF/GLB 模型
  2. 02控制模型动画与节点
  3. 03设置模型样式并拾取要素
  4. 04创建粒子效果

适用场景

  1. 01在 CesiumJS 场景中放置并动画化模型
  2. 02设置带要素 ID 的模型内容样式
  3. 03制作烟雾、火焰或雨效

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cesiumgs/cesiumjs-skills --skill cesiumjs-models-particles

安装后在 Claude Code 中输入/cesiumjs-models-particles确认已加载。

附带文件REFERENCE.md

详细介绍

CesiumJS 模型、glTF 与粒子效果

基准版本:CesiumJS v1.144。

快速参考

类用途
Model底层 glTF/GLB 基元;通过 modelMatrix 定位
ModelAnimation模型上的活动动画实例
ModelAnimationCollectionmodel.activeAnimations 中的集合
ModelNode可修改变换的命名节点
ModelFeature面向要素 ID 模型的逐要素样式设置与拾取
EdgeDisplayMode控制 Model/Cesium3DTileset 上草稿 glTF 边缘可见性渲染
ParticleSystem基于广告牌的粒子管理器(火焰、烟雾、雨)
Particle单个粒子,具有位置、速度和生命周期
ParticleBurst定时发射的一组粒子
BoxEmitter / CircleEmitter在盒体体积内 / 平面圆盘内发射
ConeEmitter / SphereEmitter从圆锥顶点 / 球体内发射

Entity API 通过 ModelGraphics 提供模型(参见 cesiumjs-entities)。Primitive API 使用 Model.fromGltfAsync,以全面控制 modelMatrix、动画和节点变换。


加载 glTF/GLB 模型

始终使用异步工厂——切勿直接调用构造函数。

import { Model, Cartesian3, Transforms, HeadingPitchRoll, Math as CesiumMath } from "cesium";

const model = await Model.fromGltfAsync({ url: "path/to/model.glb" });
viewer.scene.primitives.add(model);
公共示例模型

CesiumJS 附带可在无需 ion 令牌的情况下使用的示例模型:

https://raw.githubusercontent.com/CesiumGS/cesium/main/Apps/SampleData/models/CesiumAir/Cesium_Air.glb
https://raw.githubusercontent.com/CesiumGS/cesium/main/Apps/SampleData/models/CesiumMan/Cesium_Man.glb
https://raw.githubusercontent.com/CesiumGS/cesium/main/Apps/SampleData/models/CesiumMilkTruck/CesiumMilkTruck.glb

CesiumJS 1.143 会自动解码 KHR_meshopt_compression,包括 v1 属性编解码器和 COLOR 滤镜。请勿导入解码器或私有加载器辅助函数。加载压缩 glTF、CAD 风格的线条/点/边缘或恒定 LOD 纹理时,请参阅 REFERENCE.md,了解完整的支持与创作矩阵。相同的加载器行为也适用于 3D Tiles 内的 glTF 内容。

带航向角的定位模型
const position = Cartesian3.fromDegrees(-123.074, 44.050, 5000);
const hpr = new HeadingPitchRoll(CesiumMath.toRadians(135), 0, 0);

const model = await Model.fromGltfAsync({
  url: "CesiumAir.glb",
  modelMatrix: Transforms.headingPitchRollToFixedFrame(position, hpr),
  minimumPixelSize: 128,  // never smaller than 128 px on screen
  maximumScale: 20000,    // cap for minimumPixelSize enlargement
  scale: 2.0,             // uniform scale multiplier
});
viewer.scene.primitives.add(model);

**视觉评估构图:**模型截图中,模型必须完整位于画面内且清晰可辨,不能被底部边缘裁切。公共示例飞机模型的 minimumPixelSize 设为 256-400,添加柔和的 silhouetteColor/silhouetteSize,并使用显式坐标定位相机,使其朝向已知的模型位置。避免采用较小的俯仰角,导致模型出现在画面下方;也不要依赖 viewer.flyTo(model),因为它对 Model 基元的行为会因版本而异。

避免模型外观失真

非均匀缩放或方向矩阵构造错误时,模型可能会显得拉伸或扭曲。常见问题包括:

  • **地面对齐方向始终使用 Transforms.headingPitchRollToFixedFrame(或 Entity API 的 headingPitchRollQuaternion)。**手动构造的四元数经常会反转俯仰/滚转轴,导致轮廓垂直拉伸。
  • **使用(均匀)scale 调整尺寸,不要使用非均匀的 Matrix4.fromScale。**烘焙到 modelMatrix 中的非均匀缩放会使模型失真。Matrix4.fromScale 应用于逐节点微调(例如拉伸单个炮塔),而非整个模型。
  • **将 minimumPixelSize 与合理的 maximumScale 配合使用。**如果没有上限,远处的小模型可能会膨胀到占满画面,并在相机靠近时显得细长。
Model.fromGltfAsync 的关键选项
选项类型默认值
urlstring|Resource必填
modelMatrixMatrix4IDENTITY
scalenumber1.0
minimumPixelSizenumber0.0
maximumScalenumber--
showbooleantrue
color / colorBlendMode / colorBlendAmountColor / ColorBlendMode / number-- / HIGHLIGHT / 0.5
edgeDisplayModeEdgeDisplayModeSURFACES_ONLY
silhouetteColor / silhouetteSizeColor / numberRED / 0.0
shadowsShadowModeENABLED
heightReferenceHeightReferenceNONE
customShaderCustomShader--
idany--
allowPickingbooleantrue

就绪状态和生命周期

fromGltfAsync 会在解析完 glTF JSON 后完成,但 WebGL 资源可能仍在加载。在访问动画、节点或 boundingSphere 前,请等待 readyEvent。

const model = await Model.fromGltfAsync({ url: "robot.glb" });
viewer.scene.primitives.add(model);

model.readyEvent.addEventListener(() => {
  console.log("Bounding sphere:", model.boundingSphere);
});
// Synchronous check
if (model.ready) { const bs = model.boundingSphere; }

动画

通过 model.activeAnimations(ModelAnimationCollection)管理。

按名称播放 / 播放全部
model.readyEvent.addEventListener(() => {
  // Single animation
  const anim = model.activeAnimations.add({
    name: "Walk",                          // glTF animation name
    loop: Cesium.ModelAnimationLoop.REPEAT, // NONE | REPEAT | MIRRORED_REPEAT
    multiplier: 1.0,                       // playback speed (must be > 0)
  });
  anim.start.addEventListener((m, a) => console.log(`Started: ${a.name}`));

  // Or play all animations at once
  model.activeAnimations.addAll({
    loop: Cesium.ModelAnimationLoop.REPEAT,
    multiplier: 0.5,
  });
});

其他 add 选项:index、reverse、startTime、stopTime、delay、removeOnStop、animationTime(自定义时间回调)。

动画需要 viewer.clock.shouldAnimate = true 才会推进。 如果时钟已停止,行走中的角色会看起来定格在某个姿势(或在关键帧交界处显得扭曲)。

动画事件
animation.start.addEventListener((model, animation) => { });
animation.update.addEventListener((model, animation, time) => { });
animation.stop.addEventListener((model, animation) => { });
// Collection-level
model.activeAnimations.animationAdded.addEventListener((model, anim) => { });
model.activeAnimations.remove(animation); // remove one
model.activeAnimations.removeAll();        // remove all

模型节点

覆盖命名节点的变换,用于程序化动画(例如炮塔旋转)。

model.readyEvent.addEventListener(() => {
  const node = model.getNode("Turret");
  node.matrix = Cesium.Matrix4.fromScale(
    new Cesium.Cartesian3(5.0, 1.0, 1.0), node.matrix
  );
});

属性:name(只读)、id(只读索引)、show(布尔值)、matrix(Matrix4——设为 undefined 可恢复原始变换并重新启用 glTF 动画)。


着色、轮廓和要素拾取

// Tint + silhouette
model.color = Cesium.Color.RED.withAlpha(0.5);
model.colorBlendMode = Cesium.ColorBlendMode.MIX;
model.colorBlendAmount = 0.5;
model.silhouetteColor = Cesium.Color.YELLOW;
model.silhouetteSize = 2.0;
边缘显示模式(实验性,1.142+)

对于使用草案版 EXT_mesh_primitive_edge_visibility 扩展的 glTF 资源, EdgeDisplayMode 用于控制隐藏扩展提供的边缘、将其叠加显示在表面上,还是仅渲染边缘。不含该扩展的模型不受影响。

import { EdgeDisplayMode, Model } from "cesium";

const model = await Model.fromGltfAsync({
  url: "/models/cad-part.glb",
  edgeDisplayMode: EdgeDisplayMode.SURFACES_AND_EDGES,
});
viewer.scene.primitives.add(model);

model.edgeDisplayMode = EdgeDisplayMode.EDGES_ONLY;       // CAD-style wireframe
model.edgeDisplayMode = EdgeDisplayMode.SURFACES_ONLY;    // default

当 glTF 含有 EXT_mesh_features 或 EXT_structural_metadata 时,拾取会返回一个 ModelFeature:

const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((movement) => {
  const picked = viewer.scene.pick(movement.endPosition);
  if (picked instanceof Cesium.ModelFeature) {
    picked.getPropertyIds().forEach((name) => {
      console.log(`${name}: ${picked.getProperty(name)}`);
    });
    picked.color = Cesium.Color.YELLOW;
  }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

高度参考

// Primitive API -- scene is required for height reference
const model = await Model.fromGltfAsync({
  url: "truck.glb",
  heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
  scene: viewer.scene,
});

// Entity API
viewer.entities.add({
  position: Cartesian3.fromDegrees(-75.59, 40.03),
  model: { uri: "truck.glb", heightReference: Cesium.HeightReference.CLAMP_TO_GROUND },
});

取值:NONE、CLAMP_TO_GROUND、RELATIVE_TO_GROUND、CLAMP_TO_TERRAIN、RELATIVE_TO_TERRAIN、CLAMP_TO_3D_TILE、RELATIVE_TO_3D_TILE。


粒子系统

ParticleSystem 用于渲染基于广告牌的效果。使用 modelMatrix(世界坐标)和 emitterModelMatrix(局部偏移)设置位置。

添加粒子系统前,务必设置 viewer.clock.shouldAnimate = true——只有时钟运行时,粒子才会移动。时钟停止时,发射器原点处只会出现静止的“团块”,而非有方向性的羽流。

生成清晰可辨的垂直羽流

常见的问题是渲染出弥散的球状团块,而不是清晰可辨、向上升起的柱状效果。若要让羽流呈现垂直形态:

  • 使用 CircleEmitter 或窄角度的 ConeEmitter 来产生向上的速度。SphereEmitter 和 BoxEmitter 会向各个方向发射粒子,产生类似团块的形状。
  • 让速度明显偏向上方——在 modelMatrix 坐标系中,发射器的局部 +Z 轴朝上;请通过 Transforms.eastNorthUpToFixedFrame 设置 modelMatrix,使 +Z 轴朝向局部上方。
  • 将 minimumParticleLife / maximumParticleLife 设为数秒(例如 1.5-4.0),让粒子在淡出前移动足够远,形成可见的柱状效果。
  • 让粒子在生命周期内逐渐放大(startScale 设小,endScale 设为其 3-6 倍),使羽流随高度逐渐变宽,符合真实烟雾的形态。
  • 让发射器的占地范围小于羽流的可见范围。 对于火山口烟雾,使用小圆盘或点源;过大的地面椭圆会喧宾夺主,看起来像主体而不是源标记。
  • 不要通过放大羽流来解决裁切问题。 如果顶部被裁切,请先增大相机距离,或减小粒子寿命、速度或 endScale;不要让羽流占满画面的四条边。
  • 截图前等待数秒的模拟时间——羽流需要时间才能形成。推进时钟,或设置 viewer.clock.shouldAnimate = true 后等待。
烟雾轨迹
import { ParticleSystem, CircleEmitter, Color, Cartesian2, Transforms, Cartesian3 } from "cesium";

viewer.clock.shouldAnimate = true; // required -- particles don't move on a stopped clock

const smokeSystem = new ParticleSystem({
  image: "smoke.png",
  startColor: Color.LIGHTGRAY.withAlpha(0.7),
  endColor: Color.WHITE.withAlpha(0.0),
  startScale: 1.0,
  endScale: 5.0,
  emissionRate: 10,
  minimumSpeed: 1.0,
  maximumSpeed: 4.0,
  minimumParticleLife: 1.2,
  maximumParticleLife: 3.0,
  imageSize: new Cartesian2(25, 25), // pixel size
  emitter: new CircleEmitter(2.0),   // radius in meters
  modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.157, 39.978)),
  lifetime: 16.0,
  loop: true,
});
viewer.scene.primitives.add(smokeSystem);
火山/火山口烟雾校准

对于圣海伦斯山这类地形尺度的烟雾,应使用倾斜视角,并谨慎设置源标记。标记应指出发射器位置,但不能变成巨大的地面圆盘;烟柱应完整位于画面内,且下方可见地形。

import { ParticleSystem, CircleEmitter, Color, Cartesian2, Transforms, Cartesian3 } from "cesium";

viewer.clock.shouldAnimate = true;

const sourcePosition = Cartesian3.fromDegrees(-122.1944, 46.1914, 2549);

viewer.entities.add({
  position: sourcePosition,
  point: {
    pixelSize: 10,
    color: Color.ORANGE,
    outlineColor: Color.BLACK,
    outlineWidth: 2,
  },
});

const craterSmoke = new ParticleSystem({
  image: createRadialParticle(48, "rgba(180,180,180,0.75)"),
  startColor: Color.LIGHTGRAY.withAlpha(0.65),
  endColor: Color.WHITE.withAlpha(0.0),
  startScale: 0.8,
  endScale: 4.0,
  emissionRate: 35,
  minimumSpeed: 20.0,
  maximumSpeed: 45.0,
  minimumParticleLife: 2.0,
  maximumParticleLife: 4.0,
  imageSize: new Cartesian2(22, 22),
  emitter: new CircleEmitter(35.0),
  modelMatrix: Transforms.eastNorthUpToFixedFrame(sourcePosition),
  lifetime: 20.0,
  loop: true,
});
viewer.scene.primitives.add(craterSmoke);

viewer.trackedEntity = undefined;
viewer.camera.lookAt(
  sourcePosition,
  new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(35),
    Cesium.Math.toRadians(-22),
    6500
  )
);

当提示词要求在指定地理位置上方显示烟雾时,使用以下模式:

  • 优先使用 point 或小型公告牌标记,除非提示词明确要求显示地面范围,否则不要使用 ellipse。
  • 确保烟柱顶部、底部和源标记同时可见。 即使粒子正在渲染,烟柱被裁切或标记缺失也属于取景失败。
  • 高烟柱使用倾斜俯仰角。 接近天底的视角会将垂直体积压扁成灰色团块。
发射器类型
import { BoxEmitter, CircleEmitter, ConeEmitter, SphereEmitter } from "cesium";

new BoxEmitter(new Cesium.Cartesian3(10, 10, 10));  // 3D box, velocity outward
new CircleEmitter(2.0);                              // flat disk, velocity +Z
new ConeEmitter(Cesium.Math.toRadians(30));          // cone tip, velocity toward base
new SphereEmitter(5.0);                              // sphere, velocity radiates out
粒子爆发
const firework = new ParticleSystem({
  image: getParticleCanvas(),
  startColor: Color.RED,
  endColor: Color.RED.withAlpha(0.0),
  particleLife: 1.0,
  speed: 100.0,
  imageSize: new Cartesian2(7, 7),
  emissionRate: 0,  // bursts only
  emitter: new SphereEmitter(0.1),
  bursts: [
    new Cesium.ParticleBurst({ time: 0.0, minimum: 100, maximum: 200 }),
    new Cesium.ParticleBurst({ time: 2.0, minimum: 50, maximum: 100 }),
    new Cesium.ParticleBurst({ time: 4.0, minimum: 200, maximum: 300 }),
  ],
  lifetime: 6.0,
  loop: false,
  modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-75.597, 40.038)),
});
viewer.scene.primitives.add(firework);
更新回调(重力/风)

对于重力等作用力,updateCallback 会逐帧对每个粒子运行。

const gravityScratch = new Cesium.Cartesian3();
function applyGravity(particle, dt) {
  Cesium.Cartesian3.normalize(particle.position, gravityScratch);
  Cesium.Cartesian3.multiplyByScalar(gravityScratch, -9.8 * dt, gravityScratch);
  particle.velocity = Cesium.Cartesian3.add(particle.velocity, gravityScratch, particle.velocity);
}

const system = new ParticleSystem({
  image: "smoke.png",
  emissionRate: 20,
  emitter: new ConeEmitter(Cesium.Math.toRadians(45)),
  updateCallback: applyGravity,
  modelMatrix: Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(-105, 40, 1000)),
});
viewer.scene.primitives.add(system);
对粒子效果取景,让地图清晰可见

粒子效果应在下方地图的衬托下突出显示,而不是在天空或毫无特征的背景下突出显示。两种常见的取景失败情况:

  1. 相机距离太近 + 俯仰角太小 → 烟柱占满画面,地图被遮挡。
  2. 相机角度太陡/接近天底 → 高烟柱被压扁成团块,源几何形状显示不正确。

使用 viewer.camera.lookAt 和 HeadingPitchRange 锚定发射器,并调整到合适的倾斜视角,以保留地图环境信息:

const position = Cartesian3.fromDegrees(-122.1944, 46.1914, 2549);
viewer.trackedEntity = undefined;
viewer.camera.lookAt(
  position,
  new Cesium.HeadingPitchRange(
    Cesium.Math.toRadians(35),   // heading
    Cesium.Math.toRadians(-22),  // oblique pitch preserves plume height
    6500                         // increase range until top and base fit
  )
);

指南:

  • 对于短小、贴近地面的效果,若地图环境信息比垂直范围更重要,俯仰角应设为 -35° 至 -60°。
  • 对于需要体现垂直体积的高烟柱(例如火山烟柱),俯仰角应设为 -10° 至 -30°。
  • 确认标记/源位于画面内:在发射器位置添加公告牌或点;如果相机位置不正确,截图中就会看不到标记,问题一目了然。
  • 确保烟柱周围可见背景地形。 如果粒子触及多个画面边缘,请在截图前缩小粒子比例、缩短生命周期、降低速度或增大相机距离。
  • 在调用 lookAt 前将 viewer.trackedEntity = undefined 重置,否则被跟踪实体的参考坐标系会覆盖相机变换。

将粒子附加到移动模型

通过 scene.preUpdate 每帧同步 modelMatrix。使用 emitterModelMatrix 设置局部偏移(例如排气管)。

const entity = viewer.entities.add({
  position: sampledPosition,
  orientation: new Cesium.VelocityOrientationProperty(sampledPosition),
  model: { uri: "truck.glb", minimumPixelSize: 64 },
});

// Local offset to exhaust pipe
const trs = new Cesium.TranslationRotationScale();
trs.translation = new Cesium.Cartesian3(-4.0, 0.0, 1.4);
const emitterModelMatrix = Cesium.Matrix4.fromTranslationRotationScale(trs, new Cesium.Matrix4());

const exhaust = new ParticleSystem({
  image: "smoke.png",
  startColor: Color.GRAY.withAlpha(0.7),
  endColor: Color.TRANSPARENT,
  emissionRate: 8,
  speed: 2.0,
  particleLife: 1.5,
  imageSize: new Cartesian2(20, 20),
  emitter: new CircleEmitter(0.5),
  emitterModelMatrix: emitterModelMatrix,
});
viewer.scene.primitives.add(exhaust);

viewer.scene.preUpdate.addEventListener((scene, time) => {
  exhaust.modelMatrix = entity.computeModelMatrix(time, new Cesium.Matrix4());
});

基于 Canvas 的粒子图像

动态生成粒子纹理,而不是加载图像文件。径向渐变可以为烟雾和水效果生成柔和、逼真的边缘。

// Soft radial-gradient particle (smoke, water, fog)
function createRadialParticle(size = 32, colorStop = "rgba(200,200,200,0.9)") {
  const c = document.createElement("canvas");
  c.width = c.height = size;
  const ctx = c.getContext("2d");
  const half = size / 2;
  const grad = ctx.createRadialGradient(half, half, 0, half, half, half);
  grad.addColorStop(0, colorStop);
  grad.addColorStop(1, "rgba(0,0,0,0)");
  ctx.fillStyle = grad;
  ctx.fillRect(0, 0, size, size);
  return c;
}

// Solid circle (high-contrast, fireworks, sparks)
function createCircleImage(size = 20) {
  const c = document.createElement("canvas");
  c.width = c.height = size;
  const ctx = c.getContext("2d");
  ctx.beginPath();
  ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
  ctx.fillStyle = "#fff";
  ctx.fill();
  return c;
}

// Pass canvas directly as image
new ParticleSystem({ image: createRadialParticle(), /* ...other options */ });

当命名颜色无法满足需求时,可使用 Color.fromCssColorString 设置特定的粒子颜色:

startColor: Cesium.Color.fromCssColorString("#66ccff").withAlpha(0.95),
endColor: Cesium.Color.WHITE.withAlpha(0.0),

Entity API 模型(ModelGraphics)

对于较简单的用例,可通过 Entity API 添加模型(完整说明请参阅 cesiumjs-entities)。

const entity = viewer.entities.add({
  name: "Aircraft",
  position: Cartesian3.fromDegrees(-123.074, 44.050, 5000),
  orientation: Cesium.Transforms.headingPitchRollQuaternion(
    Cartesian3.fromDegrees(-123.074, 44.050, 5000),
    new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(135), 0, 0)
  ),
  model: {
    uri: "CesiumAir.glb",
    minimumPixelSize: 128,
    maximumScale: 20000,
    silhouetteColor: Color.RED,
    silhouetteSize: 2.0,
  },
});
viewer.trackedEntity = entity;

使用 viewer.trackedEntity 时的取景权衡: 跟踪会将模型居中,但会根据包围球自动计算距离,这通常会导致镜头太近、环境信息不足。对于既要求显示模型又要求保留地图环境信息(地形、地标、标签)的提示词,优先使用 viewer.camera.flyTo / lookAt 移动到手动选择的位置,并先清除 viewer.trackedEntity = undefined。


GPM 扩展(NGA_gpm_local)

CesiumJS 以实验性方式支持 NGA Geospatial Positioning Metadata glTF 扩展。类型:AnchorPointDirect、AnchorPointIndirect、CorrelationGroup、GltfGpmLocal、Spdcf。加载带有 NGA_gpm_local 的 glTF 时会自动解析——该 API 处于实验阶段,可能发生变化。


性能提示

  1. 优先使用 .glb 而非 .gltf —— 二进制格式可避免额外的 HTTP 请求,传输的数据也更小。
  2. 启用 Draco 压缩(KHR_draco_mesh_compression),可将网格体积缩小 80-90%。
  3. 使用 KTX2/Basis 纹理(KHR_texture_basisu)实现 GPU 压缩纹理;尺寸保持为 2 的幂。
  4. 谨慎设置 minimumPixelSize —— 较大的值会强制放大远处的模型,增加绘制开销。
  5. 限制轮廓效果 —— 每个带轮廓的模型都会增加一次渲染过程;超过 256 个可能导致模板缓冲区伪影。
  6. 重复使用临时 Matrix4 对象 —— 将粒子系统同步到移动实体时,避免每帧都分配对象。
  7. 根据效果密度匹配发射率 —— 高密度喷射效果(喷泉、火焰)可能需要 200-1000/s 的发射率;稀疏烟雾使用 10-60/s 效果良好。请在目标硬件上进行性能分析。
  8. 优先使用像素大小的粒子(sizeInMeters: false,默认值)—— 近距离下,以米为单位的粒子开销较大。
  9. 为粒子系统设置有限的 lifetime —— Number.MAX_VALUE(默认值)会阻止清理对象池。
  10. 为装饰性模型禁用拾取 —— 对无需交互的模型设置 allowPicking: false 可节省 GPU 内存。
  11. 用完后销毁 —— 先执行 viewer.scene.primitives.remove(model),再执行 model.destroy(),以释放 WebGL 资源。

另请参阅

  • cesiumjs-custom-shader —— 为 Model.customShader 编写 GLSL(结构体参考、要素 ID、元数据、顶点位移)
  • cesiumjs-materials-shaders —— ImageBasedLighting、模型的后处理阶段
  • cesiumjs-entities —— Entity API ModelGraphics、数据源、随时间动态变化的属性
  • cesiumjs-3d-tiles —— Cesium3DTileset(内部使用 Model)、裁剪、样式

评论

支持 Markdown