-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Fix vector tile overdrawing with overlapping tiles from different zoom levels #6768
Comments
Another option would be, for vector sources via the Mapbox API, ignore the maxzoom defined in the tilejson and simply request tiles at a higher zoom. So, let the server overzoom: In this case the Mapbox API will do the 404 check internally and will clip out a new tile for you. |
Thanks for summarizing the issue in this ticket @jfirebaugh! The original reason for the change in parent tile loading was to support "sparse" raster tilesets in JS, so in the case where a parent tile had data for a region with no corresponding child tile in one or more quadrant of the parent, we display the data in that area by retaining the parent and using a modified vertex buffer as a "stencil buffer". It also was meant to bring JS in line with the Native update_renderables tile retention logic which changed to "required" loading of parent tiles (from "optional" loading/retention) to deal with a bug in the node bindings (I think) mapbox/mapbox-gl-native#8769
I don't think this will actually fix the issue for sparse tilesets because we will still need to retain the loaded parent if a child is not yet available to avoid a flickering when zooming, and even if we don't actively load new parent tiles, previously cached tiles will still overdraw. Here is an example from the release prior to the tile loading changes (you need to zoom in and out a bit to reproduce) http://jsbin.com/donugareji/edit?html,output
@ryanhamley and I tested this out and, yep, this solves the overdraw issue but causes flickering on zoom 👎
I don't think this will solve the issue for all users, because not all tilesets have TileJSON bounds, and for some reason, the tileset in the example above TileJSON bounds are the mercator projection bounds while the data is only in a very small area– this could be an issue with API maps/unpacker?
I'm thinking this might be the only fool-proof option, but we won't be able to use the same technique as we did with raster tiles (because the raster tile vertex buffer only represents the bounds of the tile, we generate custom vertex buffers on the fly to mask out areas of overdraw). To use the same technique with vector layers, I think we'll have to render clipping masks to the stencil buffer for each tile's mask VAO (instead of from the general tile extent VAO). No sure what performance implications this will have, but it's worth a try I think given the above. @springmeyer thanks for the suggesstion!
I don't think the current issue is a problem with overzooming – its mainly an issue with sparse tilesets where some children of a parent tile have data and others do not, so the parent is retained and overdraws on the child tile. |
@mollymerp I'm proposing not retaining/overdrawing but rather requesting tiles from the server and letting it overzoom. Or am I missing something? |
I don't think we should rely on server-side overzooming, or ever request tiles that go beyond the TileJSON's |
update here from some more investigations @ryanhamley and I did:
I have two more ideas:
I'm open to other ideas if anyone has thoughts! |
🚗 drive-by thought: in cases where only some child tiles fail, can we iterate through the features inside each successful child tile, identify the same feature in the parent tile, and cull those out of the parent, to avoid overdraw? Only thing is, I can't say how reliable the deduping step is, without some unique feature id. |
we fixed this 90% for circle layers in #6803 – persistent overdraw is no longer present, but there is flashed overdraw when changing zoom levels (loading tiles from the network). A more permanent fix will require some kind of intelligent vertex culling and would be a more significant lift. |
The tile loading logic in Mapbox GL JS attempts to load a parent tile in certain cases when a request for a child tile fails, e.g. the tile response is a 404, or a 200 with a content length of 0. This is intended to compensate for situations where tiles are not available at the current zoom level, but may be available at lower zoom levels, which could be overzoomed.
Unfortunately, this leads to overdraw in certain situations. I believe the primary situation (there may be others) involves:
Under these conditions, the map succeeds in loading one or more tiles at zoom
z
inside the bounds, but fails on one or more tiles outside the bounds. This triggers requests for tiles atz-1
that succeed, returning tiles that overlap the child tiles. Both parent and child tiles are rendered, producing overdraw. (The fallback loading behavior was originally implemented for fully opaque raster tiles, and semi-transparent vector tiles was not taken into account.)Multiple issues have been filed relating to this behavior:
IIRC, we originally limited the parent tile fallback behavior to raster sources. This issue probably dates to when we expanded that behavior to vector sources as well. I can think of a few ways we might fix it:
@kkaefer, @mollymerp you're most familiar with tile loading / clipping behavior. What are your thoughts?
Making this high priority since it's affecting multiple customers. cc @lilykaiser
The text was updated successfully, but these errors were encountered: