Hacker Newsnew | past | comments | ask | show | jobs | submit | ux's commentslogin

Thank you for the kind words, and you're on point with "poetry using math".

I started 2-3 months ago or so doing this stuff, so don't be too intimidated to start. Especially with the two articles (Red Alp and this one), it should make it more accessible, hopefully :)


> Thanks for putting this together.

I'm glad it reaches an audience :)

> Only critique is.. if you're sharing to teach, your compact/one line [460] char GLSL code is a poor delivery mechanism.

Understandable. Though, the demos are here to illustrate "what you can do with the trick I'm sharing". It's like, I'm teaching you how to do watercolor, and illustrate it with some paintings you won't be able to perform just with that knowledge. They're meant to inspire you to create. You're not looking at a tutorial, you're looking at art.


That brought out a nice, hearty chuckle. At least you're owning your style.

> What's a good way to get started learning to build/customize shaders with GLSL?

I gave some directions and resources in a comment here, it might help you: https://www.reddit.com/r/GraphicsProgramming/comments/1pgqis...

> And GLSL syntax looks a bit tedious to be honest, but I'd love to dive in.

With the vectorization everywhere, it's surprisingly convenient given how simple the syntax is. I personally just miss some sinpi/cospi/etc, and/or a PI and TAU constant.


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


The trick is that you only solve Newton on a single subcurve: you recursively find the closest control point on all subcurves, split that subcurve and repeat until the closest control point doesn’t move much, or just however many subdivision steps work in practice. So the last curve that you apply Newton to should be smooth enough to succeed. I think there are edge cases with cusps, but I can’t exactly remember the theoretical guarantees anymore.

I think this is the main reference for this algorithm (should be able to search for the pdf): https://www.sciencedirect.com/science/article/abs/pii/S01678...


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.


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.


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.


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?


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


Thanks, I'll look into this. BTW, your 2nd shadertoy link is off (maybe it's private? Edit: seems you fixed it, thanks)


Ah nice for noticing d!=0 is d>0. Not sure how I missed the multiplication to get rid of the vector form; I guess I was too obsessed with the x-x trick...

I added your changes to the Shadertoy version with your HN nickname. I'll integrate it to the original later.

Thanks!


I saw that you used `float z;` to later use `z` instead of the constant `0.`. You can also apply that to get a zero vector: `vec3 y;` and use `y` in place of `p-p`.

It seems that leaving the obsession behind some more can save another byte.


Is this tutorial kind of abandoned? There are many teased chapters that never seem to have materialized somehow.


This is not equivalent; the `a` in `c.r+=w*a` is different, you need the original untouched w. The mountain looses its crack with your version.

But! You can save 1 char by replacing w with a:

    g -= a*=w,
    c += a*d*9.+...
    a = min(...),
    c.r += w*a*a*.2,
So thank you for the idea!


Ah, someone reported this to me today, but I must admit I have no idea how to address the issue. Currently the canvas animations are stopped when out of context, but yeah they have to be loaded.

The code on the blog is pretty simple and naive (I'm not a webdev): https://github.com/ubitux/scripts/blob/main/share/blog/shade...

Any suggestion on how to address the issue is welcome.

Note: I don't have any Windows machine to test with


If you just want it to work, stick this script on your page

https://github.com/greggman/virtual-webgl

If you want to make your own solution there's one listed here about 1/2 way down the page

https://webglfundamentals.org/webgl/lessons/webgl-multiple-v...

As an aside, WebGPU doesn't have this issue or at least has it less. For one, WebGPU can use a single device to render to multiple canvases, something WebGL can't. Another is that WebGPU is mostly stateless making it easier for both the user and the browser.


Incredible, thank you very much. I've included the script for a quick fix, I'll see how to make to cook something myself at some point!


Similar issue on iOS Safari: all examples work except for the very first one.


It loaded fine for me. iOS 26.0, iPhone 16 Pro.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: