-
-
Notifications
You must be signed in to change notification settings - Fork 716
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
Globe: Tile borders fix #4868
base: main
Are you sure you want to change the base?
Globe: Tile borders fix #4868
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #4868 +/- ##
==========================================
- Coverage 87.77% 86.65% -1.12%
==========================================
Files 265 265
Lines 37946 37945 -1
Branches 2407 2548 +141
==========================================
- Hits 33306 32881 -425
- Misses 3579 3946 +367
- Partials 1061 1118 +57 ☔ View full report in Codecov by Sentry. |
Does changing the granularity can cause a performance issue? |
In theory it can, but stencil granularity got decreased from 4x4 quad grid to 1x1 grid, it is now drawing 2 instead of 32 triangles per tile. But both meshes are so tiny that it probably has no effect. |
The problem with solving this is that in globe rendering we can't simply use stencil masks to mark some pixels as belonging to a given tile and only render the tile to those pixels, because the geometry of the stencil mask will in general never match the geometry of the underlying fill layer. Either the mask is more tesselated than the fill layer (first imagethe PR) which causes gaps at the ends of tiles, or the stencil mask is less tesselated than the fill layer (second image the PR - this seems like a very common occurence, fill layers tend to be complex). The old solution was not to use stencil at all for fill layers, but that lead to the ocean stripes in the issue. Worse, it would possibly lead to some translarent layers being drawn twice at tile borders in some maps. So the old solution should not be used. There are 3 possible solutions, I think:
The problem is that the facebook tiles rely on maplibre (or possibly mapbox) cutting off tile geometry that is beyond the normal extend at some point, and they place some extra stripes beyond this point. But the cutoff point is not defined anywhere in the spec.
I'm not sure what solutuon to pick. Option 1 is definitely the most performant, and I tend to think option 2 is the best, since it is the simplest. I will try to make a benchmark to test the performance of 2 on a real world map. |
@ibesora see if you can help here, I'm not sure I fully understand the possible solution to this or deeply understand the problem. |
I've benchmarked option 2 (set minimal subdivision of all fill to 4, which should be enough to fix the seams). Loading MapTiler map of a city at zoom 11 takes on average:
|
I think our options are to either do option 1) and somehow convince Facebook not to include invalid geometry beyond the borders of their tiles, or do 2) and suffer a hit to tile load times at high zooms everywhere where globe will be used. Option 3 would also likely result in comparable performance hit as option 2. Also there is an implicit option 4: do nothing. Facebook tiles remain broken, there is still a visible border around tiles, tile loading performance does not degrade, stencil for fill layers remains disabled, possibly leading to overdraw issues in the future. |
Is it possible to introduce some flag to support this fix? This way the user has control if they need accuracy or performance...? |
I mean not merging this PR. It would mean we keep the stripes, but they will only appear in that one tile source from Facebook that is used in the original issue #4799 We would not introduce the seams round Alaska that are visible on the screenshots in the PR post.
It is, but it would need to be a flag on the source. This is overall a pretty hard problem to solve. Doing option 2 or 3 (preprocessing tiles either by removing geometry beyond tile borders or by subdivision) slows down map loads. I was thinking about fixing this with some creative stencil usage (similar to option 1) instead, but it has to have the following properties:
Setting up stencil in a way that does this is possible I think, but I'm afraid it would slow down rendering way too much because of state changes. We would need to draw some stencil-only masks after every fill tile draw, which means switching shaders and other rendering state, potentially hundreds of times per frame. |
While there might be issues with the facebook tiles, the following issue is a regression issue as far as I understand, and it requires fixing I believe: |
The aim of this PR is to fix #4799 and #4803. In its current state, it fixes both issues, but I have uncovered other related problems.
Both issues are fixed by simply re-enabling stencil testing for the fill layer, which causes fill geometry to be clipped to the bounds of its tile. This however introduces seams in the ocean at zoom levels around 7:
What is happening is that the ocean geometry is a simple quad, but the stencil mask is a curved shape that extended above the ocean quad (because it's min granularity was set to 4), and the ocean's further edge lies below the stencil mask edge, leaving some pixels above it still marked in stencil as belonging to this tile, but not filling them with pixels.
These seams are then simply fixed by tweaking the stencil mask granularity so that it is never higher than fill granularity. This however introduces other, more subtle artifacts:
These are in turn caused by the ocean geometry being more detailed than the stencil mask. These seams are generated around shores and islands, where the ocean geometry has more vertices, causing it to be more curved than the (now flat) stencil mask. So the ocean is projected above the stencil mask, causing pixels below it to not be filled. These pixels cannot be filled by the nearer ocean tile (which presumably has the same curvature at the given edge), because that tile's stencil mask does not cover these pixels.
I tried fixing this by generating extra geometry at tile edges that extends to the planet's center, but this is also problematic, because there is no good way to determine what geometry is actually the tile's edge, because vector tiles tend to have extra border geometry beyond the regular tile extends. I'm not sure a heurestic would do here.
The original approach of not using stencil at all is also not good, because a tranparent fill layer could be drawn two or more times near tile edges due to this border geometry.
I don't yet know how to best solve this, so I am making this a draft PR for now.