home/ modules/ raymarching-first-sdf-scene

Raymarching a first SDF scene

  • learner can define signed distance functions and combine primitives with min-based scene composition and boolean operations
  • learner can march a ray through an SDF field using sphere tracing to find surface hits
  • learner can composite 2D reference SDF primitives — positioned with an offset and given visible thickness — as a screen-space overlay on the raymarched image

Raymarch a small 3D SDF scene that unions and subtracts several primitives and displays the surface hits, then composite a 2D SDF overlay on top of the image in screen space: a thickness-offset segment and an offset-positioned reference-library shape, thresholded with step/smoothstep.

This module is where your visuals stop being flat gradients and become geometry. In a live set, raymarched SDF scenes are the workhorse of projector visuals: an entire evolving 3D world lives in one fragment shader, hot-reloaded on save, with no meshes, no asset pipeline — just distance formulas you can mutate mid-performance. The whole task is a first working raymarcher: several primitives unioned and carved into a small 3D scene whose surface hits show up on screen, finished with a flat 2D SDF overlay composited over the image.

Start supported. First get one shape on canvas by understanding what a signed distance function actually returns — positive outside, negative inside, zero at the boundary — and model the camera ray as a parametric function so “where does this ray hit?” becomes “solve for t”. Then wire the sphere-tracing loop: step along the ray by exactly the SDF’s value, terminate on a hit threshold or a far miss. From there the scene grows by repetition of two micro-moves you should drill to automaticity inside the build: inserting a min() to union in a new object, and max(distance, -cutter) to subtract one. The final layer is deliberately 2D: the same distance-field math evaluated in screen space and thresholded with step()/smoothstep(), drawn over the raymarched result. Don’t derive these shapes — the segment SDF and the offset-adaptation workflow for reference-library shapes are your just-in-time how-tos, remembering that thin 1D primitives need a thickness offset subtracted to be visible at all.

Every required atom gates the capstone: without composition, subtraction, or the march loop the 3D scene cannot render, and without the segment SDF, the thickness offset, and the library drop-in workflow the 2D overlay cannot appear. The supporting atoms enrich rather than gate — why primitive-based SDFs dominate demoscene and Shadertoy practice, material IDs for per-object shading later, and the checkpoint-stage workflow that keeps a live build recoverable.

Runnable examples

Generated from the context/ instrument corpus by concept (redistributable idioms only). Do not edit — regenerate with gen-module-examples.mjs.

feedback-trail

osc(4).modulate(src(o0), 0.6).out(o0)

hydra-0022 · CC0-1.0

function draw(){ fill(0, 20); rect(0, 0, width, height); circle(mouseX, mouseY, 40) }

p5live-0003 · CC0-1.0

tiling-repeat

osc(10).repeat(3, 3).out()

hydra-0008 · CC0-1.0

tile [4,4] (circle 0 0.3) >> add

punctual-0020 · CC0-1.0

radial-symmetry

osc(10).kaleid(5).out()

hydra-0010 · CC0-1.0

// sandbox
osc(10, 0.05, 1.3).kaleid(8).out()
// sandbox

p5live-0037 · CC0-1.0

scale-pulse

uv *= 1.0 + 0.3 * sin(u_time * 2.0);

glsl-0030 · public-domain

updateAudio(); scale(1 + amp * 0.01)

p5live-0044 · CC0-1.0

sdf-shape

circle [0,0] 0.4 >> add

punctual-0018 · CC0-1.0

float d = length(uv) - r;

glsl-0003 · public-domain

mirror

uv = abs(uv);

glsl-0010 · public-domain

osc(10).kaleid(2).out()

hydra-0011 · CC0-1.0

vector-drawing

beginShape(); for(let p of pts) curveVertex(p.x, p.y); endShape()

p5live-0016 · CC0-1.0

raymarch-sdf

vec3 nrm(vec3 p){vec2 e=vec2(.001,0);return normalize(vec3(map(p+e.xyy)-map(p-e.xyy),map(p+e.yxy)-map(p-e.yxy),map(p+e.yyx)-map(p-e.yyx)));}

glsl-0033 · public-domain

boolean-sdf

float u = min(a, b); float s = max(a, -b);

glsl-0006 · public-domain

typography

let pts = font.textToPoints('P5', 0, 200, 200, {sampleFactor: 0.2})

p5live-0029 · CC0-1.0

Atoms in this module

Required — these gate the capstone

A signed distance function (SDF) returns positive distances outside a shape, negative inside, and zero at its boundary
Concept L2 First instrument G
A ray is modeled as the parametric function P(t) = A + t*b to enable intersection math
Concept L2 First instrument G
Raymarching finds ray–surface intersections by stepping along the ray using the SDF value as the safe step distance
Concept L2 First instrument G
The minimum of multiple SDFs combines them into a single scene that ray marchers can query
Concept L2 First instrument G
SDF union, intersection, and subtraction combine primitive shapes into complex ones
Concept L2 First instrument G
SDF boolean subtraction uses max(distance, -cutter) to carve one shape out of another
Concept L2 First instrument G
The SDF of a line segment is the distance from a point to the nearest point on the clamped segment
Concept L2 First instrument G
Line-segment and curve SDFs need a thickness offset subtracted to become visible
Procedure L2 First instrument G
A reference-list SDF is dropped into a shader by adding an offset parameter subtracted from p
Procedure L2 First instrument G

Supporting — enrichment, not gating

Primitive-based SDFs define scenes as mathematical formulae rather than volumetric grids, giving infinite precision and a tiny memory footprint
Concept L2 First instrument G
Returning a material ID alongside the SDF distance lets the raymarcher know which object was hit for shading
Concept L2 First instrument G
IQ's first SDF-raymarched image, Slisesix (2008), won a 4KB demoscene procedural-graphics competition
Fact L2 First instrument GO
Dividing a shader build into named checkpoint stages lets you resume from a stable state and avoid rabbit holes
Principle L3 Craft G
Reserve raymarched 3D for when depth adds meaning; a flat SDF composition is often stronger
Principle L2 First instrument LGH
SDFs and immediate-mode drawing are two distinct shape paradigms: field-based vs path-based
Concept L2 First instrument LGH
Geometric visuals are built by combining one SDF shape with boolean operations, then imposing symmetry, then composing the frame
Procedure L2 First instrument HG
Fractal visuals have two build routes: domain repetition with raymarching for 3D lattices, or feedback zoom for a cheap 2D self-similar tunnel
Concept L2 First instrument HG