4 ms·
But sliver triangles avoid overdraw and thus reduce, not increase, fragment shader invocations? Avoiding overdraw in alpha blending situations is the point of t
by Jare 5y ago
But sliver triangles avoid overdraw and thus reduce, not increase, fragment shader invocations? Avoiding overdraw in alpha blending situations is the point of this article.
Last time I rendered this kind of thing, I just did it the simple way you describe so you're not wrong. I just used stencil to prevent alphablending overdraw issues. If you can afford it, it's the simplest and actually the most flexible approach, as it works with any topology, including multiple overlapping segments (e.g. curves, X- and T-shapes, etc).
- bsder 5y agoHow do you handle two lines drawn on top of one another? The first line sets a bunch of pixels in the stencil buffer that somehow then need to get unset before drawing the next line, no? I'm actually really interested in this as I'm having a really complicated time doing what should be relatively simple 2D CAD-type stuff with any of the modern graphics APIs (Vulkan or DirectX 12). Any time I want to draw a world-coordinate vertex thing with a device pixel width dimension life just gets horrible.
- pcwalton 5y agoYou could try using the Z buffer instead of the stencil buffer. Give each object a different Z coordinate and use GL_LESS/GL_GREATER depth tests to avoid overdrawing.
- thomasikzelf 5y agoI tried this but it rules out doing antialiasing in the fragment shader.
- pcwalton 5y agoIt shouldn't if you submit the paths from back to front and enable blending. You can then use analytic AA (distance-based or whatever you'd like) to blend with paths behind the one you're currently drawing.
- pcwalton 5y agoFragment shader invocations are minimum 2x2 pixel blocks. Portions of those 2x2 pixel blocks outside the primitive represent wasted computation. Sliver triangles, with their long edges and small sizes, tend to increase the number of wasted helper invocations.
- kevingadd 5y agoAs patrick said in another reply, this has not been true for a while. On all modern GPU hardware I know of, sliver triangles fall into the category of "degenerate triangles", where the hardware by necessity wastes a ton of time and energy shading pixels that can't ever hit the framebuffer. You can partially avoid this with early-Z and early-stencil (which will reject entire groups of pixels), but those will only help if most or all of your degenerate triangle is invisible. If a single pixel passes that early culling, it will have to shade at least 4 pixels to produce that one output pixel. If you are concerned about the cost of drawing a quad where 25-50% of it is transparent/discarded, you can create a simple hull out of 2-4 triangles where it suffers less from the overhead of shading those 2x2 groups. That is a common compromise that can produce improved performance by skipping 2x2 groups that don't contribute to the output frame. In practice all quads suffer from this, and the larger the quad the more cycles you waste shading the seam between the two triangles twice. The overhead for large quads is still pretty small in comparison, but if you're doing full-screen post-processing effects it can produce a measurable speed-up to draw a single huge (viewport clipped) triangle instead. It's possible some hardware has optimizations to mitigate this, but it's also the case that since shaders can do things like read/write from arbitrary buffers, any optimization that avoids shading the seam twice would cause incorrect differences in behavior, so it's hard to do that optimization in all cases.