| name | cesiumjs-3d-tiles |
| description | CesiumJS 3D Tiles - Cesium3DTileset, styling, metadata, feature picking, voxels, point clouds, I3S, Gaussian splats, clipping planes and polygons. Use when loading 3D Tiles tilesets, styling building features, querying metadata properties, working with voxels or point clouds, or clipping spatial data. |
CesiumJS 3D Tiles
Version baseline: CesiumJS v1.139 (ES module imports, async factory methods).
Loading a Tileset
Always use async factory methods -- never call the constructor directly.
import { Cesium3DTileset, HeadingPitchRange, Math as CesiumMath } from "cesium";
const tileset = await Cesium3DTileset.fromUrl(
"https://example.com/tileset.json",
{ maximumScreenSpaceError: 16 },
);
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset, new HeadingPitchRange(
0.0, CesiumMath.toRadians(-25.0), tileset.boundingSphere.radius * 2.0,
));
const tileset = await Cesium3DTileset.fromIonAssetId(75343);
viewer.scene.primitives.add(tileset);
import { createGooglePhotorealistic3DTileset } from "cesium";
const google3D = await createGooglePhotorealistic3DTileset({
onlyUsingWithGoogleGeocoder: true,
});
viewer.scene.primitives.add(google3D);
import { createOsmBuildingsAsync } from "cesium";
const osmBuildings = await createOsmBuildingsAsync();
viewer.scene.primitives.add(osmBuildings);
Key Constructor Options
| Option | Default | Purpose |
|---|
maximumScreenSpaceError | 16 | LOD quality threshold (pixels) |
cacheBytes | 536870912 | Tile cache trim target (bytes) |
maximumCacheOverflowBytes | 536870912 | Extra cache headroom |
shadows | ShadowMode.ENABLED | Shadow casting/receiving |
modelMatrix | Matrix4.IDENTITY | Root transform |
clippingPlanes | undefined | ClippingPlaneCollection |
clippingPolygons | undefined | ClippingPolygonCollection (WebGL 2) |
enableCollision | false | Camera collision with tileset surface |
pointCloudShading | undefined | Point attenuation options object |
classificationType | undefined | TERRAIN, CESIUM_3D_TILE, or BOTH |
dynamicScreenSpaceError | true | Horizon LOD optimization |
foveatedScreenSpaceError | true | Center-screen tile priority |
preloadFlightDestinations | true | Prefetch tiles at flight target |
featureIdLabel | "featureId_0" | EXT_mesh_features ID set label |
backFaceCulling | true | Cull back faces per glTF material |
Tileset Events
tileset.loadProgress.addEventListener((pending, processing) => {
if (pending === 0 && processing === 0) console.log("Loaded");
});
tileset.initialTilesLoaded.addEventListener(() => { });
tileset.allTilesLoaded.addEventListener(() => { });
tileset.tileLoad.addEventListener((tile) => { });
tileset.tileUnload.addEventListener((tile) => { });
tileset.tileFailed.addEventListener(({ url, message }) => {
console.error(`Tile ${url}: ${message}`);
});
tileset.tileVisible.addEventListener((tile) => {
const content = tile.content;
for (let i = 0; i < content.featuresLength; i++) {
content.getFeature(i).color = Cesium.Color.fromRandom();
}
});
Runtime Properties
tileset.show = false;
tileset.maximumScreenSpaceError = 8;
const { center, radius } = tileset.boundingSphere;
import { Matrix4, Cartesian3 } from "cesium";
tileset.modelMatrix = Matrix4.fromTranslation(new Cartesian3(0, 0, 100));
Declarative Styling
Assign a Cesium3DTileStyle to tileset.style. Expressions reference feature
properties with ${PropertyName}.
import { Cesium3DTileStyle } from "cesium";
tileset.style = new Cesium3DTileStyle({
color: {
conditions: [
["${Height} >= 100", "color('purple', 0.5)"],
["${Height} >= 50", "color('red')"],
["true", "color('blue')"],
],
},
show: "${Height} > 0",
});
tileset.style = new Cesium3DTileStyle({
defines: { material: "${feature['building:material']}" },
color: {
conditions: [
["${material} === null", "color('white')"],
["${material} === 'glass'", "color('skyblue', 0.5)"],
["${material} === 'brick'", "color('indianred')"],
["true", "color('white')"],
],
},
});
tileset.style = new Cesium3DTileStyle({
show: "${feature['building']} === 'office'",
});
tileset.style = new Cesium3DTileStyle({
color: "vec4(${Temperature})",
pointSize: "${Temperature} * 2.0",
});
tileset.style = undefined;
Color Blend Modes
import { Cesium3DTileColorBlendMode } from "cesium";
tileset.colorBlendMode = Cesium3DTileColorBlendMode.REPLACE;
tileset.colorBlendAmount = 0.5;
Feature Picking and Properties
Scene.pick returns Cesium3DTileFeature for 3D Tiles features. Modifications
persist until the owning tile is evicted from the cache.
import {
ScreenSpaceEventHandler, ScreenSpaceEventType,
Cesium3DTileFeature, Color,
} from "cesium";
const handler = new ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction((movement) => {
const feature = viewer.scene.pick(movement.endPosition);
if (feature instanceof Cesium3DTileFeature) {
const ids = feature.getPropertyIds();
for (const id of ids) console.log(`${id}: ${feature.getProperty(id)}`);
feature.color = Color.YELLOW;
}
}, ScreenSpaceEventType.MOUSE_MOVE);
handler.setInputAction((movement) => {
const feature = viewer.scene.pick(movement.position);
if (feature instanceof Cesium3DTileFeature) {
console.log("Height:", feature.getProperty("Height"));
feature.setProperty("selected", true);
feature.show = false;
}
}, ScreenSpaceEventType.LEFT_CLICK);
Inherited Metadata (3D Tiles 1.1 / EXT_structural_metadata)
const value = feature.getPropertyInherited("semanticOrPropertyName");
Clipping Planes
ClippingPlaneCollection clips via half-space planes in the tileset's local
coordinate system.
import {
ClippingPlane, ClippingPlaneCollection,
Cartesian3, Color, Matrix4,
} from "cesium";
const clippingPlanes = new ClippingPlaneCollection({
planes: [new ClippingPlane(new Cartesian3(0.0, 0.0, -1.0), 0.0)],
edgeWidth: 1.0,
edgeColor: Color.WHITE,
unionClippingRegions: false,
});
const tileset = await Cesium3DTileset.fromUrl(url, { clippingPlanes });
clippingPlanes.modelMatrix = Matrix4.fromTranslation(new Cartesian3(0, 0, 50));
clippingPlanes.get(0).distance = 25.0;
Clipping Polygons
ClippingPolygonCollection clips using arbitrary polygons. WebGL 2 only.
import { ClippingPolygon, ClippingPolygonCollection, Cartesian3 } from "cesium";
const polygon = new ClippingPolygon({
positions: Cartesian3.fromDegreesArray([
-105.0077, 39.7519, -105.0095, 39.7504,
-105.0071, 39.7513, -105.0077, 39.7519,
]),
});
tileset.clippingPolygons = new ClippingPolygonCollection({
polygons: [polygon],
inverse: false,
});
viewer.scene.globe.clippingPolygons = new ClippingPolygonCollection({
polygons: [polygon],
});
Point Cloud Shading
const tileset = await Cesium3DTileset.fromUrl(pointCloudUrl, {
pointCloudShading: {
attenuation: true,
geometricErrorScale: 1.0,
maximumAttenuation: 10,
eyeDomeLighting: true,
eyeDomeLightingStrength: 1.0,
eyeDomeLightingRadius: 1.0,
backFaceCulling: false,
normalShading: true,
},
});
viewer.scene.primitives.add(tileset);
tileset.pointCloudShading.eyeDomeLightingStrength = 2.0;
Voxel Primitives
VoxelPrimitive renders volumetric data from a Cesium3DTilesVoxelProvider.
Shapes: BOX, CYLINDER, ELLIPSOID (see VoxelShapeType).
import { VoxelPrimitive, Cesium3DTilesVoxelProvider, CustomShader } from "cesium";
const provider = await Cesium3DTilesVoxelProvider.fromUrl("voxel/tileset.json");
const voxelPrimitive = new VoxelPrimitive({
provider,
customShader: new CustomShader({
fragmentShaderText: `void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
material.diffuse = fsInput.metadata.a.rgb;
material.alpha = fsInput.metadata.a.a;
}`,
}),
});
viewer.scene.primitives.add(voxelPrimitive);
voxelPrimitive.nearestSampling = true;
viewer.camera.flyToBoundingSphere(voxelPrimitive.boundingSphere, { duration: 0 });
viewer.extend(Cesium.viewerVoxelInspectorMixin);
viewer.voxelInspector.viewModel.voxelPrimitive = voxelPrimitive;
I3S Data Provider
Load Esri I3S scene layers (3D Objects, IntegratedMesh, Building Scene Layer).
import { I3SDataProvider, ArcGISTiledElevationTerrainProvider, Ellipsoid, Rectangle } from "cesium";
const geoidService = await ArcGISTiledElevationTerrainProvider.fromUrl(
"https://tiles.arcgis.com/tiles/.../EGM2008/ImageServer",
);
const i3sProvider = await I3SDataProvider.fromUrl(
"https://tiles.arcgis.com/tiles/.../SceneServer/layers/0",
{ geoidTiledTerrainProvider: geoidService },
);
viewer.scene.primitives.add(i3sProvider);
const center = Rectangle.center(i3sProvider.extent);
center.height = 5000.0;
viewer.camera.setView({
destination: Ellipsoid.WGS84.cartographicToCartesian(center),
});
Gaussian Splats
Loaded as standard 3D Tiles; CesiumJS handles KHR_gaussian_splatting automatically.
const splats = await Cesium3DTileset.fromIonAssetId(3667783);
viewer.scene.primitives.add(splats);
viewer.zoomTo(splats);
Classification
Drape tileset geometry as a classification overlay on terrain or other tilesets.
import { Cesium3DTileset, ClassificationType } from "cesium";
const classified = await Cesium3DTileset.fromUrl(url, {
classificationType: ClassificationType.BOTH,
});
viewer.scene.primitives.add(classified);
Adjusting Tileset Height
import { Cartographic, Cartesian3, Matrix4 } from "cesium";
const cartographic = Cartographic.fromCartesian(tileset.boundingSphere.center);
const surface = Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
const offset = Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
const translation = Cartesian3.subtract(offset, surface, new Cartesian3());
tileset.modelMatrix = Matrix4.fromTranslation(translation);
Performance Tips
- Keep
maximumScreenSpaceError as high as acceptable (16 default; 32+ for mobile).
- Leave
dynamicScreenSpaceError: true for street-level views with large tilesets.
- Leave
foveatedScreenSpaceError: true to prioritize center-screen tiles.
- Size
cacheBytes and maximumCacheOverflowBytes to device memory (512 MB each default).
- Use
preloadFlightDestinations: true to prefetch tiles at the camera flight target.
- Enable
skipLevelOfDetail: true for large replacement-refined tilesets to reduce memory.
- Avoid
maximumScreenSpaceError below 4 -- diminishing returns, many more tile requests.
- For point clouds, enable
attenuation and eyeDomeLighting to fill gaps and add depth.
- Keep
enableCollision: false unless camera collision or CLAMP_TO_GROUND on tiles is needed.
- Preload hidden tilesets with
show: false and preloadWhenHidden: true.
- Avoid translucent styles when possible -- they add rendering passes and disable optimizations.
- Listen to
tileFailed to log errors; call trimLoadedTiles() after large camera jumps.
See Also
- cesiumjs-custom-shader -- GLSL authoring for
Cesium3DTileset.customShader and VoxelPrimitive.customShader (struct reference, feature IDs, metadata)
- cesiumjs-materials-shaders -- ImageBasedLighting, post-processing stages for tilesets
- cesiumjs-interaction -- Scene.pick, drillPick, ScreenSpaceEventHandler for feature selection
- cesiumjs-terrain-environment -- Globe, terrain providers, atmosphere, lighting, shadows