🎨 Ray Marching — SDF Scene Rendering

CPU ray marching · SDF primitives · Smooth-min blending · Phong shading · Soft shadows · AO

Preset

Scene

Lighting

Soft shadows
Ambient occlusion

Stats

Render time
Avg ray steps
Buffer160×120 → 640×480

Drag canvas to orbit camera. Rendering runs on CPU in a 160×120 offscreen buffer.

🎨 Ray Marching & Signed Distance Functions

Ray marching is a rendering technique where camera rays advance step by step through a scene described entirely by mathematical distance functions — no polygons, no meshes. Each step size equals the minimum distance to any surface, guaranteeing safety. When that distance drops below a threshold the ray has hit a surface. This implementation runs entirely on the CPU, writing pixels into a 160×120 ImageData buffer that is scaled 4× to 640×480 — making real-time CPU ray marching feasible at 15–20 FPS.

Physics & Math

Ray march: advance t += SDF(origin + t⋅dir) until SDF < 0.001. Sphere SDF = |p| − r. Box SDF uses the sdBox formula. Torus: |vec2(length(p.xz) − R, p.y)| − r. smin(a,b,k) produces the smooth union. Normals are estimated via finite differences of the SDF gradient. Phong shading: ambient + diffuse⋅max(0, n⋅L) + specular⋅(R⋅V)^n. Soft shadows march toward the light accumulating a penumbra factor from SDF clearance.

How to Use

Drag the canvas to orbit the camera. Choose a preset to load a different scene composition. Adjust FOV (30–90°), sphere radius, smooth-min blend factor k, and light direction X. Toggle soft shadows and ambient occlusion on or off. Enable Normals view to visualise the normal map directly. Stats show per-frame CPU render time and average ray steps per pixel.

Did You Know?

Smooth-min (smin) was popularised by Inigo Quilez as a way to blend SDF primitives into organic, continuous shapes — the boundary between two objects dissolves into a soft fillet. By tuning the blend factor k you control how wide the merge zone is: k=0 is a hard union, large k creates a broad mushroom-cap blend. The same primitive combination used here — sphere, box and torus — appears in nearly every introductory ray marching tutorial because it covers the full range of basic SDF maths.

About Ray Marching with Signed Distance Functions

This simulation renders a 3D scene entirely on the CPU using ray marching, also called sphere tracing. Instead of meshes, the scene is defined by signed distance functions (SDFs) that return the distance from any point to the nearest surface. Each camera ray advances by exactly that distance — advancing t += sceneSDF(origin + t·dir) — until the value drops below 0.001, marking a hit. Pixels are computed in a 160×120 buffer and upscaled 4× to 640×480.

The controls let you pick four scene presets (sphere, blended sphere-box, torus, and a fully blended trio), set FOV from 30° to 90°, sphere radius, the smooth-min blend factor k, and the light direction X. Toggles enable soft shadows and ambient occlusion, while a Normals view shows the surface normals as colour. These same SDF techniques power demoscene shaders, procedural fractals, and volumetric effects in real games.

Frequently Asked Questions

What is ray marching?

Ray marching is a rendering method that steps a camera ray forward through a scene described by distance functions rather than polygons. At each step the ray jumps by the shortest distance to any surface, so it never overshoots. When that distance falls below a small threshold, the ray is considered to have hit a surface.

What is a signed distance function?

A signed distance function returns the distance from a point to the nearest surface of a shape, with a positive sign outside the shape and a negative sign inside. For example, a sphere of radius r centred at the origin is simply the length of the point vector minus r. The whole scene here is built from such SDFs combined together.

Why is it also called sphere tracing?

Each step advances the ray by the distance to the nearest surface, which defines an empty sphere of that radius around the current point. The ray can safely jump to the edge of that sphere without passing through any geometry. Repeatedly tracing these safe spheres gives the technique its alternative name, sphere tracing.

What does the smooth-min (k) slider do?

The blend factor k controls the smooth union (smin) that merges two SDF primitives into one continuous shape. With k near zero the join is a hard intersection edge; larger k widens the soft fillet where the shapes melt together. In this demo it blends the sphere with the box and torus to create organic, droplet-like forms.

How are the surface normals calculated?

Normals are estimated using finite differences of the SDF, sampling the field at small offsets (EPS = 0.001) along each axis and taking the gradient. The normalised gradient points away from the surface and is used for shading. The Normals view maps this vector directly to red, green and blue so you can inspect surface orientation.

How do the soft shadows work?

A secondary ray is marched from the surface toward the light. As it advances it tracks the smallest ratio of SDF clearance to distance travelled, which estimates how close the ray passes to occluders. This produces a penumbra factor, giving soft, gradually fading shadow edges instead of hard binary shadows.

What is ambient occlusion here?

Ambient occlusion darkens crevices and contact areas where surrounding geometry blocks indirect light. This implementation samples the SDF at five short steps along the normal and compares expected versus actual clearance. Where nearby surfaces crowd the point, occlusion increases, adding subtle depth and grounding objects against the floor.

What shading model does it use?

The renderer uses Phong-style shading: an ambient term, a diffuse term proportional to the dot product of the normal and light direction, and a specular highlight raised to a power for glossiness. The result is tone-mapped with a Reinhard curve and gamma-corrected (power 0.4545) before being written to the pixel buffer.

Why does it render at such a low resolution?

Ray marching is computationally heavy because every pixel may evaluate the scene SDF dozens of times, up to 64 steps each. Running this on the CPU in JavaScript would be far too slow at full resolution, so the image is computed in a 160×120 buffer and scaled up 4×. The Stats panel reports render time and average ray steps per pixel.

Is this rendering physically accurate?

It is physically inspired rather than physically exact. The geometry and normals are mathematically correct from the SDFs, but the lighting uses empirical Phong shading and approximate soft shadows and ambient occlusion rather than full path tracing. The result captures realistic-looking depth and shading while remaining fast enough to run live on the CPU.

Where is ray marching used in practice?

Ray marching with SDFs is widely used in demoscene shaders, Shadertoy experiments, and procedural fractals such as the Mandelbulb. It also appears in real games for volumetric clouds, fog and soft fields, and in tools that need to render implicit surfaces without first converting them to polygon meshes.