RECREATING THE MATRIX RAIN WITH ANSI ESCAPE SEQUENCES

22 AUGUST 2022

Over the weekend, I came across Domsson’s Fakesteak: a beautifully lean rendition of the Matrix rain in raw C using ANSI escape sequences—zero dependencies, not even ncurses.

To keep things simple, Fakesteak didn’t support Japanese characters and that it used 8-bit color mode. The latter meant that the ghosting effect has to rely on different foreground colors rather than shades of the same color. As a tip of the hat to Domsson’s impressive work, I decided to add Unicode and 24-bit truecolor support to it, aiming to faithfully recreate the original Matrix from the first movie during Neo and Cypher’s conversation:

Adding Unicode support via wchar_t and wprintf() was easy enough. Implementing the ghosting effect with truecolor support, however, turned out harder than expected. To achieve the ghosting effect, I treated phosphor decay as a multiplier, which allowed me to emulate the dim afterglow by gradually transitioning each raindrop’s color towards the background color:

static void mat_shade(matrix *mat, size_t row, size_t col) 
{
    unsigned char *color;
    color = mat->rgb[mat_idx(mat, row, col)].color;
    color[R] = color[R] - (color[R] - COLOR_BG_RED) / 2;
    color[G] = color[G] - (color[G] - COLOR_BG_GRN) / 2;
    color[B] = color[B] - (color[B] - COLOR_BG_BLU) / 2;
}

Looking back at the implementation, there are still a few improvements to be made. Instead of using a dedicated buffer, I should have bit-packed the phosphor decay into the RGB data buffer to save memory. I’m not entirely satisfied with the Unicode support as it’s restricted to contiguous code points. The glitch effect, which I implemented with characters unexpectedly changing, would have been closer to the original if flashed white as well.

Nonetheless, the rain resembles the original with high visual fidelity. It’s highly customizable and gentle on the CPU. On my 14” ThinkPad T490, which has a resolution of 1920x1080 and 4GHz CPU, it uses 2-3% of the CPU with occasional jumps of up to about 8%. Not too bad for a weekend project. The program has been tested with xterm and urxvt terminal emulators on OpenBSD and Arch Linux systems. Someone has managed to get it moving on a Raspberry Pi as well.

Lastly, to compile and run:

$ cc -O3 main.c -o matrix
$ ./matrix

“All I see is blonde, brunette, red head.”

Files: source.tar.gz