public

Ray Marching

read-only

AI authored to showcase ironpad capabilities.

Ray Marching

Ray marching is a rendering technique that traces rays through a scene defined by signed distance functions (SDFs). Unlike traditional ray tracing, which intersects rays with explicit geometry (triangles, spheres), ray marching steps along each ray using the distance to the nearest surface.

The Algorithm

For each pixel:

  1. Cast a ray from the camera through the pixel
  2. Start at the camera position and repeatedly:
    • Evaluate the SDF at the current point → get the distance d to the nearest surface
    • Step forward along the ray by d (we know nothing is closer than d)
    • If d is very small, we've hit a surface, so compute lighting
    • If we've traveled too far, the ray missed everything, so draw sky

Signed Distance Functions

An SDF f(p) returns the shortest distance from point p to a surface:

  • Positive: outside the object
  • Negative: inside the object
  • Zero: exactly on the surface

Simple SDFs: sphere(p, r) = |p| - r, plane(p) = p.y.

The magic is composability: you can combine SDFs with union (min), intersection (max), and smooth blending to create complex scenes from simple primitives.

[1]Basic Scene
1 panel
Saved output from the author's last run. Press Run to execute live in your browser.
(output too large to embed; run the cell to regenerate it)
[2]Soft Shadows
1 panel
Saved output from the author's last run. Press Run to execute live in your browser.
(output too large to embed; run the cell to regenerate it)

How It Works

Signed Distance Functions (SDFs)

Each primitive is a simple function returning the distance to the nearest surface:

PrimitiveSDF
Sphere|p - center| - radius
Planep.y - height
Boxlength(max(abs(p - center) - half_size, 0)) + interior term

CSG Operations

Combine primitives with set operations:

  • Union: min(a, b) merges two objects
  • Smooth union: blends the surfaces with a smoothing factor k
  • Intersection: max(a, b) keeps only the overlap
  • Subtraction: max(a, -b) carves one from another

Extending the Renderer

Try modifying the scene function to:

  • Add a torus: sdf_torus(p, major_r, minor_r) = length(vec2(length(p.xz) - major_r, p.y)) - minor_r
  • Use repetition: sdf(mod(p, period) - period/2) for infinite copies
  • Add ambient occlusion: sample the SDF at increasing distances from the surface along the normal