Skip to main content

Ray Marching

Raymarching Web Demo

Overview

Ray marching is an often overlooked rendering technique. Similarly to ray tracing, the idea is that for every pixel on the screen, we want to find the 3D point in world space corresponding to that pixel. The difference is that instead of representing the scene as 3D geometry (triangles) and computing intersections algebraically, we describe the scene as a signed distance field, a function that, given any point in 3D space, returns the distance to the closest surface. If the point is inside the surface, the distance is negative.

This representation allows us to "march" in the ray direction for up to the signed distance, until this distance converges to zero, meaning it hit the surface.

Raymarching Visualization A visualization of ray marching steps generated using p5js. The blue point represents the camera location, and each green point is one ray marching step.

We can keep track of the closest object at every point to get the color, and numerically approximate the normal from the distance function at three offset points to achieve basic shading.

Basic ray-marched render

Ray Marching on a Graphing Calculator

Due to the relative simplicity of the algorithm, I spent a couple hours in Math class back in high school to implement it on my NumWorks graphical calculator, which exposed a Python interface for drawing to the screen. Besides being a particularly efficient way to make time go by faster in class, it also slightly impressed my teacher at the time and kickstarted my long lasting interest in graphics programming.

Raymarching on a NumWorks calculator

Because of how slow the Python API was, it could take a minute to render a single frame. I later upgraded the script to a C++ modification of the calculator's operating system Epsilon, which is available here, though I assume it no longer works with the latest version of the operating system.

Advanced Effects

The beauty of this technique is that it allows us rather easily achieve certain advanced effects that are usually expensive to implement using other methods. For example, we can use the surface distance at the intermediary steps to compute soft shadows, or create glowing effects. We can also use modular arithmetic to create infinite repetitions at little to no extra cost, which makes ray marching ideal for rendering 3D fractals.

Another effect that can easily be achieved using ray marching is blending of nearby objects. In our signed distance function, we can use smooth minimum functions instead of the regular minimum, which will have the effect of blending objects together.

Blending and soft shadows achieved with ray marching A ray-marched render showcasing blending and soft shadows

Ray Marching Web App

I created a simple web app to play with ray marching, which you can find here. It uses the Three.js library for rendering, though it's basically only used for camera controls, as rendering is essentially taken over by a custom fragment shader written in GLSL. The user interface is implemented with vanilla HTML + JavaScript.