visgl / deck.gl

WebGL2 powered visualization framework
https://deck.gl
MIT License
12.04k stars 2.07k forks source link

Mapbox/Maplibre elevation compatibility #7064

Open Baseform opened 2 years ago

Baseform commented 2 years ago

Description

We're using interleaved terrain rendering with Deck and Mapbox/Maplibre. There is a mismatch of elevation on renders - probably due to camera positioning between Deck and the others

Expected Behavior

I'd expect to see an overlap. WebMercatorViewport docs mention compatibility of default parameters

Steps to Reproduce

This codepen allows for toggling between both deck and the new Maplibre Terrain 3D versions. We've also tested with Mapbox with the same results.

[https://codepen.io/diogovit/full/wvyNjwW]

Environment

Pessimistress commented 2 years ago

Can you help me understand how this is going to be used? deck.gl does not support offseting/overlaying layers over a base terrain (it's something we are exploring, but not yet implemented), so even if the camera movement matches that of mapbox/maplibre, the data positions may not be very useful.

With that said, the mapbox module (MapboxLayer, MapboxOverlay) should definitely make an effort to match the camera matrices. I do not think they support terrain in the base map right now.

On a high level, deck.gl's TerrainLayer works just like other layers - it renders in a self-contained context and does not affect the camera control or any other layers. I agree that this is something we should address, probably by introducing a new operation. Whether deck's default behavior should be identical to that of Mapbox's is open for discussion.

@kylebarron @chrisgervang

Baseform commented 2 years ago

@Pessimistress

We have developed a rich visualization solution for water utility network at baseform.com. This includes mapping geojson/mvt infrastructure (pipes, buildings, valves and others), as well as visualizations of hydraulics (similar to trips layer) and aggregation analytic quantities, from population, to consumer usage, to water quality and water flows. The non-deck based solution is presented here: https://baseform.com/np4/papps0.html or https://baseform.com/np4/papps1.html OSM based vector maps as an alternative to satellite imagery are available as background.

For quite a while now we've been migrating from OL (and from our own threejs 3D viz) to deck and it's finally production ready. Besides being faster, more elegant, scalable and precise in drawing, deck.gl allows for near seamless transition from 2D to 3D. 99% of the code is deck.gl; the exception being vector streets for which we're using maplibre. The new terrain 3D feature of maplibre https://github.com/maplibre/maplibre-gl-js/pull/165would allow us to have that as a 3D backdrop to our maps.

Note: 3D is particularly interesting for water and wastewater networks as gravity and pressure drive hydraulics, meaning that it's not just a nice visualization but actually useful in interacting with how water flows and networks work.

In the codepen I chose to use terrain layers for both deck.gl and maplibre to demo the difference in rendering/camera position/elevation/? this disconnect is the same using any other type of layers - my guess is that it is more related to the WebMercatorViewport. I noted that in the docs, a reference to map box is made: "altitude has a default value that matches assumptions in mapbox-gl".

I'm available to share what we have on a web call if that makes sense to you - we'd also be open to present, reference or showcase as a commercial application of the technology.

Pessimistress commented 2 years ago

As far as I can tell, Mapbox does not expose the center elevation with any public API. Map has a queryTerrainElevation method but is not the same as the altitude it uses to target the camera. I just glanced at the Maplibre implementation and it does not seem to expose any API for this purpose either.

If deck.gl is to support Mapbox/Maplibre terrains, feature requests need to be submitted to both libraries to properly expose all the parameters that they use to calculate the viewport matrices. deck.gl does sometimes employ hacks in order to work better with a base map provider. However, considering the Mapbox/Maplibre code bases have diverged significantly, any usage of private API would be too many moving targets for us to chase.

wipfli commented 2 years ago

Feel free to submit a pull request to MapLibre GL JS if you need some more public API...

Pessimistress commented 2 years ago

Tracking the mapbox-gl request here, though it's much more complicated than maplibre. https://github.com/mapbox/mapbox-gl-js/issues/12040

harisbal commented 2 years ago

Can you help me understand how this is going to be used? deck.gl does not support offseting/overlaying layers over a base terrain (it's something we are exploring, but not yet implemented), so even if the camera movement matches that of mapbox/maplibre, the data positions may not be very useful.

@Pessimistress If I read your comment well, it is likely that deck.gl will support presenting multiple layers at different heights (e.g. a GridLayer on surface level and another one at an underground level). Is there any PR or issue that you could track for this feature.

Pessimistress commented 2 years ago

@harisbal This issue is about the @deck.gl/mapbox module. My comment said that we don't automatically snap data to the terrain surface. You can already render layers at any elevation of your choice.

birkskyum commented 2 years ago

@Pessimistress There seems to be a bug in the deck.gl terrain layer that should be fixed before synchronization is attempted. When you zoom in and out there is around zoom level 12.1 a sudden jump in elevation.

Here is an example only with deck.gl (try zooming out a bit and see the terrain get more flat): https://stackblitz.com/edit/typescript-sguv1u?file=index.ts

In comparison, it can be seen that zoom in/out doesn't give the same jump in MapLibre with the exact same terrain data (not synching camera here): https://stackblitz.com/edit/typescript-bgbhil?file=index.ts

The zoom issue in deck.gl terrain persist if it i.e. is added as a MapboxOverlay from @deck.gl/mapbox in MapLibre, which might hint to where the bug doesn't come from: https://stackblitz.com/edit/typescript-hxvo9j?file=index.ts

birkskyum commented 1 year ago

Many deps were getting a bit old - Here is an updated version where it's possible to swap between maplibre / deckgl terrain: https://stackblitz.com/edit/vitejs-vite-qgwfna?file=index.html

ssaornil commented 1 year ago

Any progress on this?

I came to ask for this feature too. We are using MapboxOverlay and it would be great if the deck layers would automatically match the terrain elevation.

I thought the terrain extension would work but apparently it doesn't either.

I prepared a code sandbox with the use of MapboxOverlay and TerrainExtension if you are curious about it. https://codesandbox.io/s/deck-layers-with-3d-927gh8?file=/src/App.tsx

Pessimistress commented 1 year ago

@ssaornil If you change interleaved to false you can see that the layer does show up. When using interleaved mode there are often issues regarding GL context state handoff. Feel free to open a bug.

chrisgervang commented 1 year ago

The TerrainExtension is only supported within deck.gl since there isn't a public api in Maplibre/Mapbox to access the elevation in a performant way, afaik (there is a function to perform one-off lookups, but this could only work for offset and performance is a big question mark).

So, maplibre terrain layer won't work as a target for draping or offsetting, so you'll continue to need to use a deck.gl TerrainLayer or Tiles3DLayer as the target.

birkskyum commented 10 months ago

There is a terrain bug in Deck.gl. Solving that might help on this issue. In this example, the terrain "jumps"/changes the elevation when zooming out just a bit (at exactly zoom 12): https://deck.gl/examples/terrain-layer . Increasing the rScaler will exaggerate it further.

chrisgervang commented 10 months ago

I can reproduce the "jump"

I wonder if this jump could have anything to do with #1937, our mixed 32/64 bit mode. If I recall, that changes between modes at a particular zoom level.

What zoom level is it jumping?

birkskyum commented 10 months ago

@chrisgervang consistently at zoom = 12 for that data, and the stackblitz example i shared above. Both utilize RGB DEM tiles.

It doesn't happen in this black/white png example though : https://deck.gl/docs/api-reference/geo-layers/terrain-layer

chrisgervang commented 10 months ago

https://github.com/visgl/deck.gl/blob/0c8e2163039354581f55fada92bd4cbe5526d44e/modules/core/src/viewports/viewport.ts#L223

Edit: So it looks like zoom +/-12 behaves differently, but I'd have to familiarize myself more with this code before understanding if this is the cause and what could fix it.

birkskyum commented 10 months ago

When terrain was initially introduced in MapLibre there was also an 'elevationOffset', which was set to a large value lifting everything above sea-level, but it kept producing new issues. It's since been completely removed, which as a bonus allows for querying a point and getting the correct altitude. I noticed the offset is set to -10000 in the terrain example, and it looks a bit like a similar workaround.

chrisgervang commented 10 months ago

The offset is user editable already, right? That offset was provided by Mapbox. Do you have a link to the Maplibre change?

birkskyum commented 10 months ago

It's here

I won't rule out that a simple offset setting might appear again, but it's not something anyone has requested yet - and it should preferably be for the use case that someone is interested in offsetting the altitude of the DEM rather than fighting a near/far plane clipping or tile loading

birkskyum commented 9 months ago

In deck.gl the WEB_MERCATOR_AUTO_OFFSET projection mode appear to be used at high zoom level for increased performance and precision. I still don't know if the jump at zoom 12 is caused by WEB_MERCATOR being imprecise compared to WEB_MERCATOR_AUTO_OFFSET at that zoom level, or if WEB_MERCATOR_AUTO_OFFSET isn't correct.

UberMouse commented 1 month ago

What's the status on this now? The TerrainExtension work was merged which targets this problem, but my understanding is that only works when the terrain layer is rendered by deck.gl, not when it's rendered by Mapbox/Maplibre? And presumably the inverse issue would happen if the terrain layer was rendered by deck.gl instead of Mapbox/Maplibre? Is that correct?

birkskyum commented 1 month ago

understanding is that only works when the terrain layer is rendered by deck.gl

No, this is a problem in the deck.gl terrain renderer - it makes a jump at certain zoom level, independently of everything else