Live data from Hacker News

Fast calculation of the distance to cubic Bezier curves on the GPU

blog.pkh.me

21–30 of 37 posts

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#21
post #20

Earlier quoted context omitted.

But real shadows and lighting would require the distance aspect, no? The distance is only irrelevant for plain 2D text rendering, right?

> 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…

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?

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#22
post #20

Earlier quoted context omitted.

> 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…

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?

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.

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#23
post #16

This is fundamentally a geometric problem and the author completely missed the geometry aspect by transforming everything into polynomials and root finding. The naive generic way of finding distances from point P to curve C([0,1]) is a procedure quite standard for global minimization : repeat "find a local minimum on the space constrained to be better than any previous minimum" - Find a point P0 local minimum of d(P,…

I'm interested in the approach you're describing but it's hard to follow a comment in the margin. Is there a paper or an implementation example somewhere?

The general technique is not recent I was taught it in school in global optimisation class more than 15 years ago.

Here there is a small number of local minimum, the idea is to iterate over them in increasing order.

Can't remember the exact name but here is a more recent paper proposing "Sequential Gradient Descent" https://arxiv.org/abs/2011.04866 which features a similar idea.

Sequential convex programming : http://web.stanford.edu/class/ee364b/lectures/seq_notes.pdf

There is not really something special to it, it just standard local non linear minimization techniques with constraints Sequential Least Squares Quadratic Programming (SLSQP).

It's just about framing it as an optimization problem looking for "Points" with constraints and applying standard optimization toolbox, and recognizing which type of problem your specific problem is. You can write it as basic gradient descent if you don't care about performance.

The problem of finding a minimum of a quadratic function inside a disk is commonly known as the "Trust Region SubProblem" https://cran.r-project.org/web/packages/trust/vignettes/trus... but in this specific case of distances to curve we are on the easy case of Positive Definite.

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#24
post #16

Earlier quoted context omitted.

I'm interested in the approach you're describing but it's hard to follow a comment in the margin. Is there a paper or an implementation example somewhere?

The general technique is not recent I was taught it in school in global optimisation class more than 15 years ago. Here there is a small number of local minimum, the idea is to iterate over them in increasing order. Can't remember the exact name but here is a more recent paper proposing "Sequential Gradient Descent" https://arxiv.org/abs/2011.04866 which features a similar idea. Sequential convex programming : http:/…

What you described in your first message seemed similar to the approach used in the degree N root solving algorithm by Cem Yuksel; splitting the curve in simpler segments, then bisect into them. I'd be happy to explore what you suggested, but I'm not mathematically literate, so I'll be honest with you; what you're saying here is complete gibberish to me, and it's very hard to follow your point. It will take me weeks to figure out your suggestion and make a call as to whether it's actually simpler or more performant than what is proposed in the article.

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#25
post #5

> 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 "s…

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...

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#27
post #24

Earlier quoted context omitted.

The general technique is not recent I was taught it in school in global optimisation class more than 15 years ago. Here there is a small number of local minimum, the idea is to iterate over them in increasing order. Can't remember the exact name but here is a more recent paper proposing "Sequential Gradient Descent" https://arxiv.org/abs/2011.04866 which features a similar idea. Sequential convex programming : http:/…

What you described in your first message seemed similar to the approach used in the degree N root solving algorithm by Cem Yuksel; splitting the curve in simpler segments, then bisect into them. I'd be happy to explore what you suggested, but I'm not mathematically literate, so I'll be honest with you; what you're saying here is complete gibberish to me, and it's very hard to follow your point. It will take me weeks…

I have written some gist to illustrate the approach I suggest. The code run but there may be bugs, and it don't use the appropriate optimizer. The purpose is to illustrate the optimisation approach.

https://gist.github.com/unrealwill/1ad0e50e8505fd191b617903b...

Point 33 "intersection between bezier curve with a circle" may be useful to find the feasible regions of the subproblems https://pomax.github.io/bezierinfo/#introduction

The approach I suggest will need more work, and there are probably problematic edge cases to consider and numerical stability issues. Proper proofs have not been done. It's typically some high work-low reward situation.

It's mostly interesting because it highlight the link between roots and local mimimum. And because it respect the structure of the problem more.

To find roots we can find a first root then divide the polynomial by (x-root). And find a root again.

If you are not mathematically literate, it'll probably be hard to do the details necessary to make it performant. But if you use a standard black-box optimizer with constraints it should be able to do it in few iterations.

You can simplify the problem by considering piece-wise segments instead of splines. The extension to chains of segment is roughly the same, and the spatial acceleration structure based on branch-and-bound are easier.

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#28
Hey, thanks for the nice post. I really enjoyed reading it; it’s good see this kind of thing on the front page.

Since you’re interested in doing this on GPU, an approach that might be interesting to you (although not necessarily more efficient) would be to leverage the intrinsic properties of Bezier curves to feed a near-optimal initial guess to Newton. Some useful facts about Bezier curves: i) Bezier control points form a convex hull of the curve they define ii) Bezier curves defined on [0,1] can be split into two bezier curves, each defined on [0,t] and [t,1] that define the same curve, with a tighter control polygon. iii) This Bezier curve splitting can be done using repeated linear combinations of Bezier control points, so you can skip evaluating Bernstein polynomials directly. iv) there is a mapping from Bezier control points to their corresponding value in the [0,1] parameter space (the term for this for B-Splines is greville abcissae, I’m not sure that there is an explicit name for the equivalent for Bezier curves, but basically the preimage of control point b_i of a degree d curve is i/d, i=0,…,d+1).

These things together sort of imply an algorithm: 1. Subdivide the Bezier curve c into 2 or 3 curves c_1, c_2, c_3 2. Find the closest control point b_j to the target point x 3. Choose the curve c_i corresponding to b_j: this subcurve contains the closest point to x 4. Go to step 1 and repeat this loop several times with c = c_i 5. Then, compute the preimage of the closest control point b_j to x on c (j/d plus some shift and rescaling). This value, t’, will be the initial guess to Newton’s method. 6. Solve for the closest point on the selected subcurve c to x with Newton’s method; this should converge in very few steps because your initial guess is so good, quadratic convergence, blah, blah blah.

The break-even point for this kind of algorithm vs. a derivative based algorithm is very unclear on CPU. But, for GPU, I think the computation can be structured in an architecture friendly way; since computing the euclidean distance between x with all control points and the bezier curve splitting can written in a vectorizable manner, you will probably see a decent speed up. I’ve only really worked with CUDA though, so I’m not sure if this idea maps very cleanly to GLSL.

Here’s an example of the algorithm above for CPU if you are interested: https://github.com/qnzhou/nanospline/commit/5ac97722414dbc75...

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#29

Hey, thanks for the nice post. I really enjoyed reading it; it’s good see this kind of thing on the front page. Since you’re interested in doing this on GPU, an approach that might be interesting to you (although not necessarily more efficient) would be to leverage the intrinsic properties of Bezier curves to feed a near-optimal initial guess to Newton. Some useful facts about Bezier curves: i) Bezier control points…

Thank you! Do we have a guarantee that these subcurves are solvable with Newton's method? The approach with derivatives has this because we know there is one crossing, and also clipping them to the zero-derivatives makes sure there won't be multiple curve "pits".

Re: Fast calculation of the distance to cubic Bezier curves on the GPU

#30
This is quite a complicated approach that misses out on most of the basic numerical and geometric methods that will make the problem simpler. I would recommend looking outside of recent SIGGRAPH papers. Brushing up on the basics of Bernstein polynomials, B-splines, and rootfinding methods will lead you to develop simpler algorithms which are likely faster.
Post reply on HN