# How to Set Up CesiumJS with Google Photorealistic 3D Tiles

> Learn how to set up CesiumJS with Google Photorealistic 3D Tiles. Integrate 3D Tiles easily by configuring API keys and instantiating the viewer for stunning visuals.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: how-to-guide
- Published: 2026-08-30

---

**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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) lines 76‑88, the repository reads these values from Vite's environment system and injects them into the Cesium runtime:

```javascript
// 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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) lines 92‑106, the viewer is instantiated with explicit flags to hide unnecessary widgets:

```javascript
// 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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) lines 59‑66 demonstrates a defensive pattern that attempts to load Google tiles while maintaining functionality if the service is unavailable:

```javascript
// 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:

```javascript
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: true`** indicates the tileset will be used alongside Google's geocoder service, ensuring proper licensing compliance.
- **`creditContainer`** must point to a visible DOM element to satisfy Google's attribution requirements.
- **`targetFrameRate = 60`** prevents unnecessary GPU utilization on high-refresh displays.

## Summary

- **Credential Configuration:** Store `CESIUM_ION_TOKEN` and `GOOGLE_MAPS_API_KEY` in environment variables and inject them via `import.meta.env` in [`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) lines 76‑88.
- **Viewer Optimization:** Disable all UI chrome and set `baseLayer: false` to prepare for photorealistic tiles, as implemented in [`src/main.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) lines 92‑106.
- **Tileset Loading:** Use `Cesium.createGooglePhotorealistic3DTileset()` with `onlyUsingWithGoogleGeocoder: true` and wrap in try/catch for graceful fallback to the default globe.
- **Attribution Compliance:** Provide a dedicated `creditContainer` element 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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/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`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/main.js) lines 59‑66.