Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3d models are not correctly hidden using the globe view #4817

Closed
ibesora opened this issue Oct 10, 2024 · 2 comments · Fixed by #4838
Closed

3d models are not correctly hidden using the globe view #4817

ibesora opened this issue Oct 10, 2024 · 2 comments · Fixed by #4838
Labels
bug Something isn't working globe Globe related issues

Comments

@ibesora
Copy link
Collaborator

ibesora commented Oct 10, 2024

When using a 3d model on the globe view, the model is not correctly occluded when it goes to the back side of the globe.

Screen.Recording.2024-10-10.at.13.19.40.mov

maplibre-gl-js version: 5.0.0-pre.1

browser: Chrome

Steps to Trigger Behavior

Using the globe-3d-model example

  1. Move the camera to make the 3d model get behind the horizon

Expected Behavior

The 3d model should be occluded

Actual Behavior

You can see the 3d model right through the globe

@ibesora ibesora added bug Something isn't working globe Globe related issues labels Oct 10, 2024
@HarelM
Copy link
Collaborator

HarelM commented Oct 10, 2024

I believe this should be handled by the custom layer code, shouldn't it?
Or is this issue about updating the example's code?

@kubapelc
Copy link
Collaborator

kubapelc commented Oct 14, 2024

This is caused by MapLibre in general not having a depth buffer that stores actual depth values. Instead, depth buffer is used to minimize overdraw of transparency: opaque parts of all layers are drawn first, each using a constant depth value, then transparency is drawn while testing against this depth buffer. Layers higher in the stack get depth values closer to the camera, so if a lower transparent layer is covered by a higher opaque layer, the transparent layer's pixels get rejected by depth testing and overdraw is avoided.

These depth values are allocated near 1, from the far part of the depth range, so that drawing fill extrusion and 3D custom models works - these will occlude themselves properly. This also means that extrusion overwrites the depth buffer values the layers used, but this is okay, since fill extrusion will always render on top of the rest of the map.

This stopped being true with globe, since 3D objects can now be occluded by the map itself.

Fill extrusion currently solves this by doing globe occlusion in the pixel shader by computing a ray-sphere collision and discarding the pixel if it is occluded. I don't think this is the best solution, but it works for now.

A better solution would be to draw all 3D objects last, regardless of where they are placed in the layer stack. This would mean that when drawing 3D, the "2D" parts of the map would already be done rendering, and the depth buffer constructed during the rendering process is not needed anymore. We could then overwrite it: clear it, render the globe sphere with its actual depth values, and then get proper occlusion without doing it in the pixel shader. (And for a flat map it would make sense to instead draw all 3D first, so they can occlude the map and prevent overdraw. edit: this would not work, fill-extrusion and 3D is sometimes transparent and thus must be drawn after the main map)

I didn't implement this at first, as I didn't realize it was possible at that time. I was unsure whether a 2D layer could draw on top of a 3D one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working globe Globe related issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants