Introduction

Traditional 3D rendering cuts every surface into triangles and tests each ray against millions of them. It works brilliantly — but geometry that is hard to triangulate, like fractals, smooth organic blends, or infinite repetition, becomes painful or impossible.

Ray marching takes a different approach. Instead of triangles, you define a scene with a signed distance function (SDF): a formula that, given any point pp in space, returns the distance from pp to the nearest surface. Negative inside, positive outside, zero exactly on the surface.

The rendering loop is remarkably simple. Fire a ray from the camera. At the current position, evaluate the SDF. That value tells you: the nearest surface is at least this far away. Take a step of exactly that size — you cannot possibly overshoot the surface. Repeat. Each step is as large as safety allows, so convergence is fast. When the SDF drops below a tiny threshold ε\varepsilon, you have hit the surface.

This technique — called sphere tracing when credited to its 1996 inventor John C. Hart — needs no mesh at all. The scene lives entirely inside a mathematical formula.

Try It

The canvas below shows a 2D cross-section of a ray marching scene. The orange dot is the ray origin; the black arrow shows the ray direction. The colored circles are the SDF "safe spheres" — at each step the ray may advance by the radius of the circle centered on the current position, guaranteed not to overshoot the nearest obstacle.

<!-- {{c_intro}} -->
<div class="toolbar">
  <span class="label">{{lbl_scene}}</span>
  <button id="sceneA" type="button" class="scene-btn active">{{btn_scene_a}}</button>
  <button id="sceneB" type="button" class="scene-btn">{{btn_scene_b}}</button>
  <button id="sceneC" type="button" class="scene-btn">{{btn_scene_c}}</button>
</div>
<canvas id="cv" width="400" height="280" aria-label="{{canvas_aria}}"></canvas>
<div class="status" id="status">{{status_ready}}</div>
<div class="btns">
  <button id="btnStep" type="button">{{btn_step}}</button>
  <button id="btnAll"  type="button">{{btn_all}}</button>
  <button id="btnReset" type="button" class="ghost">{{btn_reset}}</button>
</div>
/* {{c_css_intro}} */
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; color: #222; background: #fff; }
.toolbar { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; margin-bottom: .5rem; }
.label { font-size: .8rem; color: #555; margin-right: .2rem; }
.scene-btn { font-size: .8rem; padding: .25rem .6rem; border: 1px solid #aaa; border-radius: 5px;
             background: #f0f0f0; cursor: pointer; }
.scene-btn.active { background: #1d3557; color: #fff; border-color: #1d3557; }
canvas { display: block; border: 1px solid #ccc; border-radius: 8px; max-width: 100%; }
.status { font-size: .9rem; font-weight: 600; margin: .4rem 0; min-height: 1.3em; color: #333; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .4rem .85rem;
         border: 1px solid #1d3557; background: #1d3557; color: #fff;
         border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
// Code not found

Click Step to advance one iteration at a time and watch the safe-sphere shrink as the ray closes in on the surface. Click March All to see the full convergence at once. Use Reset to restart from the beginning or try a different scene with the buttons on the right.

Notice that each step is as large as possible without risk — this is the key efficiency of sphere tracing versus naive fixed-step ray marching.

The Real Complexity

Ray marching is elegant, but its performance depends on the quality of the SDF.

  • Convergence rate. If the SDF is a true distance (Lipschitz constant 1\leq 1), each step reduces the remaining gap by a guaranteed fraction. For a smooth scene the ray typically converges in 20–100 steps, regardless of scene complexity — a striking contrast to the O(n)O(n) triangle intersection cost.
  • The Lipschitz trap. If you combine SDFs carelessly — say, by multiplying them or using non-normalized domain warping — the function can shrink faster than the true distance. The marcher takes baby steps and may never converge within the step budget.
  • Over-relaxation. A trick popularized by Inigo Quilez allows steps larger than the strict SDF value when the field is known to be well-behaved, cutting step counts nearly in half for typical scenes.
  • Soft shadows and ambient occlusion come nearly for free: sample the SDF a few times along the shadow ray and the ratio of the minimum value to the step distance gives a soft penumbra factor, something triangle renderers must approximate with expensive shadow maps.
  • Fractals like the Mandelbulb or the Menger sponge have SDFs that are approximated iteratively. The convergence is slower, but a mesh of equivalent fidelity would require billions of triangles.

The fundamental limit: ray marching cannot do better than O(log(1/ε))O(\log(1/\varepsilon)) steps near a flat surface — that is the geometric series formed by the successive half-distances as the ray closes in.

Where It Matters

The combination of mathematical elegance and GPU-friendliness has made ray marching ubiquitous in modern graphics:

  • Real-time shader art: platforms like Shadertoy host thousands of scenes — entire planets, infinite caves, fractal universes — written as a single fragment shader with no mesh data whatsoever.
  • Film and TV volumetrics: fog, clouds, and smoke are naturally described by a density SDF. Ray marching through the volume accumulates opacity and color without needing to simulate individual particles.
  • Procedural terrain: infinite landscapes defined by noise functions are cheaper to render with ray marching than to tessellate into meshes.
  • Medical imaging: CT and MRI data provide a 3D scalar field. Ray marching through it as an implicit surface is a standard visualization technique.
  • CSG (Constructive Solid Geometry): boolean operations on shapes (union, intersection, subtraction) are just min\min, max\max, and negation on their SDFs — trivial in ray marching, painful in mesh-based workflows.

Ray marching also connects to compression ideas: a complex shape is "compressed" into a short mathematical formula that the renderer expands on demand per pixel. And the step-until-convergence logic echoes the iterative methods studied in non-convex optimization.

Conclusion

Ray marching distills a scene into its mathematical essence: instead of a catalog of triangles, you carry a single function that answers "how far am I from anything?" at any point in space. The marcher uses that answer greedily — step as far as safety allows, ask again, repeat — and arrives at the surface in a handful of iterations.

The payoff is extraordinary. Fractals with infinite detail, smooth organic blends, fog, fire, and infinite procedural worlds all fall within reach of a few lines of math. What you lose in raw triangle throughput you gain tenfold in geometric expressiveness.

If you have ever admired a Shadertoy scene running entirely on a GPU with zero mesh data, you were watching sphere tracing at work — one of the most beautiful algorithms in computer graphics, hiding in plain sight inside a distance function.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/ray-marching/Content licensed under CC BY-NC 4.0.