From cec40722d56c8395056fbbce77c562552156f6b4 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Fri, 12 Dec 2025 23:16:51 +0800 Subject: Matrix post. --- _projects/matrix-digital-rain.md | 88 ++++++++++++++++++++++---- _site/feed.xml | 2 +- _site/posts.xml | 2 +- _site/projects/matrix-digital-rain/index.html | 89 +++++++++++++++++++++++---- 4 files changed, 156 insertions(+), 25 deletions(-) diff --git a/_projects/matrix-digital-rain.md b/_projects/matrix-digital-rain.md index f9a1a22..1b48d82 100644 --- a/_projects/matrix-digital-rain.md +++ b/_projects/matrix-digital-rain.md @@ -5,25 +5,91 @@ thumbnail: thumb.png layout: post --- -The famous digital rain from The Matrix, implemented in C. +"All I see is blonde, brunette, red head." The iconic digital rain from The +Matrix in C, with zero dependencies - not even ncurses. -This project is a fork of Domsson's beautiful Fakesteak. +rel="noopener noreferrer">Fakesteak. While studying the code, I wondered +what it would take to faithfully recreate the original Matrix from the first +movie without sacrificing the program's minimalism and elegance. + +My version adds: + + - Unicode character support. + - Fully customizable 24-bit RGB (truecolor) colors. + - Glitches in the matrix. + - Ghosting effect of old monochrome CRT displays. + - Closely resembles the Matrix seen in the background during Neo and Cypher's + conversation. + +With no dependencies, compilation is trivial: + +``` +$ cc -O3 main.c -o matrix +$ ./matrix +``` + +## How does it work? + +The program tracks the state of the terminal - characters, background and +foreground colors, shading levels, cursor position - using multiple internal +data buffers. On each frame, it updates these buffers and repaints the screen +using ANSI escape codes: + +``` +static void term_print(const matrix *mat, size_t row, size_t col) +{ + size_t idx; + idx = mat_idx(mat, row, col); + wprintf(L"\x1b[%d;%dH\x1b[38;2;%d;%d;%dm%lc", + row, col, + mat->rgb[idx].color[R], + mat->rgb[idx].color[G], + mat->rgb[idx].color[B], + mat->code[idx]); +} +``` + +The ghosting effect, the signature feature of this implementation, works by +scaling and mixing the RGB channels: + +``` +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; +} +``` + +The ghosting function emulates the screen decay by gradually transitioning each +raindrop's color towards the background color. This approach provides two key +benefits: straightforward color configuration that integrates naturally with +Unix ricing (desktop customization) and high-fidelity recreation of the Matrix +aesthetic. + +## Customization + +While you can adjust almost every aspect, including its speed, glitch +frequency, and rain density, the most useful settings for customization are the +color scheme and character set. -There are three color settings: head, tail, and background. They are configured -by setting the 24-bit RGB channels using `COLOR_*_RED`, `COLOR_*_GRN`, and -`COLOR_*_BLU` definitions. The ghosting effect of old monochrome screens is -achieved by scaling the RGB channels. This results in a rain effect that -closely resembles the original from the first Matrix movie. +There are three color settings: head, tail, and background. You can configure +them by setting the `COLOR_*_RED`, `COLOR_*_GRN`, and `COLOR_*_BLU` definitions +in main.c. -In addition, this implementation supports UTF-32 character sets. The -`UNICODE_MIN` and `UNICODE_MAX` controls the Unicode block used. For -instance, setting them to `0x30A1` and `0x30F6` rains Katakana: +The `UNICODE_MIN` and `UNICODE_MAX` values control the Unicode block used. For +example, setting them to `0x30A1` and `0x30F6` rains Katakana (if a font that +supports Katakana is present on the system): diff --git a/_site/feed.xml b/_site/feed.xml index 444d5a0..8cfe80e 100644 --- a/_site/feed.xml +++ b/_site/feed.xml @@ -1 +1 @@ -Jekyll2025-12-12T19:52:43+08:00/feed.xmlASCIIMX | BlogW. D. Sadeep MadurangeHow I manage Suckless software installations2025-11-30T00:00:00+08:002025-11-30T00:00:00+08:00/blog/suckless-softwareW. D. Sadeep MadurangeNeo4J A* search2025-09-14T00:00:00+08:002025-09-14T00:00:00+08:00/blog/neo4j-a-star-searchW. D. Sadeep MadurangeMOSFETs as electronic switches2025-06-22T00:00:00+08:002025-06-22T00:00:00+08:00/blog/mosfet-switchesW. D. Sadeep MadurangeHow to configure ATmega328P microcontrollers to run at 3.3V and 5V2025-04-10T00:00:00+08:002025-04-10T00:00:00+08:00/blog/arduino-unoW. D. Sadeep MadurangeHow to set up ATSAM3X8E microcontrollers for bare-metal programming in C2024-10-05T00:00:00+08:002024-10-05T00:00:00+08:00/blog/arduino-dueW. D. Sadeep Madurange \ No newline at end of file +Jekyll2025-12-13T14:22:49+08:00/feed.xmlASCIIMX | BlogW. D. Sadeep MadurangeHow I manage Suckless software installations2025-11-30T00:00:00+08:002025-11-30T00:00:00+08:00/blog/suckless-softwareW. D. Sadeep MadurangeNeo4J A* search2025-09-14T00:00:00+08:002025-09-14T00:00:00+08:00/blog/neo4j-a-star-searchW. D. Sadeep MadurangeMOSFETs as electronic switches2025-06-22T00:00:00+08:002025-06-22T00:00:00+08:00/blog/mosfet-switchesW. D. Sadeep MadurangeHow to configure ATmega328P microcontrollers to run at 3.3V and 5V2025-04-10T00:00:00+08:002025-04-10T00:00:00+08:00/blog/arduino-unoW. D. Sadeep MadurangeHow to set up ATSAM3X8E microcontrollers for bare-metal programming in C2024-10-05T00:00:00+08:002024-10-05T00:00:00+08:00/blog/arduino-dueW. D. Sadeep Madurange \ No newline at end of file diff --git a/_site/posts.xml b/_site/posts.xml index f9d56bb..844a600 100644 --- a/_site/posts.xml +++ b/_site/posts.xml @@ -1 +1 @@ -Jekyll2025-12-12T19:52:43+08:00/posts.xmlASCIIMXW. D. Sadeep Madurange \ No newline at end of file +Jekyll2025-12-13T14:22:49+08:00/posts.xmlASCIIMXW. D. Sadeep Madurange \ No newline at end of file diff --git a/_site/projects/matrix-digital-rain/index.html b/_site/projects/matrix-digital-rain/index.html index 666456b..2893c92 100644 --- a/_site/projects/matrix-digital-rain/index.html +++ b/_site/projects/matrix-digital-rain/index.html @@ -44,23 +44,88 @@

THE MATRIX DIGITAL RAIN

12 JANUARY 2024

-

The famous digital rain from The Matrix, implemented in C.

+

“All I see is blonde, brunette, red head.” The iconic digital rain from The +Matrix in C, with zero dependencies - not even ncurses.

-

This project is a fork of Domsson’s beautiful Fakesteak.

- -

There are three color settings: head, tail, and background. They are configured -by setting the 24-bit RGB channels using COLOR_*_RED, COLOR_*_GRN, and -COLOR_*_BLU definitions. The ghosting effect of old monochrome screens is -achieved by scaling the RGB channels. This results in a rain effect that -closely resembles the original from the first Matrix movie.

- -

In addition, this implementation supports UTF-32 character sets. The -UNICODE_MIN and UNICODE_MAX controls the Unicode block used. For -instance, setting them to 0x30A1 and 0x30F6 rains Katakana:

+

Overview

+ +

This is my fork of Domsson’s beautiful Fakesteak. While studying the code, I wondered +what it would take to faithfully recreate the original Matrix from the first +movie without sacrificing the program’s minimalism and elegance.

+ +

My version adds:

+ +
    +
  • Unicode character support.
  • +
  • Fully customizable 24-bit RGB (truecolor) colors.
  • +
  • Glitches in the matrix.
  • +
  • Ghosting effect of old monochrome CRT displays.
  • +
  • Closely resembles the Matrix seen in the background during Neo and Cypher’s +conversation.
  • +
+ +

With no dependencies, compilation is trivial:

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

How does it work?

+ +

The program tracks the state of the terminal - characters, background and +foreground colors, shading levels, cursor position - using multiple internal +data buffers. On each frame, it updates these buffers and repaints the screen +using ANSI escape codes:

+ +
static void term_print(const matrix *mat, size_t row, size_t col)
+{
+    size_t idx;
+    idx = mat_idx(mat, row, col);
+    wprintf(L"\x1b[%d;%dH\x1b[38;2;%d;%d;%dm%lc",
+        row, col,
+        mat->rgb[idx].color[R],
+        mat->rgb[idx].color[G],
+        mat->rgb[idx].color[B],
+        mat->code[idx]);
+}
+
+ +

The ghosting effect, the signature feature of this implementation, works by +scaling and mixing the RGB channels:

+ +
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;
+}
+
+ +

The ghosting function emulates the screen decay by gradually transitioning each +raindrop’s color towards the background color. This approach provides two key +benefits: straightforward color configuration that integrates naturally with +Unix ricing (desktop customization) and high-fidelity recreation of the Matrix +aesthetic.

+ +

Customization

+ +

While you can adjust almost every aspect, including its speed, glitch +frequency, and rain density, the most useful settings for customization are the +color scheme and character set.

+ +

There are three color settings: head, tail, and background. You can configure +them by setting the COLOR_*_RED, COLOR_*_GRN, and COLOR_*_BLU definitions +in main.c.

+ +

The UNICODE_MIN and UNICODE_MAX values control the Unicode block used. For +example, setting them to 0x30A1 and 0x30F6 rains Katakana (if a font that +supports Katakana is present on the system):

-- cgit v1.2.3