Task 4 of 6
Lighting needs surface normals, and a mesh would hand them to you per-vertex. We have no mesh — but we have something better. The normal of an implicit surface is the gradient of its distance field: the direction in which distance grows fastest is exactly "straight off the surface".
Estimate it with central differences: nudge the hit point by a tiny
e along each axis, sample the field on both sides, subtract. Six extra field
evaluations, then normalize. The classic way to sanity-check normals is to paint them:
n * 0.5 + 0.5 maps each component into color range — a head-on surface
(normal (0, 0, -1), pointing at the camera) renders as
rgb(0.5, 0.5, 0), that mustard-olive tone every graphics programmer knows.
sceneDist and paint each component as n * 0.5 + 0.5 —
hint 2 has the exact this.color call.tHit at the first hite = 0.01 along x, y and z around the hit pointMath.sqrtn * 0.5 + 0.5; misses keep the background colorThe x component before normalizing is
sceneDist(wx + e, wy, pz, …) - sceneDist(wx - e, wy, pz, …)
where pz = -2.5 + tHit. Same pattern for y and z.
const len = Math.sqrt(nx * nx + ny * ny + nz * nz);
this.color(nx / len * 0.5 + 0.5,
ny / len * 0.5 + 0.5,
nz / len * 0.5 + 0.5, 1);This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.