visgl / deck.gl

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

[Feat] [RFC] Have FillStyleExtension support other scaling behaviours #7600

Open DanielBoa opened 1 year ago

DanielBoa commented 1 year ago

Target Use Case

When using the FillStyleExtension it would be nice to be able to configure different texture scaling behaviours.

Currently the texture is always scaled to the world/common space, so as you zoom or pan the texture will scale and move along with other map features. As an aside this behaviour doesn't seem to work correctly as zooming too far in/out can result in moiré patterns.

I believe for most use cases it would be preferable that the texture remain the same size as you zoom, but move along with other features as you pan.

Proposal

I think it could make sense to borrow the same units convention used elsewhere in the API for properties such as radiusUnits or lineWidthUnits. So you could make the texture scale by "meters" – more or less the existing behaviour – or "pixels" which would have the texture remain the same size as you zoom/pan.

I've tried two approaches to achieve the desired behaviour so far, but neither have been completely successful;

Generate pattern UV from screen space

If I use the clip/pixel space to generate the texture UV instead of the world/common coordinates I can indeed get the desired scaling effect, however with this approach the fill pattern doesn't move when you pan, instead it's fixed to the viewport. I tried introducing an offset by converting the common origin to clipspace but didn't get anywhere really.

https://user-images.githubusercontent.com/1169866/214907054-dbb3321d-d1e1-49dd-8a39-e59f7ad04d8f.mp4

This is close to my desired behaviour, I just don't know the correct way to "anchor" the pattern to the world whilst scaling it to screen.

Calculate & pass a new scale value as uniform

After trying and failing with the above approach I tried to implement a slightly different behaviour whereby I'd have the texture scale as it currently does but then "jump" back to its original scale on every zoom integer (this is difficult to describe but it was inspired by this Mapbox fill-pattern example).

This does work but when you zoom too close you start to see strange artefacts. I'm not sure why this is but I believe it's probably a loss of accuracy when carving up the common map space too much?

https://user-images.githubusercontent.com/1169866/214907979-4db14a55-e80e-42aa-9dfd-32c60fdda9f0.mp4

Any direction on how to achieve this would be greatly appreciated, I feel as though there is likely a relatively simple way of achieving either of these examples and my knowledge of shaders & deck.gl's coordinate systems is failing me.

Here's a codesandbox of the latter example.

oscarnc commented 1 month ago

I'm very late to the party but I've had a go at this.

CodePen