feat: data driven line opacity shading fix - #7514
Conversation
|
that is interesting, because running the modified benchmark above only shows 30% (20ms -> 30ms). I might not entirely understand how to run the benchmarks maybe. |
Well.. that seems to be an outlier in terms of how the style is written. CC @1ec5 Of 356 layers, 285 of 301 line layers have zoom-transitionable oppacity. For the other styles, I would not expect such a large impact given that americana is a bit out there in many metrics (complexity, ...) |
|
Running this benchmark is a little tricky. Since it's not already included on |
Migrating to lumagl is a large body of work and something that I don't think I have the time for. So to maybe ask: |
Sorry for the confusion,
There's no difference between
One more alternative worth weighing: rewrite the line-join geometry to eliminate overlapping triangles within a feature, while keeping overlap across features identical. That'd address the motivating OSM Carto case directly, with no breaking change, no opt-in, and likely minimal perf impact. I haven't dug into the join code yet so I can't say how hard it'd be. |
There are other styles that use enough data-driven |
|
To be honest, I would like to avoid adding a new style spec property for this if possible. |
|
The more fundamental fix I mentioned doesn't involve the stencil buffer. The source of self-intersections is in how we build line geometry: at every corner and miter, we generate overlapping triangles. If we change the way line corners are constructed so the pieces don't overlap, the artifacts disappear with no extra rendering pass and minimal perf cost. I think that's worth investigating, but I'd set expectations: this is a ~10-year-old known issue and nobody's tackled it, so it's probably harder than it sounds. Even if we fix the geometry, we'd only solve overlap within a single line feature. Overlap between different lines, and the broader "fade a whole layer" effect, still need something else. That's where I think
I hear you on not wanting to grow the spec. But this isn't growing it to patch one bug. It's adding one well-understood property that covers this case plus a long wishlist of others, without breaking existing styles or imposing cost on users who don't opt in. |
I can only introduce this one layer at a time, when I need it for capacity reasons. |
No problem! It's not all on your shoulders. I'm happy to chip in some dev time once we agree on a path forward. |
|
I believe we should start a discussion in the style-spec repo if we want to introduce a new feature to the spec. |
|
As a side-note, while the geometry approach might solve the places where lines change direction and overlap itself I don't think it can solve places where the line "crosses itself". Smart stencil logic might be an interesting approach to pursue, according to AI. |
On the Diagram
We're shipping this diagram no matter what! The diagram shows two "flavors" of opacity:
In this PR, If we add On Community Signalmapbox/mapbox-gl-js#4090 is the 5th most-commented issue on the mapbox-gl-js repo. That's the strongest data we have and it's strong. Our community isn't as old or large, so without some maintainer support behind a proposal here I don't think we'd get comparable independent data in our repo before v6 ships. On Fixing TessellationYou're right that re-tessellation only fixes overlap within a single feature (corners, miters, U-turns). It doesn't fix a line that crosses itself, and it doesn't fix two different features overlapping. Both of those still need flavor B opacity. I want to push back on the idea that tessellation fixes aren't worth pursuing though. It would fix many real-world cases (the OSM Carto motivating example, road casings with sharp bends) with zero spec change and lower perf cost. On StencilsWe could use a stencil if and only if we drop support for data-driven "flavor B" opacity. Stencils can make uniform opacity work but it can't compose two different alpha values at one pixel. A stencil-based #7490 would might have somewhat better perf but would stricter ( |
On Community SignalPer-layer opacity has come up within the Maplibre issue tracker rather often
|
|
For upgrading between version 5 and version 6 we started a migration guide so people who are upgrading can read it and do the relevant changes if need be. The main issue that I would like see solved is the following: This is, from my perspective, what users expect when they set line-opacity. Having said all that, a performance degradation is a problem we can't dismiss. |
|
@HarelM lets just discuss this on our TSC. |
osm-americana/openstreetmap-americana#995 (based on this fork) is much more representative of a typical production style, making heavier use of data-driven styling on the road layers for less complexity. We still haven’t optimized the railway layers to take advantage of #5812: osm-americana/openstreetmap-americana#526. But I suspect a significant performance hit there would be indicative of a broader problem. I had @lucaswoj run the same benchmarks on this branch. He found that the impact was less severe but still notable. Here are the per-frame stats he posted in Slack:
Even though OSM Americana’s complexity seems comical, I’ve definitely seen more complex Mapbox styles in the wild and have no reason to believe it doesn’t exist among MapLibre styles too. Another good data point would be the three MapLibre styles currently deployed on the osm.org homepage: Transport Map, Shortbread (VersaTiles Colorful), and MapTiler OMT (OSM OpenMapTiles). OpenHistoricalMap also has several styles in production. Some of these styles still have a lot of gaps that developers will want to fill in the future, so it’s important to have some slack, performance-wise. Taking a step back, I hope my comments in #7490 (comment) aren’t taken as a carte blanche on the performance side. I think designers are desperate enough for a solution to that problem to be open to some performance degradation, but the tradeoff will depend on the particular stylesheet and application. Also, note that the problem isn’t just about overlaps; designers care just as much about the spillover effect, which is not addressed by this change. |
|
I'd like to support @lucaswoj that a layer-opacity would be the better fix (but I do not currently have the bandwidth to push this forward myself, so I just add my 2 cents here instead of opening an issue maplibre-style-spec). Consider the following use-case which uses all three properties in a natural way: Visualizing a large number of gps tracks from different sport activities so that hotspots and mixed-use ways are clearly recognizable but the base map is never completely covered by the data. A very straightforward style to do that would use:
|
|
Rather than slipping in an offscreen render step behind the scenes, why not make it explicit? In response to a question of @nyurik's a couple years ago, I sketched out a design for doing more complex multi-pass styles. That's basically what you're doing here, but just for transparent lines. Muti-pass rendering is how most games work, helpful for functionality like shadows, data rendering and definitely where things are going in the future. You could get this improvement and open up a whole new area of cartographic experimentation. |
|
I have no clue what this would mean and I don't want to do render targets. I don't want to add targets and operations and this sort of thing for a simple fix like this |
You're already doing them. That's what an offscreen buffer is. Ignore the parts of my Stamen Watercolor post that discuss operations on the buffer. That's just what would be necessary for effects. The core idea is simple:
The extra part is making it explicit in the style sheet. |
|
+1 to render targets. They're effectively the same as what we've been calling "blending" or "comp-ops," which is a much larger discussion than |
One of the reasons I run the Native Development Group for Amazon is I have a non-M*pbox perspective on map rendering. I wasn't aware they'd discussed doing something similar and I'm going to avoid looking at it. The concept of render targets is something we use for weather rendering, but we didn't invent it. It's a pretty basic concept, not likely to infringe anyone's IP. |
|
Fair to keep your perspective independent of Mapbox. That said, there's a substantial MapLibre-side discussion on render targets and per-layer compositing that's worth engaging with before sketching new designs, none of which touches Mapbox prior art:
Whatever shape we land on will be stronger if it builds on the tradeoffs the community has already worked through here. |
|
I still don't understand what a render target is for a map designer. I think that this PR seems to not have the support it would need to get merged. |
Well it's a compromise for real-time rendering. A cartographer might not give it much thought unless they were doing something very experimental (e.g. Stamen Watercolor). It might normally just be an implied operation on a layer that requires a separate render step. Mapnik did stuff like this under the hood if you picked the right operations. The problem with just doing it by implication is the cost. Setting up a separate rendering step is expensive and you really need to let the map designer control its resolution, how it's blended back in and what goes in to it. If they care about performance at all, that is. For image based maps, they did things like this quite a bit, I believe. They'd form layers with a variety of content and then composite them after the fact. In a sense, it's a return to older, richer techniques. |
|
I don't think render target is the right approach. You, @sjg-wdw and @lucaswoj, are looking at render target like it's a second nature. Most users won't. I don't think the style spec should be overloaded with graphic engineering concepts. |
|
For what it’s worth, I’ve mainly seen a desire for compositing operations from non-engineers used to similar operations in graphic design. The operations fit more naturally in a raster graphics environment than a vector one, so the requests will naturally come out of things like wanting to implement Watercolor with vector tiles. Anyways, a general solution is much more substantial than what @CommanderStorm started out with. As far as I could tell from the monthly meeting this morning, a lot of the unease with the proposed change would be addressed by making behavior opt-in somehow. Is there a way to express the one case that he’s improving without necessarily having to implement the whole feature? Or is the whole feature ultimately easier to implement than making the one case intuitive to developers and designers? |
|
Let's keep the conversation in the newly created discussion. |

Second part of the line-oppacity during overlap fix, this time for data-driven styling.
There are more tradeoffs here of "how should this work", here is the one I came up with:
Opus helped a bit with finding all the places that needed tweaking.