Lichtso
13 hours ago
> The next step is to work with chains of Bézier curves to make up complex shapes (such as font glyphs). It will lead us to build a signed distance field. This is not trivial at all and mandates one or several dedicated articles. We will hopefully study these subjects in the not-so-distant future.
If you only want to fill a path of bezier curves (e.g. for text rendering) you can do without the "distance" part from "signed distance field" [0], leaving you with a "signed field" aka. an implicit curve [1].
Meaning not having to calculate the exact distance but only the sign (inside or outside) can be done without all the crazy iterative root finding in an actually cheap manner with only four multiplications and one addition per pixel / fragment / sample for a rational cubic curve [3].
[0]: https://en.wikipedia.org/wiki/Signed_distance_function
[1]: https://en.wikipedia.org/wiki/Implicit_curve
[2]: https://github.com/Lichtso/contrast_renderer/blob/a189d64a13...
ux
12 hours ago
Finding the sign of the distance has been extremely challenging to me in many ways, so I'm very curious about the approach you're presenting. The snippet you shared has a "a³-bcd ≤ 0" formula which is all I get without more context. Can you elaborate on it or provide resources?
The winding number logic is usually super involved, especially when multiple sub-shapes start overlap and subtracting each other. Is this covered or orthogonal to what you are talking about?
Lichtso
10 hours ago
> "a³-bcd ≤ 0" formula
These are the coefficients of the implicit curve, finding them can be done once upfront.
For integral quadratic bezier curves that is trivial as they are constant, see: https://www.shadertoy.com/view/fsXcDj
For rational cubic bezier curves it is more involved, see: https://www.shadertoy.com/view/ttVfzh
And for the full complexity of dealing with self intersecting loops and cusps see: https://github.com/Lichtso/contrast_renderer/blob/main/src/f...
> The winding number logic is usually super involved, especially when multiple sub-shapes start overlap and subtracting each other. Is this covered or orthogonal to what you are talking about?
Orthogonal: The implicit curve only tells you if you are inside or outside (the sign of the SDF), so that is technically sufficient, but usually you want more things: Some kind of anti-aliasing, composite shapes of more than one bezier curve and boolean operators for masking / clipping. Using the stencil buffer for counting the winding number allows to do all of that very easily without tessellation or decomposition at path intersections.
> Can you elaborate on it or provide resources?
If you are interested in the theory behind implicit curve rendering and how to handle the edge cases of cubic bezier curves checkout these papers:
Loop, Charles, and Jim Blinn. "Resolution independent curve rendering using programmable graphics hardware." https://www.microsoft.com/en-us/research/wp-content/uploads/...
BARROWCLOUGH, Oliver JD. "A basis for the implicit representation of planar rational cubic Bézier curves." https://arxiv.org/abs/1605.08669
ux
9 hours ago
Thanks, I'll look into this. BTW, your 2nd shadertoy link is off (maybe it's private? Edit: seems you fixed it, thanks)
vlovich123
8 hours ago
But real shadows and lighting would require the distance aspect, no? The distance is only irrelevant for plain 2D text rendering, right?
Lichtso
8 hours ago
> The distance is only irrelevant for plain 2D text rendering, right?
Yes, as I said it is relevant for text rendering, but not necessarily 2D. It can also be embedded in a 3D perspective as long as the text itself is planar. Meaning you can directly render text in a 3D scene this way without rendering to a texture first.
> But real shadows and lighting would require the distance aspect, no?
I think the difference is in stroke vs fill, not the illumination (as you could still use shadow mapping / projection). In stroking you need to calculate an offset curve either explicitly or implicitly sample it from a signed distance field. Thus the exact distance matters for stroking, for filling it does not.
vlovich123
8 hours ago
Couldn’t you do stroking by doing a second fill operation on a slightly scaled down version of the first with the negative space color as the interior?
Lichtso
8 hours ago
Yep, stroking is just filling of the space between offset curves (aka. parallel curves), and that "slightly scaled down version of the first" is the "calculate an offset curve explicitly" approach I mentioned.
Though it is very unpractical because the offset curve of a cubic bezier curve is not a cubic bezier curve anymore, instead it is an analytic curve of degree 10. Thus, in practice the offset curves for stroking are either approximated by polygons or implicitly sampled from signed distance fields.
Raph Levien has a good blog post about it:
https://raphlinus.github.io/curves/2022/09/09/parallel-bezie...
One more thing: Offset curves are different form classical scaling from a center point in all but the most trivial cases where there exists such a center; namely regular polygons. And cubic bezier curves can be concave, even have a self intersecting loop or form a cusp.
cubefox
7 hours ago
I wonder which method Apple is using for their recently introduced Bézier curve primitives for real-time 3D rendering in Metal. From their WWDC 2023 presentation [1]:
> Geometry such as hair, fur, and vegetation can have thousands or even millions of primitives. These are typically modeled as fine, smooth curves. Instead of using triangles to approximate these curves, you can use Metal's new curve primitives. These curves will remain smooth even as the camera zooms in. And compared to triangles, curves have a more compact memory footprint and allow faster acceleration structure builds.
> A full curve is made of a series of connected curve segments. Every segment on a curve is its own primitive, and Metal assigns each segment a unique primitive ID. Each of these segments is defined by a series of control points, which control the shape of the curve. These control points are interpolated using a set of basis functions. Depending on the basis function, each curve segment can have 2, 3, or 4 control points. Metal offers four different curve basis functions: Bezier, Catmull-Rom, B-Spline, and Linear. (...)
1: https://developer.apple.com/videos/play/wwdc2023/10128/?time...