| name | cesiumjs-terrain-environment |
| description | CesiumJS terrain, globe, and environment - TerrainProvider, Globe, sampleTerrain, atmosphere, sky, fog, lighting, shadows, panoramas. Use when configuring terrain providers, querying terrain heights, customizing atmosphere or sky rendering, adding panoramas, or adjusting scene lighting and shadows. |
CesiumJS Terrain, Globe & Environment
Version baseline: CesiumJS v1.143 | ES module imports (import { ... } from "cesium";)
Terrain Providers
Terrain is served through TerrainProvider implementations. Use async factory methods
(fromIonAssetId, fromUrl), not the constructor directly.
Cesium Ion World Terrain
import { Viewer, Terrain } from "cesium";
const viewer = new Viewer("cesiumContainer", {
terrain: Terrain.fromWorldTerrain({
requestVertexNormals: true,
requestWaterMask: true,
}),
});
CesiumTerrainProvider from Ion Asset / URL
import { CesiumTerrainProvider } from "cesium";
const tp = await CesiumTerrainProvider.fromIonAssetId(3956, {
requestVertexNormals: true,
});
viewer.scene.globe.terrainProvider = tp;
const tp2 = await CesiumTerrainProvider.fromUrl(
"https://my-server.example.com/terrain",
{ requestVertexNormals: true },
);
EllipsoidTerrainProvider (Flat Globe)
import { EllipsoidTerrainProvider } from "cesium";
viewer.scene.globe.terrainProvider = new EllipsoidTerrainProvider();
CustomHeightmapTerrainProvider (Procedural)
import { CustomHeightmapTerrainProvider } from "cesium";
viewer.scene.globe.terrainProvider = new CustomHeightmapTerrainProvider({
width: 32,
height: 32,
callback: function (x, y, level) {
const buf = new Float32Array(32 * 32);
for (let r = 0; r < 32; r++) {
for (let c = 0; c < 32; c++) {
buf[r * 32 + c] = Math.sin((x + c / 32) * 6.28) * 5000;
}
}
return buf;
},
});
Sampling Terrain Heights
Both functions mutate the input Cartographic[] in place (setting .height) and
return a promise resolving to the same array.
import { sampleTerrain, sampleTerrainMostDetailed, Cartographic } from "cesium";
const positions = [
Cartographic.fromDegrees(86.925145, 27.988257),
Cartographic.fromDegrees(87.0, 28.0),
];
await sampleTerrain(viewer.scene.globe.terrainProvider, 11, positions);
await sampleTerrainMostDetailed(viewer.scene.globe.terrainProvider, positions);
await sampleTerrainMostDetailed(provider, positions, true);
Clamped-Height Callback Correctness (1.143+)
CesiumJS 1.143 fixes the internal Scene.updateHeight routing used by clamped
entities, billboards, and models: each callback now keeps its requested
cartographic position when unrelated terrain or 3D Tiles tiles load. Prefer
public HeightReference values and upgrade to 1.143+ rather than calling the
private Scene.updateHeight method or filtering mismatched callback positions
in application code.
Globe Configuration
Access via viewer.scene.globe. Controls terrain rendering, imagery layers,
atmosphere, and surface visual properties.
const globe = viewer.scene.globe;
globe.show = true;
globe.maximumScreenSpaceError = 2;
globe.tileCacheSize = 100;
globe.enableLighting = true;
globe.dynamicAtmosphereLighting = true;
globe.dynamicAtmosphereLightingFromSun = false;
globe.lambertDiffuseMultiplier = 0.9;
globe.showGroundAtmosphere = true;
globe.atmosphereHueShift = 0.0;
globe.atmosphereSaturationShift = 0.0;
globe.atmosphereBrightnessShift = 0.0;
globe.depthTestAgainstTerrain = false;
globe.showWaterEffect = true;
globe.shadows = Cesium.ShadowMode.RECEIVE_ONLY;
globe.baseColor = Cesium.Color.BLUE;
globe. = ;
globe. = ;
Globe.pick and Globe.getHeight
const ray = viewer.camera.getPickRay(windowPosition);
const hit = viewer.scene.globe.pick(ray, viewer.scene);
const h = viewer.scene.globe.getHeight(Cesium.Cartographic.fromDegrees(-105, 40));
Terrain Exaggeration
viewer.scene.verticalExaggeration = 2.0;
viewer.scene.verticalExaggerationRelativeHeight = 0.0;
Globe Translucency
Makes the globe see-through for underground/subsurface visualization.
const globe = viewer.scene.globe;
globe.translucency.enabled = true;
globe.translucency.frontFaceAlpha = 0.5;
globe.translucency.backFaceAlpha = 1.0;
globe.translucency.frontFaceAlphaByDistance = new Cesium.NearFarScalar(
1.5e2, 0.5,
8.0e6, 1.0,
);
globe.translucency.rectangle = Cesium.Rectangle.fromDegrees(-120, 30, -80, 50);
Elevation Band Material
Color the globe surface by elevation.
import { createElevationBandMaterial, Color } from "cesium";
viewer.scene.globe.material = createElevationBandMaterial({
scene: viewer.scene,
layers: [{
entries: [
{ height: 0, color: new Color(0.0, 0.0, 0.5, 1.0) },
{ height: 500, color: new Color(0.0, 0.8, 0.0, 1.0) },
{ height: 2000, color: new Color(0.6, 0.3, 0.1, 1.0) },
{ height: 5000, color: Color.WHITE },
],
}],
});
SkyAtmosphere
Atmospheric haze ring around the globe limb. 3D mode only.
const sky = viewer.scene.skyAtmosphere;
sky.show = true;
sky.perFragmentAtmosphere = false;
sky.atmosphereLightIntensity = 50.0;
sky.hueShift = 0.0;
sky.saturationShift = 0.0;
sky.brightnessShift = 0.0;
sky.atmosphereRayleighCoefficient = new Cesium.Cartesian3(5.5e-6, 13.0e-6, 28.4e-6);
sky.atmosphereMieCoefficient = new Cesium.Cartesian3(21e-6, 21e-6, 21e-6);
sky.atmosphereMieAnisotropy = 0.9;
SkyBox
Star field cube map behind the globe. 3D mode only.
import { SkyBox } from "cesium";
viewer.scene.skyBox = SkyBox.createEarthSkyBox();
viewer.scene.skyBox = new SkyBox({
sources: {
positiveX: "skybox_px.png", negativeX: "skybox_nx.png",
positiveY: "skybox_py.png", negativeY: "skybox_ny.png",
positiveZ: "skybox_pz.png", negativeZ: "skybox_nz.png",
},
});
Fog
Blends distant terrain toward atmosphere color and culls far tiles. 3D mode only.
const fog = viewer.scene.fog;
fog.enabled = true;
fog.renderable = true;
fog.density = 0.0006;
fog.visualDensityScalar = 0.15;
fog.maxHeight = 800000.0;
fog.heightFalloff = 0.59;
fog.screenSpaceErrorFactor = 2.0;
fog.minimumBrightness = 0.03;
Sun and Moon
viewer.scene.sun = new Cesium.Sun();
viewer.scene.sun.show = true;
viewer.scene.moon.show = true;
Lighting
scene.light controls the scene light source. Default is SunLight (follows clock).
import { SunLight, DirectionalLight, Cartesian3, Color } from "cesium";
viewer.scene.light = new SunLight({ color: Color.WHITE, intensity: 2.0 });
viewer.scene.light = new DirectionalLight({
direction: new Cartesian3(0.2, -0.5, -0.8),
color: Color.WHITE,
intensity: 1.5,
});
viewer.scene.globe.enableLighting = true;
DynamicAtmosphereLightingType enum (NONE, SCENE_LIGHT, SUNLIGHT) is configured
via globe.enableLighting, globe.dynamicAtmosphereLighting, and
globe.dynamicAtmosphereLightingFromSun flags.
Shadows
Cascaded shadow maps from the scene light source.
viewer.shadows = true;
const sm = viewer.shadowMap;
sm.maximumDistance = 5000.0;
sm.softShadows = true;
sm.darkness = 0.3;
sm.fadingEnabled = true;
viewer.scene.globe.shadows = Cesium.ShadowMode.RECEIVE_ONLY;
Panoramas (v1.139+)
360-degree imagery at a scene location. Two formats: equirectangular and cube map.
EquirectangularPanorama
import {
EquirectangularPanorama, Cartesian3,
HeadingPitchRoll, Transforms, Math as CesiumMath,
} from "cesium";
const position = Cartesian3.fromDegrees(-75.17, 39.95, 100.0);
const hpr = new HeadingPitchRoll(CesiumMath.toRadians(45), 0, 0);
const transform = Transforms.headingPitchRollToFixedFrame(position, hpr);
viewer.scene.primitives.add(new EquirectangularPanorama({
transform,
image: "path/to/equirectangular-360.jpg",
radius: 100000.0,
}));
CubeMapPanorama
import { CubeMapPanorama, Cartesian3, Transforms, Matrix3, Matrix4 } from "cesium";
const pos = Cartesian3.fromDegrees(-122.42, 37.77, 10.0);
const northDown = Transforms.localFrameToFixedFrameGenerator("north", "down");
const xform = Matrix4.getMatrix3(northDown(pos), new Matrix3());
viewer.scene.primitives.add(new CubeMapPanorama({
sources: {
positiveX: "px.jpg", negativeX: "nx.jpg",
positiveY: "py.jpg", negativeY: "ny.jpg",
positiveZ: "pz.jpg", negativeZ: "nz.jpg",
},
transform: xform,
}));
GoogleStreetViewCubeMapPanoramaProvider
import { GoogleStreetViewCubeMapPanoramaProvider, Cartographic } from "cesium";
const provider = new GoogleStreetViewCubeMapPanoramaProvider({
key: "YOUR_GOOGLE_STREETVIEW_API_KEY",
});
const pano = await provider.loadPanorama({
cartographic: Cartographic.fromDegrees(-122.42, 37.77, 0),
});
viewer.scene.primitives.add(pano);
Terrain Provider Events
viewer.scene.globe.terrainProviderChanged.addEventListener((newProvider) => {
console.log("Terrain changed:", newProvider.constructor.name);
});
Performance Tips
- Increase
maximumScreenSpaceError from 2 to 4+ on mobile -- single biggest
terrain perf knob.
- Keep fog enabled (default) -- culls distant tiles, reducing draw calls.
- Avoid per-frame
verticalExaggeration changes -- forces terrain tile reloads.
- Set
requestVertexNormals: true only when lighting is enabled -- doubles tile size.
- Skip
requestWaterMask (default false) when showWaterEffect is off.
- Prefer
sampleTerrain over sampleTerrainMostDetailed when approximate heights
suffice -- resolves faster with fewer tile requests.
- Batch terrain sampling -- pass all positions in one array to share tile loads.
- Tune
tileCacheSize -- increase for zoom-heavy workflows, decrease for memory.
- Disable
showGroundAtmosphere on non-Earth ellipsoids to avoid artifacts.
- Keep
depthTestAgainstTerrain = false (default) to avoid z-fighting with
labels and billboards near the surface.
Quick Reference
| Class / Function | Purpose |
|---|
CesiumTerrainProvider.fromIonAssetId(id, opts) | Ion terrain asset |
CesiumTerrainProvider.fromUrl(url, opts) | Self-hosted terrain |
EllipsoidTerrainProvider | Flat ellipsoid (no terrain) |
CustomHeightmapTerrainProvider | Procedural/callback terrain |
ArcGISTiledElevationTerrainProvider | ArcGIS elevation service |
sampleTerrain(provider, level, positions) | Heights at fixed LOD |
sampleTerrainMostDetailed(provider, positions) | Heights at max LOD |
Globe | Surface rendering, terrain, atmosphere |
GlobeTranslucency | See-through globe for underground views |
createElevationBandMaterial | Color surface by elevation |
SkyAtmosphere | Atmospheric limb glow |
SkyBox / SkyBox.createEarthSkyBox() | Star field cube map |
Fog | Distance fog and terrain culling |
Sun / Moon | Celestial body rendering |
SunLight | Light following the Sun |
DirectionalLight | Fixed-direction light |
ShadowMap | Cascaded shadow maps |
EquirectangularPanorama | 360-degree panorama |
CubeMapPanorama | Cube map panorama |
GoogleStreetViewCubeMapPanoramaProvider | Google Street View panoramas |
DynamicAtmosphereLightingType | Enum: NONE, SCENE_LIGHT, SUNLIGHT |
ShadowMode | Enum: DISABLED, ENABLED, CAST_ONLY, RECEIVE_ONLY |
See Also
- cesiumjs-viewer-setup -- Viewer initialization, Ion token, Scene configuration
- cesiumjs-imagery -- Imagery providers and layer management
- cesiumjs-spatial-math -- Cartesian3, Cartographic, Transforms, coordinate math