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

Custom layer with renderWorldCopies #9759

Closed
zakjan opened this issue Jun 4, 2020 · 6 comments
Closed

Custom layer with renderWorldCopies #9759

zakjan opened this issue Jun 4, 2020 · 6 comments

Comments

@zakjan
Copy link

zakjan commented Jun 4, 2020

mapbox-gl-js version: 1.10.0

Question

Custom layer receives the transformation matrix in prerender/render functions for a single world only. When renderWorldCopies is true, how do I get the transformation matrix for all rendered world copies? So that I could render the copies of the custom layer as well.

Links to related documentation

https://docs.mapbox.com/mapbox-gl-js/api/properties/#customlayerinterface
https://docs.mapbox.com/mapbox-gl-js/example/custom-style-layer/
https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/

@arindam1993
Copy link
Contributor

@zakjan , we don't have a good way of doing this currently. We currently achieve the renderWorldCopies behaviour by duplicating the zoom level 0 tile multiple times.

The analogy for a custom layer would be having multiple model matrices for your custom layer object. However since we don't provide separated model, view and projection matrices from the custom layer interface, this is tricky to achieve.

@zakjan
Copy link
Author

zakjan commented Jun 4, 2020

I have found an undocumented way how to do it currently, without any more matrices.

In prerender/render, I get the world offsets with:

const worldOffsets = map.transform.getVisibleUnwrappedCoordinates({z: 0, x: 0, y: 0}).map(x => x.wrap).sort((a, b) => a - b);
return worldOffsets.slice(1, worldOffsets.length - 1);

This returns for example [-1, 0, 1].

Then I render my shaders multiple times for each world offset, pass it as a uniform, and add vec2(uWorldOffset, 0) to every Mercator position before multiplying with the matrix. It works!

Is this a good solution, or would you recommend anything better? I'm worried about the way to get the world offsets, because map.transform is private.

It seems that it would be helpful if a function to get the world offsets is provided as a public method officially on its own, unrelated to custom layers.

@zakjan
Copy link
Author

zakjan commented Jul 21, 2020

Closing, I have switched to simple map.getBounds. It returns the entire bounds, including world copies. The bounds can be transformed to Mercator, and used as shader input vertices, rendering the custom layer in a single draw call.

@zakjan zakjan closed this as completed Jul 21, 2020
@GarrettCannon
Copy link

@zakjan Any chance you could throw an example into a codepen/jsfiddle? I would like to be able to do the same thing. Much appreciated!

@m9dfukc
Copy link

m9dfukc commented Oct 7, 2023

@zakjan I would also be interested in how to apply the map.getBounds. Currently I do it with multiple render passes but that seems not very elegant. Any code example would be very welcome even a very simple one just to get the rough picture.

Thanks!

@tangzijun
Copy link

Here is my solution:maplibre/maplibre-gl-js#4614 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants