Last modified: 2025-04-12 12:52:13
< 2025-04-10Better intersections performance
So I think the current status is the "better intersections idea" is:
And then the distance to surface is min of [max of initial distances] and the distance that the settled point is from the start point.
And it only works for convex shapes that have non-zero intersection.
And I can only do 1 iteration because my derivatives have awful performance for some reason. So next step is working out why. I'm going to dump the generated code for a box, and then the (simple) intersection of two boxes, and then one iteration of following gradients, and see what seems to be growing.
Box is:
add(vlength(vmax(vsub(vabs(p), vdiv(u_Box_1_size, 2)), Vec3(0, 0, 0))), min(max(vecX(vsub(vabs(p), vdiv(u_Box_1_size, 2))), max(vecY(vsub(vabs(p), vdiv(u_Box_1_size, 2))), vecZ(vsub(vabs(p), vdiv(u_Box_1_size, 2))))), 0))
Derivative of Box is absolutely enormous (6869 bytes, when dumped in the same format).
Why is it so big?
One thing I've noticed is the derivative of vmin
has:
P.mix(bDerivative[0].vecX, aDerivative[0].vecX, P.step(P.vecX(b), P.vecX(a)))
But foo.vecX
is not how you do it! Why does this work? I think it doesn't, I think there's
no test for vmin
. I'll add one now. It also had the arguments to step
the wrong way
around.
So the derivative of Box should be the derivative of add
where the arguments are a
vlength(...)
and min(...)
. Derivative of a+b
is equal to derivative of a
plus
derivative of b
.
OK, here's why it is getting so big. When you take the derivative of a function you get an expression somewhere between maybe 3x and 6x as large as what you started with.
Looking at the amount of generated JS code:
So maybe our derivative gains about 6 lines of code for every line of code we add to the base object? If it is linear.
So if the "BetterIntersection" is 724 lines longer than the simple intersection, then the derivative should be 4344 lines longer than the simple intersection derivative derivative, or about 4600 lines.
So yeah that is pretty long.
How do I figure out why it is running out of memory?
Firefox seems to have some thing where if a page hangs and then you close the tab and open the same page in a new tab it doesn't load? I don't really understand why.
Oh! I see the problem. The problem is that we're calling derivative()
before simplify()
. Which means it has to calculate and recalculate the
same expressions over and over again. I could make Peptide cache the results?
With that solved, I get the derivative of the "Better Intersection" almost instantly! It is 2635 lines of JavaScript, or about 10x larger than the derivative of the simple intersection.
Should Peptide do "expression interning" more generally? So we'd basically do
simplify()
automatically as the expression is being built, instead of in one
big pass at the end.
Adding more and more iterations of gradient following, I got a new error from the shader compiler:
Internal error: assembly compile error for fragment shader at offset 1972813:
-- error message --
line 65583, column 1: error: too many instructions
And I still haven't got an intersection SDF that is "correct" even for convex overlapping shapes. Maybe the idea just doesn't work.
But I have made derivative calculation more efficient and fixed vmin
, so
there's that.