Task 3 of 6

March Until You Hit Something

Now the third dimension. Every pixel fires a ray straight into the screen (orthographic: origin (wx, wy, -2.5), direction (0, 0, 1)), and the SDF turns finding the surface into a beautiful trick called sphere tracing: the distance at your current point is a guaranteed-safe step size — nothing can be closer than that. So step exactly that far, re-evaluate, repeat.

Near a surface the distance shrinks toward zero, so the march converges right onto the skin. When d drops below a small epsilon, that ray has hit. Rays that miss just keep flying — after a fixed number of steps you paint them background. GPUs need that fixed bound: every thread runs the same loop, so give it 48 iterations and let hits simply stop making progress.

the field value is a promise — hop exactly that far and you'll never overshoot
Goal: write the ray-marching loop — 48 steps of t += d — and paint hit pixels pink, misses dark blue.

Requirements

Hint 1 — the loop shape

Two state variables before the loop: let t = 0.0; and let hit = 0.0;. Inside: evaluate sceneDist, set hit = 1.0 when close enough, then advance t. After the loop, color by hit.

Hint 2 — the loop, spelled out
for (let i = 0; i < 48; i++) {
  const d = sceneDist(wx, wy, -2.5 + t, sep, r, k);
  if (d < 0.01) hit = 1.0;
  t += d;
}

Same idea elsewhere

The fixed bound is a gpu.js/WebGL constraint — shader loop bounds must be static, so we guard instead of break. Real marchers on CUDA, WGSL or Shadertoy do break on a hit, and it pays off whenever a whole warp hits or misses together. The durable lesson is about divergence: warps execute in lockstep, so a warp runs as long as its slowest thread.

All tasks in Ray-Marched Metaballs

  1. The Sphere as a Number
  2. Two Spheres Melt Into One
  3. March Until You Hit Something
  4. Normals Without Geometry
  5. Turn On the Light
  6. Soft Shadows, Full Scene

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.