summaryrefslogtreecommitdiffstats
path: root/_site/log/matrix-digital-rain
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2025-12-21 01:10:18 +0800
committerSadeep Madurange <sadeep@asciimx.com>2025-12-21 01:21:00 +0800
commitaad38bc831c8bba90688df2cc28c46a46cac1112 (patch)
tree7ccd19e374254b52502a9cf1d9a0e5f8347a4cf6 /_site/log/matrix-digital-rain
parente15f1076b59e997108914f6a5b9b28652d323268 (diff)
downloadwww-aad38bc831c8bba90688df2cc28c46a46cac1112.tar.gz
Matrix post as a journal entry.
Diffstat (limited to '_site/log/matrix-digital-rain')
-rw-r--r--_site/log/matrix-digital-rain/index.html100
1 files changed, 34 insertions, 66 deletions
diff --git a/_site/log/matrix-digital-rain/index.html b/_site/log/matrix-digital-rain/index.html
index 26244b3..ac4a536 100644
--- a/_site/log/matrix-digital-rain/index.html
+++ b/_site/log/matrix-digital-rain/index.html
@@ -2,12 +2,12 @@
<html>
<head>
<meta charset="utf-8">
- <title>The Matrix digital rain</title>
+ <title>Recreating the Matrix rain with ANSI escape sequences</title>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
- <title>The Matrix digital rain</title>
+ <title>Recreating the Matrix rain with ANSI escape sequences</title>
<link rel="stylesheet" href="/assets/css/main.css">
<link rel="stylesheet" href="/assets/css/skeleton.css">
</head>
@@ -41,61 +41,30 @@
<main>
<div class="container">
<div class="container-2">
- <h2 class="center" id="title">THE MATRIX DIGITAL RAIN</h2>
+ <h2 class="center" id="title">RECREATING THE MATRIX RAIN WITH ANSI ESCAPE SEQUENCES</h2>
<h6 class="center">22 AUGUST 2022</h5>
<br>
- <div class="twocol justify"><p>“All I see is blonde, brunette, red head.” The iconic digital rain from The
-Matrix in C, with zero dependencies—not even ncurses.</p>
+ <div class="twocol justify"><p>Over the weekend, I came across Domsson’s <a href="https://github.com/domsson/fakesteak" class="external" target="_blank" rel="noopener noreferrer">Fakesteak</a>: a beautifully lean rendition of the
+Matrix rain in raw C using ANSI escape sequences—zero dependencies, not even
+ncurses.</p>
+
+<p>The project’s README noted that it 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.</p>
+
+<p>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:</p>
<video style="max-width:100%;" controls="" poster="poster.png">
<source src="matrix.mp4" type="video/mp4" />
</video>
-<h2 id="overview">Overview</h2>
-
-<p>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.</p>
-
-<p>My implementation supports:</p>
-
-<ul>
- <li>Unicode characters.</li>
- <li>24-bit RGB colors (truecolor).</li>
- <li>Glitches in the matrix.</li>
- <li>Ghosting effect of old monochrome CRT displays.</li>
- <li>Closely resembles the Matrix seen in the background during Neo and Cypher’s
-conversation.</li>
-</ul>
-
-<p>With no dependencies, compilation is trivial:</p>
-
-<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cc -O3 main.c -o matrix
-$ ./matrix
-</code></pre></div></div>
-
-<h2 id="how-does-it-work">How does it work?</h2>
-
-<p>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:</p>
-
-<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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-&gt;rgb[idx].color[R],
- mat-&gt;rgb[idx].color[G],
- mat-&gt;rgb[idx].color[B],
- mat-&gt;code[idx]);
-}
-</code></pre></div></div>
-
-<p>The ghosting effect is achieved by carefully scaling the RGB
-channels before mixing them:</p>
+<p>Adding Unicode support via <code class="language-plaintext highlighter-rouge">wchar_t</code> and <code class="language-plaintext highlighter-rouge">wprintf()</code> 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, allowing me to emulate a dim afterglow by gradually
+transitioning each raindrop’s RGB values towards the background color:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>static void mat_shade(matrix *mat, size_t row, size_t col)
{
@@ -107,26 +76,25 @@ channels before mixing them:</p>
}
</code></pre></div></div>
-<p>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.</p>
-
-<h2 id="customization">Customization</h2>
+<p>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, really should flash white as well.</p>
-<p>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.</p>
+<p>Nonetheless, the rain closely resembles the original, is highly customizable,
+and is gentle on the CPU. Not too bad for a weekend project. I tested the
+program 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.</p>
-<p>There are three color settings: head, tail, and background. You can configure
-them using <code class="language-plaintext highlighter-rouge">COLOR_*_RED</code>, <code class="language-plaintext highlighter-rouge">COLOR_*_GRN</code>, and <code class="language-plaintext highlighter-rouge">COLOR_*_BLU</code> definitions found in
-main.c.</p>
+<p>Lastly, to compile and run:</p>
-<p>The <code class="language-plaintext highlighter-rouge">UNICODE_MIN</code> and <code class="language-plaintext highlighter-rouge">UNICODE_MAX</code> values control the Unicode block used. For
-example, setting them to <code class="language-plaintext highlighter-rouge">0x30A1</code> and <code class="language-plaintext highlighter-rouge">0x30F6</code> rains Katakana, if a font that
-supports Katakana is present on the system:</p>
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cc -O3 main.c -o matrix
+$ ./matrix
+</code></pre></div></div>
-<p><img style="width: 100%;" src="katakana.png" /></p>
+<p>“All I see is blonde, brunette, red head.”</p>
<p>Files: <a href="source.tar.gz">source.tar.gz</a></p>
</div>