-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Composite functions behave incorrectly with non-integer stops #8460
Comments
Awesome graphs and analysis! Thinking through one more thing here: for these cases where there's only a single stop in the given integer zoom range, could native get behavior identical to the gl-js behavior by changing how it calculates the interpolation factor? For example, with the first example, we could define the interpolation factor f such that f(z) = 0 for z <= 15, f(z) = 1 for z >= 15.2, and linearly interpolated in between. Then the shader would "do the right thing" when it uses f(z) to interpolate between the min and max values in the layout vertex attribute, and we'd get the magenta line in the graph. In the second example, it seems like this breaks down though. We can say f(z) = 0 for z <= 15, and f(16) = 1, but how do we define f for 15 < z < 16 and z > 16 (which we need because the tile may be rendered with overzoom)? The slope between 15 and 15.2 and between 15.2 and 16, depend on the function result at 15.2 for a particular source property value. But we only have one interpolation factor uniform, which must have the same value for a given z across all source features. So, my conclusion is that native can match gl-js exactly in the first example, but must use the approximation in blue in the second. Does that sound right? |
Let me just throw in another 🐒 🔧 here. Over in mapbox/mapbox-gl-js#4228, one thing I was working through is that, when Rather than wasting buffer space / attribute bindings on two different values of the same function, I have been thinking that it might be worth trying to have the shader calculate both of these values based on the stop values given to it. (I.e., we'd give it an additional interpolation_t value in order to calculate (b).). Not sure if this will end up being the best path, but even if not (and certainly if so!), I think we may want to consider bringing JS and native's composite-function calculations into sync by sticking with just 2 stops in JS. [1] The reason for this is because there's a bunch of layout data that's constructed using b), and the shader will thus need both values to make adjustments. |
Just ran into this with a style created in Studio: For two symbol layers, Changing the zoom levels to an integer ( |
Composite ("zoom-and-property") functions behave differently in mapbox-gl-native and mapbox-gl-js: part of this is intentional and part is a bug.
Considering the following function:
In mapbox-gl-js, this would cause fill-extrusions to rise from flat at z15 to property-based heights at z15.2, and then maintain that height at all higher zooms.
In mapbox-gl-native, since PaintPropertyBinders are evaluated at layout time at integer zoom levels, we won't be able to assign different slopes to z15-15.2 and 15.2-16, and it will, necessarily, behave differently.
However, current behavior is as such:
When I add another set of stops,
the above behavior only changes in that at z16 they reset to their intended property-based identity height and maintain that height to z22.
This is an issue with the logic in
coveringRanges
. I believe what needs to happen is:upper_bound
line should look forzoom + 1
The following shows the behavior with the above function for a feature with value=600: pink is how mapbox-gl-js behaves (and is the literal interpretation of the function stops), green is how mbgl-native currently works, yellow is how mbgl-native would work if only changing the
upper_bound
here to(zoom + 1)
, and blue is how I believe it should work, with artificial stops.Same below, but for a function specified as
The text was updated successfully, but these errors were encountered: