summaryrefslogtreecommitdiffstats
path: root/_log/matrix-digital-rain.md
diff options
context:
space:
mode:
Diffstat (limited to '_log/matrix-digital-rain.md')
-rw-r--r--_log/matrix-digital-rain.md96
1 files changed, 96 insertions, 0 deletions
diff --git a/_log/matrix-digital-rain.md b/_log/matrix-digital-rain.md
new file mode 100644
index 0000000..d8e2543
--- /dev/null
+++ b/_log/matrix-digital-rain.md
@@ -0,0 +1,96 @@
+---
+title: The Matrix digital rain
+date: 2022-08-22
+layout: post
+project: true
+thumbnail: thumb_sm.png
+---
+
+"All I see is blonde, brunette, red head." The iconic digital rain from The
+Matrix in C, with zero dependencies—not even ncurses.
+
+<video style="max-width:100%;" controls="" poster="poster.png">
+ <source src="matrix.mp4" type="video/mp4">
+</video>
+
+## Overview
+
+This is my fork of Domsson's beautiful <a
+href="https://github.com/domsson/fakesteak" class="external" target="_blank"
+rel="noopener noreferrer">Fakesteak</a>. While going through his code, I
+wondered what it would take to faithfully recreate the original Matrix from the
+first movie without sacrificing its minimalism.
+
+My implementation supports:
+
+ - Unicode characters.
+ - 24-bit RGB colors (truecolor).
+ - 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, such as code points, background
+and foreground colors, and 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 is achieved by carefully scaling the RGB
+channels before mixing them:
+
+```
+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 dim after glow 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 and high-fidelity recreation of the Matrix aesthetic.
+
+## Customization
+
+While you can alter almost every aspect, including speed, glitch frequency, and
+rain density, the most common customizations are the color scheme and character
+set.
+
+There are three color settings: head, tail, and background. You can configure
+them using `COLOR_*_RED`, `COLOR_*_GRN`, and `COLOR_*_BLU` definitions found 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:
+
+<img style="width: 100%;" src="katakana.png" />
+
+Files: [source.tar.gz](source.tar.gz)