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.
Link to the demonstration
No response
Steps to trigger the unexpected behavior
- new mapboxgl.Map({ style: 'mapbox://styles/mapbox/standard', center: [-74.0, 40.7], zoom: 20, pitch: 0 }).
- Add an image source and a raster layer with raster-opacity: 254/255 and raster-elevation: 0.1.
- 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).
- View at pitch: 0 — polygon is missing; the raster paints through where it should be.
- map.easeTo({ pitch: 45 }) — polygon reappears.
- map.easeTo({ pitch: 0 }) — polygon disappears again.
- Alternate: keep pitch 0 and zoom from 22 → 18 — polygon vanishes below ~zoom 20.5.
Relevant log output
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.
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
~zoom 20.5 on zoom-out and near-orthographic views. At the transition zooms the polygon flickers in and out as depth values quantize.
(which doesn't depth-test) stays visible; only the fill-extrusion top face is occluded.
Link to the demonstration
No response
Steps to trigger the unexpected behavior
raster in world Z).
Relevant log output
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.