# How GeoLibre Renders 3D Tiles for Point Clouds and Buildings

> Discover how GeoLibre renders 3D Tiles for point clouds and buildings. Learn about native OGC 3D Tiles and proprietary format integration via Deck.gl.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-07-31

---

**GeoLibre renders 3D Tiles through two distinct architectural paths: native OGC 3D Tiles (point clouds and buildings) integrate directly via `maplibre-gl-3d-tiles`, while proprietary formats like Google Photorealistic 3D Tiles and ArcGIS I3S render through an interleaved Deck.gl overlay with custom altitude offsets and authentication headers.**

GeoLibre is an open-source geospatial framework that unifies diverse 3D data sources into a single MapLibre-based view. To understand **3D Tiles rendering** in this codebase, you must examine how the library distinguishes between standard OGC 3D Tiles and vendor-specific formats, routing each through optimized rendering engines while maintaining synchronized state via a central Zustand store.

## The Two Rendering Paths for 3D Tiles

GeoLibre implements a bifurcated rendering strategy depending on the tileset format. The system detects the source type during layer initialization and delegates to either the native three.js-based pipeline or the Deck.gl overlay system.

### Native OGC 3D Tiles via maplibre-gl-3d-tiles

For standard **OGC 3D Tiles** containing point clouds or glTF-based buildings, GeoLibre uses the `maplibre-gl-3d-tiles` plugin. When a layer of type `3d-tiles` enters the store, the system instantiates a `ThreeDTilesControl` UI panel (defined at lines 68-88 in [`packages/plugins/src/plugins/maplibre-3d-tiles.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-3d-tiles.ts)). This control creates a `ThreeDTilesLayer` (instantiated at lines 16-22) and attaches it directly to the MapLibre map via `map.addLayer`.

The native path renders 3D geometry using three.js primitives that sit within the standard MapLibre layer stack, allowing these tiles to interact with existing 2D layers and standard map controls.

### Google Photorealistic and ArcGIS I3S via Deck.gl

For **Google Photorealistic 3D Tiles** (Earth-scale point clouds) and **ArcGIS I3S Scene Layers** (buildings), GeoLibre employs a [`shared-deck-overlay.ts`](https://github.com/opengeos/GeoLibre/blob/main/shared-deck-overlay.ts) system. The overlay constructs a subclassed `Tile3DLayer` that applies altitude offsets through `offsetGooglePhotorealisticTileLayers` (lines 313-338) and injects API keys via `resolveThreeDTilesRequestHeaders`.

ArcGIS I3S URLs are intercepted by `installArcgisI3sTilesPanelHandlers` (lines 882-904) and routed to the same Deck overlay. The layer list rebuilds only when the signature changes, as detected by `googleTilesLayerSignature` (lines 666-680), ensuring efficient updates without unnecessary re-renders.

## Step-by-Step Rendering Pipeline

The complete 3D Tiles rendering lifecycle follows a unidirectional data flow with bidirectional synchronization:

1. **User initiates layer addition** – via the UI panel, the Python API (`geolibre.add_3d_tiles`), or direct store dispatch.
2. **Store hydration** – `hydrateThreeDTilesControlFromStore` (lines 329-351) reads persisted layers and invokes `restoreThreeDTilesMapLayer`.
3. **Control instantiation** – `restoreThreeDTilesMapLayer` (lines 55-70) creates either a native `ThreeDTilesLayer` or registers a Deck layer for Google/I3S sources.
4. **MapLibre rendering** – Native tiles draw via three.js within the MapLibre canvas; Google/I3S tiles render via Deck.gl on top of the map, respecting custom opacity and altitude settings.
5. **State synchronization** – `syncThreeDTilesStoreFromControl` (lines 301-327) updates the Zustand store when users toggle visibility or adjust opacity, ensuring UI consistency.

## Implementation Details and Key Functions

### Control Configuration and Store Sync

The **ThreeDTilesControl options** are centralized in `THREE_D_TILES_OPTIONS` (lines 68-88), which defines default URLs for AGI, Google, and ArcGIS sample datasets. When creating layers programmatically, `createThreeDTilesStoreLayer` (lines 86-122) constructs the `GeoLibreLayer` record with metadata flags like `externalNativeLayer: true` to indicate native rendering capability.

For Google tiles specifically, `ensureGooglePhotorealisticTilesOverlay` (lines 175-181) initializes the shared Deck context, while `renderGooglePhotorealisticTilesLayers` (lines 230-265) assembles the final `Tile3DLayer` instances using the `GoogleAltitudeOffsetTile3DLayer` subclass (lines 211-229).

## Code Examples: Adding 3D Tile Layers

### Adding Native OGC 3D Tiles from the UI

```tsx
// Open the "Add 3D Tiles Layer" panel
openThreeDTilesLayerPanel(app);

// User submits the form with tileset URL and styling options
await addThreeDTilesLayer(app, {
  tilesetUrl: 'https://myserver.com/tileset.json',
  name: 'LiDAR Point Cloud',
  visible: true,
  opacity: 0.8,
});

```

This triggers the control installer at lines 58-73 of the 3D tiles plugin, which ultimately calls `map.addLayer` with a `ThreeDTilesLayer` instance.

### Adding Google Photorealistic 3D Tiles via Python

```python
from geolibre import GeoLibre

g = GeoLibre()
g.add_3d_tiles(
    "https://tile.googleapis.com/v1/3dtiles/root.json",
    name="Google Satellite 3D",
    altitude_offset=10,
    request_headers={"X-GOOG-API-KEY": "YOUR_API_KEY"},
    opacity=0.9,
)

```

The `add_3d_tiles` method in [`python/src/geolibre/geolibre.py`](https://github.com/opengeos/GeoLibre/blob/main/python/src/geolibre/geolibre.py) (lines 1609-1628) creates a layer with `sourceKind: 'google-photorealistic-3d-tiles'`, which the frontend recognizes as requiring the Deck overlay path.

### Direct Store Dispatch (Advanced)

```ts
import { useAppStore } from '@geolibre/core';

useAppStore.getState().addLayer({
  id: 'city-buildings',
  name: 'Downtown OSM Buildings',
  type: '3d-tiles',
  source: {
    type: '3d-tiles',
    url: 'https://example.com/city/tileset.json',
    sourceId: 'city-buildings',
    altitudeOffset: 0,
  },
  visible: true,
  opacity: 1,
  metadata: {
    sourceKind: '3d-tiles-url',
    customLayerType: '3d-tiles',
    externalNativeLayer: true,
  },
});

```

The store subscription `threeDTilesStoreUnsubscribe` (registered at lines 68-96) detects this dispatch and updates the native control automatically.

### Internal Deck Layer Construction

```ts
// Ensure shared overlay exists
await ensureGooglePhotorealisticTilesOverlay(app);

// Build the layer with altitude offset and auth headers
const deckLayer = new Tile3DLayer({
  id: 'google-3d-tiles-layer',
  data: 'https://tile.googleapis.com/v1/3dtiles/root.json',
  altitudeOffset: layer.source.altitudeOffset,
  loadOptions: {
    fetch: { headers: resolveThreeDTilesRequestHeaders(layer) },
  },
  opacity: layer.opacity,
});

setSharedDeckLayers('google-3d-tiles', [deckLayer]);

```

This mirrors `buildGooglePhotorealisticTilesDeckLayer` (lines 84-109) and `renderGooglePhotorealisticTilesLayers` (lines 230-265), showing how the system handles per-layer altitude correction and authentication.

## Summary

- **Dual rendering architecture**: Native OGC 3D Tiles use `maplibre-gl-3d-tiles` (three.js), while Google and ArcGIS sources use Deck.gl overlays.
- **Store-driven state**: All layer configuration lives in a Zustand store, synchronized to controls via `syncThreeDTilesStoreFromControl` and `hydrateThreeDTilesControlFromStore`.
- **Altitude and auth handling**: Google Photorealistic tiles automatically receive altitude offsets and API key injection through `GoogleAltitudeOffsetTile3DLayer` and `resolveThreeDTilesRequestHeaders`.
- **I3S support**: ArcGIS I3S Scene Layers share the Google rendering pipeline, intercepted by `installArcgisI3sTilesPanelHandlers`.
- **Source files**: Core logic resides in [`packages/plugins/src/plugins/maplibre-3d-tiles.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/maplibre-3d-tiles.ts) and [`packages/plugins/src/plugins/shared-deck-overlay.ts`](https://github.com/opengeos/GeoLibre/blob/main/packages/plugins/src/plugins/shared-deck-overlay.ts), with Python bindings in [`python/src/geolibre/geolibre.py`](https://github.com/opengeos/GeoLibre/blob/main/python/src/geolibre/geolibre.py).

## Frequently Asked Questions

### What is the difference between native and Deck.gl 3D Tiles rendering in GeoLibre?

**Native rendering** utilizes `ThreeDTilesLayer` from `maplibre-gl-3d-tiles` to draw OGC-compliant tilesets (point clouds, buildings) directly within MapLibre's three.js context. **Deck.gl rendering** handles proprietary formats like Google Photorealistic 3D Tiles and ArcGIS I3S through an interleaved overlay that supports custom altitude offsets and authentication headers not available in the native pipeline.

### How do I apply an altitude offset to Google Photorealistic 3D Tiles?

Pass the `altitude_offset` parameter when adding the layer via Python, or include `altitudeOffset` in the layer source configuration. The system applies this through `offsetGooglePhotorealisticTileLayers` (lines 313-338), which adjusts the Z-coordinate of fetched tiles before rendering to account for terrain discrepancies or vertical datum differences.

### Can I render both point clouds and buildings simultaneously in GeoLibre?

Yes. You can mix native OGC 3D Tiles (point clouds or meshes) with Google Photorealistic tiles or ArcGIS I3S buildings in the same view. The store manages each layer type independently, routing point clouds to the native renderer and building datasets to Deck.gl as determined by their `sourceKind` metadata and `externalNativeLayer` flags.

### Where does GeoLibre store the state for 3D Tiles layers?

Layer state persists in a centralized Zustand store defined in the core package. Functions like `createThreeDTilesStoreLayer` (lines 86-122) construct the layer records, while `syncThreeDTilesStoreFromControl` (lines 301-327) ensures the UI panel reflects current visibility and opacity settings. This architecture allows 3D Tiles to be restored across sessions and controlled programmatically from Python or TypeScript.