# core: fix color-relief/hillshade invisible above fill layers on Metal/Vulkan/WebGPU (#4166)

This commit is contained in:
Andrew Calcutt
2026-03-11 20:24:13 -04:00
committed by GitHub
parent 41b085f66a
commit 586ddbf854
18 changed files with 60260 additions and 2 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

View File

@@ -0,0 +1,111 @@
{
"version": 8,
"metadata": {
"test": {
"height": 256,
"width": 256,
"allowed": 0.01,
"description": "Same as the fill-sandwich test but without the fill layer, to verify that two color-relief layers with hillshade render correctly on all backends (Metal, Vulkan, WebGPU) when no vector layer is present. Used to isolate whether the fill layer is the cause of the rendering regression. A small allowed difference (0.01) accounts for sub-pixel floating-point variation in hillshade between OpenGL and non-OpenGL backends."
}
},
"center": [0, 45],
"zoom": 1,
"sources": {
"dem-ocean-color-relief": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.ocean.webp"
]
},
"dem-ocean-hillshade": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.ocean.webp"
]
},
"dem-terrain-color-relief": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.terrain.png"
]
},
"dem-terrain-hillshade": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.terrain.png"
]
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": "#0d1a0a"
}
},
{
"id": "bathymetry-color-relief",
"type": "color-relief",
"source": "dem-ocean-color-relief",
"paint": {
"color-relief-opacity": 1,
"color-relief-color": [
"interpolate",
["linear"],
["elevation"],
-9500, "#020d18",
-4000, "#041828",
-500, "#082438",
-1, "#0d3050",
0, "rgba(0,0,0,0)"
]
}
},
{
"id": "bathymetry-hillshade",
"type": "hillshade",
"source": "dem-ocean-hillshade",
"paint": {
"hillshade-method": "igor",
"hillshade-illumination-anchor": "map",
"hillshade-exaggeration": 0.4,
"hillshade-shadow-color": "#000000",
"hillshade-highlight-color": "#1a3a5c",
"hillshade-accent-color": "#000000"
}
},
{
"id": "terrain-color-relief",
"type": "color-relief",
"source": "dem-terrain-color-relief",
"paint": {
"color-relief-opacity": 1,
"color-relief-color": [
"interpolate",
["linear"],
["elevation"],
0, "rgba(0,0,0,0)",
0.1, "#006600",
500, "#00FF00",
1000, "#FFFF00",
2000, "#FF8800",
3000, "#FF0000",
5000, "#FFFFFF"
]
}
},
{
"id": "terrain-hillshade",
"type": "hillshade",
"source": "dem-terrain-hillshade",
"paint": {
"hillshade-method": "standard",
"hillshade-exaggeration": 0.6,
"hillshade-shadow-color": "#000000",
"hillshade-highlight-color": "#ffffff",
"hillshade-accent-color": "#000000"
}
}
]
}

View File

@@ -0,0 +1,127 @@
{
"version": 8,
"metadata": {
"test": {
"height": 256,
"width": 256,
"allowed": 0.01,
"description": "Tests that color-relief renders correctly above a vector (fill) layer. Layer order mirrors the reference WDB_COLOR_RELIEF_DARK style: bathymetry-color-relief → bathymetry-hillshade → land-fill (vector, sandwiched) → terrain-color-relief (above vector!) → terrain-hillshade. This specifically targets a Metal rendering regression where color-relief placed above a vector layer failed to render, while OpenGL rendered it correctly."
}
},
"center": [0, 45],
"zoom": 1,
"sources": {
"dem-ocean-color-relief": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.ocean.webp"
]
},
"dem-ocean-hillshade": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.ocean.webp"
]
},
"osm-basemap": {
"type": "vector",
"tiles": [
"local://tiles/{z}-{x}-{y}.osm_basemap.pbf"
]
},
"dem-terrain-color-relief": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.terrain.png"
]
},
"dem-terrain-hillshade": {
"type": "raster-dem",
"tiles": [
"local://tiles/{z}-{x}-{y}.terrain.png"
]
}
},
"layers": [
{
"id": "background",
"type": "background",
"paint": {
"background-color": "#0d1a0a"
}
},
{
"id": "bathymetry-color-relief",
"type": "color-relief",
"source": "dem-ocean-color-relief",
"paint": {
"color-relief-opacity": 1,
"color-relief-color": [
"interpolate",
["linear"],
["elevation"],
-9500, "#020d18",
-4000, "#041828",
-500, "#082438",
-1, "#0d3050",
0, "rgba(0,0,0,0)"
]
}
},
{
"id": "bathymetry-hillshade",
"type": "hillshade",
"source": "dem-ocean-hillshade",
"paint": {
"hillshade-method": "igor",
"hillshade-illumination-anchor": "map",
"hillshade-exaggeration": 0.4,
"hillshade-shadow-color": "#000000",
"hillshade-highlight-color": "#1a3a5c",
"hillshade-accent-color": "#000000"
}
},
{
"id": "land-fill",
"type": "fill",
"source": "osm-basemap",
"source-layer": "land",
"paint": {
"fill-opacity": 1,
"fill-color": "#FF4400"
}
},
{
"id": "terrain-color-relief",
"type": "color-relief",
"source": "dem-terrain-color-relief",
"paint": {
"color-relief-opacity": 1,
"color-relief-color": [
"interpolate",
["linear"],
["elevation"],
0, "rgba(0,0,0,0)",
0.1, "#006600",
500, "#00FF00",
1000, "#FFFF00",
2000, "#FF8800",
3000, "#FF0000",
5000, "#FFFFFF"
]
}
},
{
"id": "terrain-hillshade",
"type": "hillshade",
"source": "dem-terrain-hillshade",
"paint": {
"hillshade-method": "standard",
"hillshade-exaggeration": 0.6,
"hillshade-shadow-color": "#000000",
"hillshade-highlight-color": "#ffffff",
"hillshade-accent-color": "#000000"
}
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
## Attribution
| File pattern | Format | Description | Source / License |
|---|---|---|---|
| `{z}-{x}-{y}.ocean.webp` | WebP raster-DEM (Mapbox terrain-RGB encoding) | Ocean bathymetry DEM tiles, z=0–1 | Derived from [GEBCO](https://www.gebco.net/) gridded bathymetric data. Public domain. |
| `{z}-{x}-{y}.osm_basemap.pbf` | Vector (PBF, raw/uncompressed) | Land, water, and coastline polygons, z=0–1 | © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright), [ODbL](https://opendatacommons.org/licenses/odbl/). Polygons from [osmdata.openstreetmap.de](https://osmdata.openstreetmap.de/). |
| `{z}-{x}-{y}.terrain.png` | PNG raster-DEM (Mapbox terrain-RGB encoding) | Terrain DEM tiles | Credit: [AW3D30 (JAXA)](https://www.eorc.jaxa.jp/ALOS/en/dataset/aw3d30/aw3d30_e.htm). Added in [369af13](https://github.com/maplibre/maplibre-native/commit/369af13ead1b). |

View File

@@ -374,7 +374,7 @@ void RenderColorReliefLayer::update(gfx::ShaderRegistry& shaders,
}
builder->setShader(colorReliefShader);
builder->setDepthType(gfx::DepthMaskType::ReadOnly);
builder->setEnableDepth(false);
builder->setColorMode(gfx::ColorMode::alphaBlended());
builder->setCullFaceMode(gfx::CullFaceMode::disabled());
builder->setRenderPass(renderPass);

View File

@@ -367,7 +367,7 @@ void RenderHillshadeLayer::update(gfx::ShaderRegistry& shaders,
}
hillshadeBuilder->setShader(hillshadeShader);
hillshadeBuilder->setDepthType(gfx::DepthMaskType::ReadOnly);
hillshadeBuilder->setEnableDepth(false);
hillshadeBuilder->setColorMode(gfx::ColorMode::alphaBlended());
hillshadeBuilder->setCullFaceMode(gfx::CullFaceMode::disabled());
hillshadeBuilder->setRenderPass(renderPass);