Ray Marching Soft Shadows in 2D Sep 23, 2020 • 9 minute read
Disclaimer: the demos on this page use WebGL features that aren’t available on some mobile devices.
A couple of weeks ago I tweeted a video of a toy graphics project (below). It’s not done, but a lot of people liked it which was surprising and fun! A few people asked how it works, so that’s what this post is about.
Under the hood it uses something called a distance field. A distance field is an image like the one below that tells you how far each pixel is from your shape. Light grey pixels are close to the shape and dark grey pixels are far from it.
When the demo starts up, it draws some text on a 2D canvas and generates a distance field of it. It uses a library I wrote that generates distance fields really quickly. If you’re curious how the library works, I wrote about that here.
Our lighting scheme works like this: when processing a particular pixel we consider a ray from it to the light, like so…
If the ray intersects a glyph, the pixel we’re shading must be in shadow because there’s something between it and the light.
The simplest way to check this would be to move along the ray in 1px increments, starting from the pixel we’re shading and ending at the light, repeatedly asking the distance field if we’re distance 0 from a shape. This would work, but it’d be really slow.
We could pick some specific length like 30px and move in increments of that size, but then we risk jumping over glyphs that are smaller than 30px. We might think we’re not in shadow when we should be.
Ray marching’s core idea is this: the distance field tells you how far you are from the closest glyph. You can safely advance along your ray by that distance without skipping over any glyphs.
... continue reading