At the risk of shedding it to bikes, one point that the author makes is that Zig's lack of operator overloading makes him write vector math like this:
if (discriminant > 0.0) {
// I stared at this monster for a while to ensure I got it right
return uv.sub(n.mul(dt)).mul(ni_over_nt).sub(n.mul(math.sqrt(discriminant)));
}
He signs off with:> How do C programmers manage?
The answer is simple: we assign names to intermediate results. Now, I have absolutely no idea what that expression computes, because I suck at graphics programming and math in general. Please pretend that these are proper mathy terms:
if (discriminant > 0.0) {
const banana = uv.sub(n.mul(dt))
const apple = banana.mul(ni_over_nt)
const pear = n.mul(math.sqrt(discriminant)
return apple.sub(pear)
}
I'm convinced that there's a proper mathy/lighting-y word for each component in that expression. Of course this approach totally breaks down if you're copying expressions from papers or articles without understanding why they are correct (which is how I do all my graphics programming). I do find that naming variables is often a great way to force myself to grok what's going on.