How to Set Up CesiumJS with Google Photorealistic 3D Tiles
You can integrate Google Photorealistic 3D Tiles into CesiumJS by configuring API credentials, instantiating a minimal viewer with UI chrome disabled, and calling Cesium.createGooglePhotorealistic3DTileset() with error handling that falls back to the default Cesium globe.
CesiumJS enables high-performance 3D geospatial visualization in the browser, and pairing it with Google's Photorealistic 3D Tiles creates photorealistic terrain rendering suitable for cinematic applications. This guide explains the implementation pattern used in the bilawalsidhu/gods-eye-view repository, covering environment configuration, viewer optimization, and robust tileset loading with graceful degradation.
Configuring API Credentials and Environment Variables
Before rendering any tiles, you must supply both a Cesium Ion access token and a Google Maps API key. In src/main.js lines 76‑88, the repository reads these values from Vite's environment system and injects them into the Cesium runtime:
// src/main.js - lines 76-88
Cesium.Ion.defaultAccessToken = import.meta.env.CESIUM_ION_TOKEN;
Cesium.GoogleMaps.defaultApiKey = import.meta.env.GOOGLE_MAPS_API_KEY;
This approach keeps sensitive credentials out of the source tree while making them available to the browser at runtime. The corresponding environment variables (CESIUM_ION_TOKEN and GOOGLE_MAPS_API_KEY) are exposed to the client bundle through vite.config.js, ensuring the build process substitutes the correct values during compilation.
Creating a Minimal Cesium Viewer for Performance
To optimize for a cinematic, distraction-free experience, the repository disables all default UI chrome and caps the render loop at 60 frames per second. In src/main.js lines 92‑106, the viewer is instantiated with explicit flags to hide unnecessary widgets:
// src/main.js - lines 92-106
const viewer = new Cesium.Viewer('cesiumContainer', {
timeline: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
navigationHelpButton: false,
fullscreenButton: false,
vrButton: false,
selectionIndicator: false,
infoBox: false,
baseLayer: false,
creditContainer: document.getElementById('cesium-credits'),
msaaSamples: 4,
contextOptions: { webgl: { preserveDrawingBuffer: true } }
});
viewer.targetFrameRate = 60;
Setting baseLayer: false removes the default Cesium World Terrain, preparing the scene for the Google tileset. The creditContainer parameter is essential for compliance—Google requires visible attribution for their photorealistic tiles, and this dedicated DOM element allows Cesium to populate the necessary credits automatically.
Loading Google Photorealistic 3D Tiles with Graceful Degradation
The core tileset loading logic in src/main.js lines 59‑66 demonstrates a defensive pattern that attempts to load Google tiles while maintaining functionality if the service is unavailable:
// src/main.js - lines 59-66
let tileset = null;
try {
tileset = await Cesium.createGooglePhotorealistic3DTileset({
onlyUsingWithGoogleGeocoder: true
});
viewer.scene.primitives.add(tileset);
viewer.scene.globe.show = false;
} catch (e) {
console.warn('Google 3D Tiles failed – using Cesium globe instead', e);
viewer.scene.globe.show = true;
}
When Cesium.createGooglePhotorealistic3DTileset() succeeds, the code adds the tileset to the scene primitives and hides the default Cesium globe by setting viewer.scene.globe.show = false. If the request fails—due to network issues, invalid credentials, or service outages—the catch block ensures the application remains functional by re-enabling the default globe.
Complete Implementation Example
Below is a self-contained implementation that mirrors the repository's architecture. This example assumes a Vite-based build system but can be adapted to any environment that supports ES modules:
import * as Cesium from 'cesium';
// Step 1: Configure API credentials
Cesium.Ion.defaultAccessToken = import.meta.env.CESIUM_ION_TOKEN;
Cesium.GoogleMaps.defaultApiKey = import.meta.env.GOOGLE_MAPS_API_KEY;
// Step 2: Create minimal viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
timeline: false,
animation: false,
baseLayerPicker: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
navigationHelpButton: false,
fullscreenButton: false,
vrButton: false,
selectionIndicator: false,
infoBox: false,
baseLayer: false,
creditContainer: (() => {
const el = document.createElement('div');
el.id = 'cesium-credits';
document.body.appendChild(el);
return el;
})(),
msaaSamples: 4,
contextOptions: { webgl: { preserveDrawingBuffer: true } }
});
viewer.targetFrameRate = 60;
// Step 3: Load Google Photorealistic 3D Tiles
async function loadTileset() {
try {
const tileset = await Cesium.createGooglePhotorealistic3DTileset({
onlyUsingWithGoogleGeocoder: true
});
viewer.scene.primitives.add(tileset);
viewer.scene.globe.show = false;
console.log('Google Photorealistic 3D Tiles loaded successfully');
} catch (error) {
console.warn('Failed to load Google tiles, falling back to Cesium globe:', error);
viewer.scene.globe.show = true;
}
}
loadTileset();
Key implementation details:
onlyUsingWithGoogleGeocoder: trueindicates the tileset will be used alongside Google's geocoder service, ensuring proper licensing compliance.creditContainermust point to a visible DOM element to satisfy Google's attribution requirements.targetFrameRate = 60prevents unnecessary GPU utilization on high-refresh displays.
Summary
- Credential Configuration: Store
CESIUM_ION_TOKENandGOOGLE_MAPS_API_KEYin environment variables and inject them viaimport.meta.envinsrc/main.jslines 76‑88. - Viewer Optimization: Disable all UI chrome and set
baseLayer: falseto prepare for photorealistic tiles, as implemented insrc/main.jslines 92‑106. - Tileset Loading: Use
Cesium.createGooglePhotorealistic3DTileset()withonlyUsingWithGoogleGeocoder: trueand wrap in try/catch for graceful fallback to the default globe. - Attribution Compliance: Provide a dedicated
creditContainerelement to display required Google attribution. - Performance Tuning: Cap frame rates at 60 FPS and disable the default globe when photorealistic tiles are active to reduce resource consumption.
Frequently Asked Questions
Do I need both a Cesium Ion token and a Google Maps API key?
Yes. The implementation requires both credentials. The Cesium Ion token authenticates your access to Cesium's runtime and services, while the Google Maps API key unlocks the Photorealistic 3D Tiles endpoint. According to the src/main.js source, both Cesium.Ion.defaultAccessToken and Cesium.GoogleMaps.defaultApiKey must be set before initializing the viewer.
What happens if Google Photorealistic 3D Tiles fail to load?
The application falls back to Cesium's default globe. The repository implements defensive error handling in src/main.js lines 59‑66, where a try/catch block surrounds the tileset creation. If createGooglePhotorealistic3DTileset() throws an exception—due to network failures, quota limits, or authentication errors—the catch block logs a warning and re-enables viewer.scene.globe.show to maintain basic functionality.
Can I use this setup without Vite?
Yes, but you must adapt the environment variable access. The repository uses import.meta.env (a Vite convention) to access CESIUM_ION_TOKEN and GOOGLE_MAPS_API_KEY. In Webpack, Parcel, or plain HTML/JS implementations, replace import.meta.env with your build tool's equivalent (e.g., process.env in Webpack with DefinePlugin) or inject the keys as global constants at runtime.
Why disable the default Cesium globe when using Google tiles?
To prevent Z-fighting and improve performance. The Google Photorealistic 3D Tiles provide complete terrain and building coverage, making the default Cesium globe redundant. Setting viewer.scene.globe.show = false after successfully loading the tileset eliminates rendering conflicts between the two data sources and reduces GPU overhead, as evidenced by the globe-hide logic in src/main.js lines 59‑66.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →