mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.2k stars 2.22k forks source link

Access 3D terrain mesh for use in custom 3D layer #12522

Open chrispahm opened 1 year ago

chrispahm commented 1 year ago

Motivation

I'm using threebox (three.js + mapbox) to render 3D wind turbines on a Mapbox map including shadows using @mourner's awesome suncalc module. https://observablehq.com/@chrispahm/visualizing-wind-turbines-in-3d-using-threebox

This works great, however it would be nice if the shadows would also be displayed on the ground when the 3D terrain is enabled. Right now, this is not possible since the custom 3D layer / three.js is unaware of the underlying 3D terrain mesh (see discussion in the threebox repo: https://github.com/jscastro76/threebox/issues/381). I guess if there was a way to access the terrain mesh, rendering the shadows should be possible?

Design Alternatives

Another way to approach this would be to re-create the mesh by following the steps outlined in @mourner's ObservableHQ notebook demonstrating MARTINI https://observablehq.com/@mourner/martin-real-time-rtin-terrain-mesh. However, this would a) require to query the elevation data a second time and b) also require to re-compute the mesh which is presumably available within GL JS internally. So do nothing is an option for sure, I guess it would just be a nice to heave feature!

Design

Potentially expose the current mesh geometry through an API so it can be consumed by three.js

chrispahm commented 1 year ago

For anyone interested, I eventually implement the "design alternative" approach: https://observablehq.com/@chrispahm/enabling-shadows-in-a-mapbox-terrain-map

image

Unfortunately, the resulting mesh is not identical to the one generated by GL JS internally, which sometimes leads to parts of a shadow vanishing below the maps surface. I tried to access the actual terrain data that I found in the map.transform.elevation property, but couldn't access the WebGLBuffer data since the copyBufferSubData is not available in WebGL 1 (related to https://github.com/mapbox/mapbox-gl-js/issues/8581)...