Modern terminals can show far more than the green-and-black Matrix-style terminals of old. Many support a 24-bit colour space, allow interactivity, and can render characters from a vast array of scripts. With these capabilities, writing and using a purely terminal-based application can actually be enjoyable (rather than like pulling teeth).

The colour space support is particularly exciting, as it allows us to render arbitrary graphics, treating characters as pseudo-pixels. In fact, by carefully choosing which character we use in each spot, we can add more detail than a traditional pixel.

A previous project of mine rendered 3D toruses with nice lighting and shadows, drawn into a traditional pixel-filled window. How can we draw to the terminal instead?

I use Notty, an easy-to-use OCaml library that includes almost all of the infrastructure needed to draw characters to arbitrary points on the terminal. If you want to check out how it works, see the Terminal module in lib/frontend.ml in the GitHub repository.

Some example recordings are shown below, using the amazing Asciinema tool for recording terminal sessions.

Quirks

  • As terminal characters are approximately twice as tall as they are wide, the formula for projecting the rays out from the camera needs to be scaled in the \(y\) direction appropriately, otherwise you will get quite a stretched image.

  • Make sure that your terminal supports 24-bit colour! For whatever reason the MacOS Terminal doesn’t support it, so I had to replace it with iTerm2.

  • GitHub repository (link).