Zachary W. Huang

Home Projects Blog Guides Resume

An ASCII Ray Marcher

All of the code can be found in this github repo.

Introduction

I’ve always found computer graphics intriguing, especially the subfields of ASCII art/animation.

One of the first ‘cool’ things about the command line I discovered was that you could type in

telnet towel.blinkenlights.nl

and watch an entire Star Wars movie through ASCII drawings.

star wars asciimation A screenshot from the original website

Another animation that fascinated me was donut.c, which displayed a spinning donut using only ASCII characters (and with donut-shaped C code).

donut.c A gif recorded from the author's website

I had previously forayed into the world of ray tracing, but it never really worked out well. However, I soon discovered Ray Marching, a method of generating graphics which can be easily adapted to 3D ASCII animations. There was no way I wasn’t going to try this out.

Ray Marching

The one key ingredient in ray marching is the Signed Distance Function (SDF). An SDF is a mathematical function that calculates the shortest distance from a vector to some 3D surface. Using an SDF, we can march rays forward by the maximum distance before they potentially hit a surface. This is more efficient than ray tracing, which marches all rays at a small, fixed value. Once the SDF for a ray becomes close to 0, we know we have hit a surface. To calculate shading on that surface, we need to know the surface normal, or the vector pointing perpendicular from a surface. With an SDF, this is easy - the surface normal is simply the gradient of the SDF at its surface. This is because the fastest way to increase an SDF at a surface is to travel perpendicular to it. Then, we can convert the shading information into ascii characters to generate a frame. For more information, you can check out this article.

Now, for the results!

rotating rectangle A rotating rectangular prism rotating sphere A sphere with a revolving light above it.

Some Technical Stuff

Julia made it very easy to work with math expressions and get good performance out of it too. With stack-allocated arrays and multithreading both an import away, the ray marcher could easily render at 60 frames per second.

RSS icon github logo linkedin logo

Zachary W. Huang © 2021-2024