fix(core): add shader-based globe occlusion for IconLayer, TextLayer, and ArcLayer#9975
fix(core): add shader-based globe occlusion for IconLayer, TextLayer, and ArcLayer#9975chrisgervang wants to merge 4 commits intomasterfrom
Conversation
charlieforward9
left a comment
There was a problem hiding this comment.
Looks like a nice cleanup for dependent projects building workarounds to deal with this.
A UX issue ive had to accept with the Text culling issue is not culling the GlobeView, which leads to this:
20260203-2059-29.4561020.mp4
Ill pull this version into my repo and test it out.
(is there an easier way for production builds to depend on deck.gl feature branches alternative to the submodule setup?)
felixpalmer
left a comment
There was a problem hiding this comment.
My hunch still is that there should be a way to fix this by setting up the camera parameters (#9592 (comment)) correctly - but for now this does resolve the issue.
In general we have a number of z-indexing issues when integrating the the maplibre globe, so perhaps in the future we'll be able to safely remove this again
There was a problem hiding this comment.
seems a waste to do return visibility > 0.0 ? 0.0 : 1.0; only to undo it with project_globe_get_occlusion(commonPosition) > 0.5
There was a problem hiding this comment.
Thanks for catching that. I was exploring the idea of fading around the horizon and this got left over since I decided to start with a simple fix for now
There was a problem hiding this comment.
I worry that this will cause artifacts when one end of a line segment will be occluded, while the other isn't. Instead you could set the widthPixels to 0 when occluded
There was a problem hiding this comment.
Good call, I'll switch to doing that
… and ArcLayer Fixes #9777 and #9592. The previous approach of setting cullMode: 'back' globally for globe projections had two issues: 1. Billboard geometry (IconLayer, TextLayer) doesn't have proper back faces, causing icons and text to be incorrectly culled and disappear 2. The coordinate system handedness could cause culling to work in unexpected ways This change implements shader-based globe occlusion that works for all geometry types: - Added project_globe_get_occlusion() and project_globe_is_occluded() functions to the projection shader module (both GLSL and WGSL) - IconLayer, TextLayer (via MultiIconLayer), and ArcLayer now automatically hide geometry that is on the back side of the globe - Removed the global cullMode: 'back' parameter from getDefaultParameters() in deck-utils.ts - Updated examples to remove manual cullMode: 'none' workarounds The solution is transparent to users - no API changes or special configuration needed. https://claude.ai/code/session_01P6canyQPTd6nckN66pauLK
Adds a billboard dimension to basemap-browser example to test IconLayer and TextLayer behavior with billboard: true vs false on globe projection. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
abe4b3c to
79f4262
Compare
|
Here's what the maplibre website example and get-started maplibre globe examples now look like without
|
- Simplify project_globe_is_occluded to return bool directly (remove redundant float conversion via project_globe_get_occlusion) - Fix GLSL icon-layer to use anchor position without offset for occlusion check, matching WGSL behavior - Fix arc-layer to set widthPixels=0 when occluded instead of hard clipping vertices, avoiding artifacts at segment boundaries Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TextBackgroundLayer was missing the project_globe_is_occluded check, causing ghost background rectangles to appear on the back of the globe while the text itself was hidden. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang actually, no it looks broken to me as the flights are getting cut off too early. The current code does it correctly: Screen.Recording.2026-02-09.at.11.41.02.movwith the shader addition in this PR, we are losing the flights near the horizon - so I'm thinking this approach isn't going to work :/ Actually, I'm a bit confused why this PR needs to fix |
|
I had an approach in my workaround that blended opacity-fading with a more generous occlusion threshold for smoother transition - but I agree the ArcLayer is a difficult edge case since it is not a layer that sits on the surface of the globe. |
|
Ah true, we can remove ArcLayer from the scope of this PR. I included it because it had the But looking again, those were setting it to "none" which the system does again anyways now I'm removing the "back" override in |


Fixes #9777, #9592, and #9554.
Problem
The previous approach of setting cullMode: 'back' globally for globe projections had two issues:
Solution
This change implements shader-based globe occlusion that works for all geometry types:
project_globe_is_occluded()function to the projection shader module (both GLSL and WGSL)The solution is transparent to users - no API changes or special configuration needed.
When to use
project_globe_is_occluded()In interleaved mode with basemaps (MapLibre, Mapbox), the basemap's depth buffer provides occlusion for most geometry automatically. The shader-based
project_globe_is_occluded()function is needed for specific cases where depth buffer occlusion doesn't work correctly:Usage Pattern
For instance-based layers (IconLayer, TextLayer), use the anchor position without offsets:
For segment-based layers (ArcLayer), use the actual vertex position:
https://claude.ai/code/session_01P6canyQPTd6nckN66pauLK