**European Economic Area (EEA) developers**

> [!NOTE]
> If your billing address is in the European Economic Area, effective on 8 July 2025, the [Google
> Maps Platform EEA Terms of Service](https://cloud.google.com/terms/maps-platform/eea) will apply to your use of the Services. [Learn more](https://developers.google.com/maps/comms/eea/faq.md.txt). In addition, certain content from the Map Tiles API will no longer be returned. [Learn more](https://developers.google.com/maps/comms/eea/map-tiles.md.txt).

Photorealistic 3D Tiles are in the
[OGC standard glTF format](https://portal.ogc.org/files/102132),
meaning you can use any renderer that supports the OGC 3D Tiles spec to build
your 3D visualizations. For example,
[Cesium](https://cesium.com/platform/)
is a foundational open source library for rendering 3D visualizations.

## Work with CesiumJS

CesiumJS is an open source Javascript library for 3D visualization on the web.
For more information about using CesiumJS, see
[Learn CesiumJS](https://cesium.com/learn/cesiumjs-learn/).

> [!TIP]
> **Tip:** For demonstrations of several CesiumJS code samples, see [CesiumJS renderer examples](https://developers.google.com/maps/documentation/tile/use-renderer.md.txt#cesiumjs-renderer-examples).

### User controls

The CesiumJS tile renderer has a standard set of user controls.

| Action | Description |
|---|---|
| Pan view | Left click \& drag |
| Zoom view | Right click \& drag, or scroll the mouse wheel |
| Rotate view | Ctrl + left/right click \& drag, or middle click \& drag |

### Best practices

There are several approaches that you can take to decrease CesiumJS 3D loading
times. For example:

- Enable simultaneous requests by adding the following statement to your rendering HTML:

  ```javascript
  Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = <REQUEST_COUNT>
  ```

  The higher the `REQUEST_COUNT`, the quicker the
  tiles load. However, when loading in a Chrome browser with `REQUEST_COUNT`
  greater than 10 and cache disabled, you might run into a known
  [Chrome issue](https://bugs.chromium.org/p/chromium/issues/detail?id=1428295).
  For most use cases, we recommend a `REQUEST_COUNT` of 18 for optimal
  performance.
- Enable skipping levels of detail. For more information, see this
  [Cesium issue](https://github.com/CesiumGS/cesium/issues/3857).

Ensure that you properly display data attributions by enabling
`showCreditsOnScreen: true`. For more information, see
[Policies](https://developers.google.com/maps/documentation/tile/policies.md.txt#cesiumjs).

### Rendering metrics

To find the framerate, look at how many times per second the
[requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
method is called.

To see how the frame latency is calculated, take a look at the
[PerformanceDisplay](https://github.com/CesiumGS/cesium/blob/9295450e64c3077d96ad579012068ea05f97842c/packages/engine/Source/Scene/PerformanceDisplay.js#L83)
class.

### CesiumJS renderer examples

You can use the CesiumJS renderer with Map Tiles API's 3D Tiles by simply
supplying the root tileset URL.

#### Simple example

The following example initializes the CesiumJS renderer, and then loads the root
tileset.

```html
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <title>CesiumJS 3D Tiles Simple Demo</title>
  <script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
  <link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
  <div id="cesiumContainer"></div>
  <script>

    // Enable simultaneous requests.
    Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;

    // Create the viewer.
    const viewer = new Cesium.Viewer('cesiumContainer', {
      imageryProvider: false,
      baseLayerPicker: false,
      geocoder: false,
      globe: false,
      // https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/#enabling-request-render-mode
      requestRenderMode: true,
    });

    // Add 3D Tiles tileset.
    const tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
      url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
      // This property is needed to appropriately display attributions
      // as required.
      showCreditsOnScreen: true,
    }));
  </script>
</body>
```

For information about `requestRenderMode`, see
[Enabling request render mode](https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/#enabling-request-render-mode).

The HTML page renders as shown here.

![](https://developers.google.com/static/maps/documentation/tile/images/cesium-display.png)

#### Places API (New) integration

You can use CesiumJS with the
[Places API (New)](https://developers.google.com/maps/documentation/places/web-service)
to retrieve more information. You can use the Autocomplete widget to fly to the
viewport of Places. This example uses the Places Autocomplete API,
which is enabled by
[following these instructions](https://developers.google.com/maps/documentation/javascript/places-autocomplete),
and the Maps JavaScript API, which is enabled by
[following these instructions](https://developers.google.com/maps/documentation/javascript/cloud-setup#enabling-apis).

```html
<!DOCTYPE html>
<head>
 <meta charset="utf-8" />
 <title>CesiumJS 3D Tiles Places API (New) Integration Demo</title>
 <script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
 <link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
 <label for="pacViewPlace">Go to a place: </label>
 <input
   type="text"
   id="pacViewPlace"
   name="pacViewPlace"
   placeholder="Enter a location..."
   style="width: 300px"
 />
 <div id="cesiumContainer"></div>
 <script>
   // Enable simultaneous requests.
   Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;

   // Create the viewer.
   const viewer = new Cesium.Viewer("cesiumContainer", {
     imageryProvider: false,
     baseLayerPicker: false,
     requestRenderMode: true,
     geocoder: false,
     globe: false,
   });

   // Add 3D Tiles tileset.
   const tileset = viewer.scene.primitives.add(
     new Cesium.Cesium3DTileset({
       url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
       // This property is required to display attributions as required.
       showCreditsOnScreen: true,
     })
   );

   const zoomToViewport = (viewport) => {
     viewer.entities.add({
       polyline: {
         positions: Cesium.Cartesian3.fromDegreesArray([
           viewport.getNorthEast().lng(), viewport.getNorthEast().lat(),
           viewport.getSouthWest().lng(), viewport.getNorthEast().lat(),
           viewport.getSouthWest().lng(), viewport.getSouthWest().lat(),
           viewport.getNorthEast().lng(), viewport.getSouthWest().lat(),
           viewport.getNorthEast().lng(), viewport.getNorthEast().lat(),
         ]),
         width: 10,
         clampToGround: true,
         material: Cesium.Color.RED,
       },
     });
     viewer.flyTo(viewer.entities);
   };

   function initAutocomplete() {
     const autocomplete = new google.maps.places.Autocomplete(
       document.getElementById("pacViewPlace"),
       {
         fields: [
           "geometry",
           "name",
         ],
       }
     );
     autocomplete.addListener("place_changed", () => {
       viewer.entities.removeAll();
       const place = autocomplete.getPlace();
       if (!place.geometry || !place.geometry.viewport) {
         window.alert("No viewport for input: " + place.name);
         return;
       }
       zoomToViewport(place.geometry.viewport);
     });
   }
 </script>
 <script
   async=""
   src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initAutocomplete"
 ></script>
</body>
```

#### Rotating drone view

You can control the camera to animate through the tileset. When combined with
the Places API (New) and the Elevation API, this animation simulates an interactive
drone flyover of any point of interest.

This code sample flies you around the place that you selected in the
Autocomplete widget.

> [!NOTE]
> **Note:** To use this code sample, you must enable the [Places API (New)](https://console.cloud.google.com/apis/library/places-backend.googleapis.com), [Maps JavaScript API](https://console.cloud.google.com/apis/library/maps-backend.googleapis.com), and the [Elevation API](https://console.cloud.google.com/apis/library/elevation-backend.googleapis.com) on the same project that you're using for 3D Tiles. Go to each of these pages, select your 3D Tiles project from the dropdown menu in the blue bar at the top of the page. Then select the blue **ENABLE** button under the API's name.
>
> - If the button says **MANAGE**, then the API is already enabled on that project.

```html
<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <title>CesiumJS 3D Tiles Rotating Drone View Demo</title>
  <script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
  <link href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
  <label for="pacViewPlace">Go to a place: </label>
  <input type="text" id="pacViewPlace" name="pacViewPlace" placeholder="Enter a location..." style="width: 300px" />
  <div id="cesiumContainer"></div>
  <script>
    // Enable simultaneous requests.
    Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;

    // Create the viewer and remove unneeded options.
    const viewer = new Cesium.Viewer("cesiumContainer", {
      imageryProvider: false,
      baseLayerPicker: false,
      homeButton: false,
      fullscreenButton: false,
      navigationHelpButton: false,
      vrButton: false,
      sceneModePicker: false,
      geocoder: false,
      globe: false,
      infobox: false,
      selectionIndicator: false,
      timeline: false,
      projectionPicker: false,
      clockViewModel: null,
      animation: false,
      requestRenderMode: true,
    });

    // Add 3D Tile set.
    const tileset = viewer.scene.primitives.add(
      new Cesium.Cesium3DTileset({
        url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",
        // This property is required to display attributions.
        showCreditsOnScreen: true,
      })
    );

    // Point the camera at a location and elevation, at a viewport-appropriate distance.
    function pointCameraAt(location, viewport, elevation) {
      const distance = Cesium.Cartesian3.distance(
        Cesium.Cartesian3.fromDegrees(
          viewport.getSouthWest().lng(), viewport.getSouthWest().lat(), elevation),
        Cesium.Cartesian3.fromDegrees(
          viewport.getNorthEast().lng(), viewport.getNorthEast().lat(), elevation)
      ) / 2;
      const target = new Cesium.Cartesian3.fromDegrees(location.lng(), location.lat(), elevation);
      const pitch = -Math.PI / 4;
      const heading = 0;
      viewer.camera.lookAt(target, new Cesium.HeadingPitchRange(heading, pitch, distance));
    }

    // Rotate the camera around a location and elevation, at a viewport-appropriate distance.
    let unsubscribe = null;
    function rotateCameraAround(location, viewport, elevation) {
      if(unsubscribe) unsubscribe();
      pointCameraAt(location, viewport, elevation);
      unsubscribe = viewer.clock.onTick.addEventListener(() => {
        viewer.camera.rotate(Cesium.Cartesian3.UNIT_Z);
      });
    }

    function initAutocomplete() {
      const autocomplete = new google.maps.places.Autocomplete(
        document.getElementById("pacViewPlace"), {
          fields: [
            "geometry",
            "name",
          ],
        }
      );

      autocomplete.addListener("place_changed", async () => {
        const place = autocomplete.getPlace();

        if (!(place.geometry && place.geometry.viewport && place.geometry.location)) {
          window.alert(`Insufficient geometry data for place: ${place.name}`);
          return;
        }
        // Get place elevation using the ElevationService.
        const elevatorService = new google.maps.ElevationService();
        const elevationResponse =  await elevatorService.getElevationForLocations({
          locations: [place.geometry.location],
        });

        if(!(elevationResponse.results && elevationResponse.results.length)){
          window.alert(`Insufficient elevation data for place: ${place.name}`);
          return;
        }
        const elevation = elevationResponse.results[0].elevation || 10;

        rotateCameraAround(
          place.geometry.location,
          place.geometry.viewport,
          elevation
        );
      });
    }
  </script>
  <script async src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initAutocomplete"></script>
</body>
```

#### Draw polylines and labels

This code sample demonstrates how to add polylines and labels to a map. You can
add polylines to a map to show driving and walking directions, or to show
property boundaries, or to calculate driving and walking durations. You can also
get attributes without actually rendering the scene.

You could take users on a curated tour of a neighborhood, or you could show
neighboring properties that are currently on sale, and then you could add 3D
objects such as billboards to the scene.

You could summarize a trip, listing the properties that you viewed, displaying
these details in virtual objects.

```html
<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <title>CesiumJS 3D Tiles Polyline and Label Demo</title>
  <script src="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Cesium.js"></script>
  <link
    href="https://ajax.googleapis.com/ajax/libs/cesiumjs/1.105/Build/Cesium/Widgets/widgets.css"
    rel="stylesheet"
  />
</head>
<body>
  <div id="cesiumContainer"></div>
  <script>
    // Enable simultaneous requests.
    Cesium.RequestScheduler.requestsByServer["tile.googleapis.com:443"] = 18;

    // Create the viewer.
    const viewer = new Cesium.Viewer("cesiumContainer", {
      imageryProvider: false,
      baseLayerPicker: false,
      requestRenderMode: true,
      geocoder: false,
      globe: false,
    });

    // Add 3D Tiles tileset.
    const tileset = viewer.scene.primitives.add(
      new Cesium.Cesium3DTileset({
        url: "https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY",

        // This property is required to display attributions as required.
        showCreditsOnScreen: true,
      })
    );

    // Draws a circle at the position, and a line from the previous position.
    const drawPointAndLine = (position, prevPosition) => {
      viewer.entities.removeAll();
      if (prevPosition) {
        viewer.entities.add({
          polyline: {
            positions: [prevPosition, position],
            width: 3,
            material: Cesium.Color.WHITE,
            clampToGround: true,
            classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
          },
        });
      }
      viewer.entities.add({
        position: position,
        ellipsoid: {
          radii: new Cesium.Cartesian3(1, 1, 1),
          material: Cesium.Color.RED,
        },
      });
    };

    // Compute, draw, and display the position's height relative to the previous position.
    var prevPosition;
    const processHeights = (newPosition) => {
      drawPointAndLine(newPosition, prevPosition);

      const newHeight = Cesium.Cartographic.fromCartesian(newPosition).height;
      let labelText = "Current altitude (meters above sea level):\n\t" + newHeight;
      if (prevPosition) {
        const prevHeight =
          Cesium.Cartographic.fromCartesian(prevPosition).height;
        labelText += "\nHeight from previous point (meters):\n\t" + Math.abs(newHeight - prevHeight);
      }
      viewer.entities.add({
        position: newPosition,
        label: {
          text: labelText,
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          pixelOffset: new Cesium.Cartesian2(0, -10),
          showBackground: true,
          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
        }
      });

      prevPosition = newPosition;
    };

    const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
    handler.setInputAction(function (event) {
      const earthPosition = viewer.scene.pickPosition(event.position);
      if (Cesium.defined(earthPosition)) {
        processHeights(earthPosition);
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  </script>
</body>
```

#### Camera orbit

In Cesium, you can orbit the camera around a point of interest, avoiding
collisions with buildings. Alternatively, you can make buildings transparent
when the camera moves through them.

First, lock the camera onto a point, then you can create a camera orbit to
showcase your asset. You can do this by using the camera's
[`lookAtTransform`](https://cesium.com/learn/cesiumjs/ref-doc/Camera.html#lookAtTransform)
function with an event listener, as demonstrated in this code sample.

```javascript
// Lock the camera onto a point.
const center = Cesium.Cartesian3.fromRadians(
  2.4213211833389243,
  0.6171926869414084,
  3626.0426275055174
);

const transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);

viewer.scene.camera.lookAtTransform(
  transform,
  new Cesium.HeadingPitchRange(0, -Math.PI / 8, 2900)
);

// Orbit around this point.
viewer.clock.onTick.addEventListener(function (clock) {
  viewer.scene.camera.rotateRight(0.005);
});
```

For more information about controlling the camera, see
[Control the camera](https://cesium.com/learn/cesiumjs-learn/cesiumjs-camera/)

## Work with Cesium for Unreal

To use the Cesium for Unreal Plugin with the 3D Tiles API, follow the steps
below.

> [!TIP]
> **Tip:** For detailed instructions, see the [Cesium for Unreal Quickstart](https://cesium.com/learn/unreal/unreal-quickstart/).

1. Install the Cesium for Unreal plugin.

2. Create a new Unreal project.

3. Connect to Google Photorealistic 3D Tiles API.

   1. Open the Cesium window by selecting **Cesium** \> **Cesium** from the menu.

   2. Select **Blank 3D Tiles Tileset**.

   3. In the **World Outliner** , open the **Details** panel by selecting this
      **Cesium3DTileset**.

   4. Change the **Source** from **From Cesium Ion** to **From URL**.

   5. Set the URL to be the Google 3D Tiles URL.

       https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY

   1. Enable **Show Credits On Screen** to properly display attributions.
4. This loads the world. To move to any LatLng, select the
   **CesiumGeoreference** item in the **Outliner** panel, and then edit the
   **Origin Latitude/Longitude/Height** in the **Details** panel.

## Work with Cesium for Unity

> [!NOTE]
> **Note:** For more information on Cesium for Unity, see the [Cesium for Unity Quickstart](https://cesium.com/learn/unity/unity-quickstart/).

To use photorealistic tiles with Cesium for Unity, follow the steps below.

1. Create a new Unity project.

2. Add a new Scoped Registry in the Package Manager section (through **Editor** \> **Project Settings**).

   - Name: Cesium

   - URL: https://unity.pkg.cesium.com

   - Scope(s): com.cesium.unity

3. Install the Cesium for Unity package.

4. Connect to the Google Photorealistic 3D Tiles API.

   1. Open the Cesium window by selecting **Cesium** \> **Cesium** from the menu.

   2. Click **Blank 3D Tiles Tileset**.

   3. On the left-side panel, in the **Tileset Source** option under **Source** ,
      select **From URL** (instead of From Cesium Ion).

   4. Set the URL to the Google 3D Tiles URL.

       https://tile.googleapis.com/v1/3dtiles/root.json?key=YOUR_API_KEY

   1. Enable **Show Credits On Screen** to properly display attributions.
5. This loads the world. To move to any LatLng, select the
   **CesiumGeoreference** item in the **Scene Hierarchy** , and then edit the
   Origin Latitude/Longitude/Height in the **Inspector**.

## Work with deck.gl

> [!NOTE]
> **Note:** The minimum version of deck.gl to use with the Map Tiles API is 8.9.13 (and above).

[deck.gl](https://deck.gl/),
powered by WebGL, is an open source JavaScript framework for high-performance,
large-scale data visualizations.

### Attribution

Ensure that you properly display data attributions by extracting the `copyright`
field from tiles gltf `asset`, and then displaying it on the rendered view. For
more information, see
[Display data attributions](https://developers.google.com/maps/documentation/tile/create-renderer.md.txt#display-attributions).

### deck.gl renderer examples

#### Simple example

The following example initializes the deck.gl renderer, and then loads a place
in 3D. In your code, be sure to replace <var translate="no">YOUR_API_KEY</var> with your
actual API key.

```html
<!DOCTYPE html>
<html>
 <head>
   <title>deck.gl Photorealistic 3D Tiles example</title>
   <script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
   <style>
     body { margin: 0; padding: 0;}
     #map { position: absolute; top: 0;bottom: 0;width: 100%;}
     #credits { position: absolute; bottom: 0; right: 0; padding: 2px; font-size: 15px; color: white;
        text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;}
   </style>
 </head>

 <body>
   <div id="map"></div>
   <div id="credits"></div>
   <script>
     const GOOGLE_API_KEY = YOUR_API_KEY;
     const TILESET_URL = `https://tile.googleapis.com/v1/3dtiles/root.json`;
     const creditsElement = document.getElementById('credits');
     new deck.DeckGL({
       container: 'map',
       initialViewState: {
         latitude: 50.0890,
         longitude: 14.4196,
         zoom: 16,
         bearing: 90,
         pitch: 60,
         height: 200
       },
       controller: {minZoom: 8},
       layers: [
         new deck.Tile3DLayer({
           id: 'google-3d-tiles',
           data: TILESET_URL,
           loadOptions: {
            fetch: {
              headers: {
                'X-GOOG-API-KEY': GOOGLE_API_KEY
              }
            }
          },
           onTilesetLoad: tileset3d => {
             tileset3d.options.onTraversalComplete = selectedTiles => {
               const credits = new Set();
               selectedTiles.forEach(tile => {
                 const {copyright} = tile.content.gltf.asset;
                 copyright.split(';').forEach(credits.add, credits);
                 creditsElement.innerHTML = [...credits].join('; ');
               });
               return selectedTiles;
             }
           }
         })
       ]
     });
   </script>
 </body>
</html>
```

#### Visualize 2D layers on top of Google Photorealistic 3D Tiles

The deck.gl
[TerrainExtension](https://deck.gl/docs/api-reference/extensions/terrain-extension)
renders otherwise 2D data onto a 3D surface. For example, you can drape the
GeoJSON of a building footprint on top of the Photorealistic 3D Tiles Geometry.

In the following example, a layer of buildings is visualized with the polygons
adapted to the Photorealistic 3D Tiles surface.

```html
<!DOCTYPE html>
<html>
 <head>
   <title>Google 3D tiles example</title>
   <script src="https://unpkg.com/deck.gl@latest/dist.min.js"></script>
   <style>
     body { margin: 0; padding: 0;}
     #map { position: absolute; top: 0;bottom: 0;width: 100%;}
     #credits { position: absolute; bottom: 0; right: 0; padding: 2px; font-size: 15px; color: white;
        text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;}
   </style>
 </head>

 <body>
   <div id="map"></div>
   <div id="credits"></div>
   <script>
     const GOOGLE_API_KEY = YOUR_API_KEY;
     const TILESET_URL = `https://tile.googleapis.com/v1/3dtiles/root.json`;
     const BUILDINGS_URL = 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/google-3d-tiles/buildings.geojson'
     const creditsElement = document.getElementById('credits');
     const deckgl = new deck.DeckGL({
       container: 'map',
       initialViewState: {
         latitude: 50.0890,
         longitude: 14.4196,
         zoom: 16,
         bearing: 90,
         pitch: 60,
         height: 200
       },
       controller: true,
       layers: [
         new deck.Tile3DLayer({
           id: 'google-3d-tiles',
           data: TILESET_URL,
           loadOptions: {
            fetch: {
              headers: {
                'X-GOOG-API-KEY': GOOGLE_API_KEY
              }
            }
          },
          onTilesetLoad: tileset3d => {
             tileset3d.options.onTraversalComplete = selectedTiles => {
               const credits = new Set();
               selectedTiles.forEach(tile => {
                 const {copyright} = tile.content.gltf.asset;
                 copyright.split(';').forEach(credits.add, credits);
                 creditsElement.innerHTML = [...credits].join('; ');
               });
               return selectedTiles;
             }
           },
           operation: 'terrain+draw'
         }),
         new deck.GeoJsonLayer({
           id: 'buildings',
           // This dataset is created by CARTO, using other Open Datasets available. More info at: https://3dtiles.carto.com/#about.
           data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/google-3d-tiles/buildings.geojson',
           stroked: false,
           filled: true,
           getFillColor: ({properties}) => {
             const {tpp} = properties;
             // quantiles break
             if (tpp < 0.6249)
               return [254, 246, 181]
             else if (tpp < 0.6780)
               return [255, 194, 133]
             else if (tpp < 0.8594)
               return [250, 138, 118]
             return [225, 83, 131]
           },
           opacity: 0.2,
           extensions: [new deck._TerrainExtension()]
         })
       ]
     });
   </script>
 </body>
</html>
```