3 ms·
This seems like a silly way to do vector graphics in a shader. What I've done in the past is representing the shape as a https://en.wikipedia.org/wiki/Signed_d
by pyrolistical 4y ago
This seems like a silly way to do vector graphics in a shader.
What I've done in the past is representing the shape as a https://en.wikipedia.org/wiki/Signed_distance_function https://en.wikipedia.org/wiki/Signed_distance_function to allow each pixel to figure out if it is inside or outside the shape. This avoids the need to figure out the winding.
Anti-aliasing is implemented as a linear interpolation for values near zero. This also allows you to control the "thickness" of the shape boundary. The edge become mores blurry if you increase the lerp length.
Shader toy demo https://www.shadertoy.com/view/sldyRj https://www.shadertoy.com/view/sldyRj
- Guzba 4y agoSDF is cool but not a generally good solution to GPU vector graphics. It only works for moderate scaling up before looking bad, the CPU prep figuring out the data the GPU needs takes far longer than just rasterizing on CPU would, etc. It's great as a model for games where there are many renders as world position changes but that's about it.
- johndough 4y ago> It only works for moderate scaling up before looking bad That problem has been solved by multi-channel signed distance fields https://github.com/Chlumsky/msdfgen https://github.com/Chlumsky/msdfgen
- cyber_kinetist 4y agoThe decomposition method used by msdfgen works well enough for fonts, but I'm not sure if it would work for more complex vector drawings. Probably would need much more than 3 color channels (= decompositions) to render something like the tiger SVG...
- tayistay 4y agoSeems like you're thinking of precomputed SDFs that are stored in a texture. They don't have to be :) (for example, my little library: https://github.com/audulus/vger https://github.com/audulus/vger)
- cyber_kinetist 4y agoIf you are talking about analytic SDFs, then you need a good "decomposition" method that can divide an arbitrary SVG into simple SDF-friendly primitives. Mabye it could be done, I think it can be a good research topic.
- jstimpfle 4y agoI don't know the details of using SDF (especially MSDF!) for doing vector graphics, but my understanding is that essentially it's a precomputation that involves _already_ a rasterization. I would like to know why you think the described approach is silly? It doesn't involve a final rasterization but merely a prefiltering of segments.
- pyrolistical 4y agoSDF are not precomputed. The SDF is implemented in the shader code itself. Added shader toy link in my OP
- Lichtso 4y agoWhat about SDFs of cubic bezier curves and rational bezier curves? Because these appear in vector graphics and I think there is no analytic solution for them (yet?).
- moonchild 4y ago> yet? SDF of a cubic bezier involves solving a quintic, so it's not analytic. There are approximations, of course, but for an outline, using an sdf is just silly. (For a stroke, you don't really have much choice--though it's common to approximate strokes using outlines.) I'll add that sdf aa is not as good as analytic aa.
- pcwalton 4y agoIIRC Loop-Blinn gives you a pretty good distance approximation using the 2D generalization of Newton's method to avoid having to solve the quintic. (Though I've never actually seen anybody implement Loop-Blinn for cubics because the edge cases around cusps/loops are annoying. Every Loop-Blinn implementation I've actually seen just approximates cubics with quadratics.) (Fun fact: Firefox uses the same 2D Newton's method trick that Loop-Blinn does for antialiasing of elliptical border radii in WebRender—I implemented it a few years back.) :)
- johndough 4y agoSigned distance fields only work well for relatively simple graphics. If you have highly detailed characters like Chinese or emojis, you need larger resolution to faithfully represent every detail. The problem is that SDFs are sampled uniformly over the pixel grid. If the character is locally complex, a high resolution is required to display it, but if the character has simple flat regions, memory is wasted. One way to get around excessive memory requirements is to store the characters in their default vector forms and only render the subset of required characters on demand, but then you might as well render them at the required pixel resolution and do away with the additional complexity of SDF rendering. SDFs are still useful though if you have to render graphics at many different resolutions, for example on signs in computer games, as seen in the original Valve paper https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007...
- tayistay 4y agoI did vector graphics using SDFs in this library (https://github.com/audulus/vger https://github.com/audulus/vger). Works pretty well for my uses which are rendering dynamic UIs, not rendering SVGs. But I can still do some pretty gnarly path fills!