#13720·mapbox-gl-js

fill-extrusion polygons occluded by underlying raster layer with raster-elevation at low pitch, depth-test appears to collapse

Author: Siraj-zakiCreated Aug 26, 2026Updated Aug 27, 2026
Labelsbug :lady_beetle:auto-triaged

mapbox-gl-js version

3.25.x

Browser and version

Chrome 130 / Safari 17 / Firefox 131 — reproduces in all three

Expected behavior

A fill-extrusion polygon whose fill-extrusion-base sits above a raster layer's raster-elevation should paint on top of the raster at every pitch and
zoom. The raster's sub-1 raster-opacity (254/255) forces the alpha-blend path and should skip depth-write, so the elevated polygon always wins the depth test.

Actual behavior

  • At pitch >= ~30°: polygon renders correctly on top of the raster.
    • At pitch < ~15° (near top-down): the polygon becomes invisible; the raster paints where the polygon should be. The effect gets 100% reproducible past ~zoom 20.5 on zoom-out and near-orthographic views. At the transition zooms the polygon flickers in and out as depth values quantize.
    • map.queryRenderedFeatures() still returns the polygon at the missing pixels — it's in the scene, just not drawn. A line layer on the same geometry
      (which doesn't depth-test) stays visible; only the fill-extrusion top face is occluded.
    • Removing raster-elevation from the raster paint restores the polygon at all pitches, but breaks multi-floor raster stacking.
Image Image Image

Link to the demonstration

No response

Steps to trigger the unexpected behavior

  1. new mapboxgl.Map({ style: 'mapbox://styles/mapbox/standard', center: [-74.0, 40.7], zoom: 20, pitch: 0 }).
  2. Add an image source and a raster layer with raster-opacity: 254/255 and raster-elevation: 0.1.
  3. Add a fill-extrusion layer whose polygon overlaps the raster, with fill-extrusion-base: 0.15 and fill-extrusion-height: 0.5 (top clearly above the
    raster in world Z).
  4. View at pitch: 0 — polygon is missing; the raster paints through where it should be.
  5. map.easeTo({ pitch: 45 }) — polygon reappears.
  6. map.easeTo({ pitch: 0 }) — polygon disappears again.
  7. Alternate: keep pitch 0 and zoom from 22 → 18 — polygon vanishes below ~zoom 20.5.

Relevant log output

bash
No warnings or errors are emitted by Mapbox GL JS. The console stays clean throughout.
                                                                                                                                                         
  map.queryRenderedFeatures(centerPixel, { layers: ['poly'] }) at pitch 0, zoom 19:
  [{ layer: { id: 'poly', type: 'fill-extrusion' }, properties: {...}, geometry: {...} }]                                                                
  (polygon is found in the scene but not visible on screen.)
                                                                                                                                                         
  map.getStyle().layers.map(l => ({ id: l.id, type: l.type, slot: l.slot })) — confirms raster sits before poly in the style layer order.
                                                                                                                                                         
  WebGL: WEBGL_debug_renderer_info reports ANGLE (…) / Apple M-series GPU / … on affected machines; the same repro fails identically on Intel integrated,
   Apple Silicon, and discrete NVIDIA, so it's not driver-specific.