Skip to content

[Bug] Deck GL > 9.0 results in failed 3D tiles for compressed tiles #9912

@aparlato

Description

@aparlato

Description

Rendering a 3D tileset using Tile3DLayer is failing on versions greater than 9.0. I believe these tiles use a KTX2 compression which should be supported by Deck GL.

For now I have redacted the name of the tileset until I am sure it is considered public and can be used as an example here. I will update if possible with that example. Please let me know if I can be more helpful here.

v9.0.0 (works as expected):
Image

Example:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>MapLibre + Deck.gl + 3D Tiles</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" rel="stylesheet" />
    <script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist.min.js"></script> <!-- Older version works -->
    <script src="https://unpkg.com/@loaders.gl/[email protected]/dist/dist.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@loaders.gl/[email protected]/dist/dist.min.js"></script> <!-- Older version works, new loader version combined with old deck.gl results in just black shapes and no textures -->

    <style>
      html,
      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>

    <script>
      const { MapboxOverlay } = deck;
      const { Tile3DLayer } = deck;
      const { Tiles3DLoader } = loaders;

      const map = new maplibregl.Map({
        container: 'map',
        style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
        center: [-122.4, 37.78],
        zoom: 14,
        pitch: 45,
        bearing: -7.4,
      });

      const API_KEY = 'abc123';
      // Tileset redacted until known if it can be used publicly as an example
      const tilesetUrl = `https://my-tiles.com/tileset.json?apiKey=${API_KEY}`;

      const my3DLayer = new Tile3DLayer({
        id: 'my-3d-layer',
        data: tilesetUrl,
        loader: Tiles3DLoader,
        onTileLoad: (tileHeader) => console.log('Tile loaded:', tileHeader),
        onTileError: (err) => console.error('Tile load error:', err),
      });

      const overlay = new MapboxOverlay({
        interleaved: true,
        layers: [my3DLayer],
      });

      map.addControl(overlay);
    </script>
  </body>
</html>

v9.2.2 (does not work as expected):
Image

Example:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>MapLibre + Deck.gl + 3D Tiles</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link
      href="https://unpkg.com/[email protected]/dist/maplibre-gl.css"
      rel="stylesheet"
    />
    <script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script>

    <script src="https://unpkg.com/[email protected]/dist.min.js"></script>
    <script src="https://unpkg.com/@loaders.gl/[email protected]/dist/dist.min.js"></script>
    <script src="https://unpkg.com/@loaders.gl/[email protected]/dist/dist.min.js"></script>

    <style>
      html,
      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }
      #map {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>

    <script>
      const { MapboxOverlay } = deck;
      const { Tile3DLayer } = deck;
      const { Tiles3DLoader } = loaders;

      const map = new maplibregl.Map({
        container: 'map',
        style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
        center: [-122.4, 37.78],
        zoom: 14,
        pitch: 45,
        bearing: -7.4,
      });

      const API_KEY = 'abc123';
      // Tileset redacted until known if it can be used publicly as an example
      const tilesetUrl = `https://my-tiles.com/tileset.json?apiKey=${API_KEY}`;

      const my3DLayer = new Tile3DLayer({
        id: 'my-3d-layer',
        data: tilesetUrl,
        loader: Tiles3DLoader,
        onTileLoad: (tileHeader) => console.log('Tile loaded:', tileHeader),
        onTileError: (err) => console.error('Tile load error:', err),
      });

      const overlay = new MapboxOverlay({
        interleaved: true,
        layers: [my3DLayer],
      });

      map.addControl(overlay);
    </script>
  </body>
</html>

Flavors

  • Script tag
  • React
  • Python/Jupyter notebook
  • MapboxOverlay
  • GoogleMapsOverlay
  • CARTO
  • ArcGIS

Expected Behavior

I expect the compressed 3D tiles to be able to render the same in the latest 9.x.x version as in 9.0.0 as there has not been a major version change indicating these tiles are no longer supported.

Steps to Reproduce

  • Find an appropriate tileset with KTX2 texture compression (assuming this is the issue)
  • Add the tileset into the non-working v9.2.2 example above
  • See no 3D tiles render despite loading and see web GL errors in the console

Environment

  • Framework version: [email protected]
  • Browser: Chrome Version 142.0.7444.135 (Official Build) (arm64)
  • OS: Mac OS 26.1 (25B78)

Logs

Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions