summaryrefslogtreecommitdiffstats
path: root/_log/_site/matrix-digital-rain.html
diff options
context:
space:
mode:
Diffstat (limited to '_log/_site/matrix-digital-rain.html')
-rw-r--r--_log/_site/matrix-digital-rain.html103
1 files changed, 103 insertions, 0 deletions
diff --git a/_log/_site/matrix-digital-rain.html b/_log/_site/matrix-digital-rain.html
new file mode 100644
index 0000000..85bac5d
--- /dev/null
+++ b/_log/_site/matrix-digital-rain.html
@@ -0,0 +1,103 @@
+<p>The Matrix digital rain implemented in raw C using ANSI escape sequences with
+zero dependencies—not even ncurses.</p>
+
+<video style="max-width:100%;" controls="" poster="poster.png">
+ <source src="matrix.mp4" type="video/mp4" />
+</video>
+
+<p>This project began over three years ago as a fork of Domsson’s unique rendition
+of the Matrix rain: <a href="https://github.com/domsson/fakesteak" class="external" target="_blank" rel="noopener noreferrer">Fakesteak</a>. I
+aimed to modify the algorithm to produce a rain that resembled the original
+with high visual fidelity.</p>
+
+<h2 id="unicode-support">Unicode support</h2>
+
+<p>Unicode support in the 2022 version lacked flexibility. The charset used in the
+rain had to be a single contiguous block defined by <code class="language-plaintext highlighter-rouge">UNICODE_MIN</code> and
+<code class="language-plaintext highlighter-rouge">UNICODE_MAX</code> settings:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#define UNICODE_MIN 0x0021
+#define UNICODE_MAX 0x007E
+
+static inline void insert_code(matrix *mat,
+ size_t row, size_t col)
+{
+ mat-&gt;code[index(mat, row, col)] = rand()
+ % (UNICODE_MAX - UNICODE_MIN)
+ + UNICODE_MIN;
+}
+</code></pre></div></div>
+
+<p>There was no way, for instance, to use both ASCII and Katakana at the same
+time. The user had to pick one. In the new version, the user can use any number
+of Unicode blocks using <code class="language-plaintext highlighter-rouge">glyphs</code> array. In fact, the default rain now includes
+both ASCII and half-width Katakana characters:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#define UNICODE(min, max) (((uint64_t)max &lt;&lt; 32) | min)
+
+static uint64_t glyphs[] = {
+ UNICODE(0x0021, 0x007E), /* ASCII */
+ UNICODE(0xFF65, 0xFF9F), /* Half-width Katakana */
+};
+
+static uint8_t glyphlen = (sizeof glyphs) / (sizeof glyphs[0]);
+
+static inline void insert_code(matrix *mat,
+ size_t row, size_t col)
+{
+ uint64_t block;
+ uint32_t unicode_min, unicode_max;
+
+ block = glyphs[(rand() % glyphlen)];
+ unicode_min = (uint32_t)block;
+ unicode_max = (uint32_t)(block &gt;&gt; 32);
+
+ mat-&gt;code[index(mat, row, col)] = rand()
+ % (unicode_max - unicode_min)
+ + unicode_min;
+}
+</code></pre></div></div>
+
+<p>Entries in the <code class="language-plaintext highlighter-rouge">glyphs</code> array are Unicode blocks bit-packed in an 8-byte
+container: the four low bytes forms the first codepoint and the four high bytes
+the last.</p>
+
+<h2 id="phosphor-decay">Phosphor decay</h2>
+
+<p>The dim afterglow of monochrome CRT displays is achieved by carefully scaling
+the RGB channels individually and mixing them:</p>
+
+<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#define DECAY_MPLIER 2
+
+static inline void blend(matrix *mat,
+ size_t row, size_t col)
+{
+ unsigned char *color;
+
+ color = mat-&gt;rgb[index(mat, row, col)].color;
+ color[R] = color[R] - (color[R] - RGB_BG_RED) / DECAY_MPLIER;
+ color[G] = color[G] - (color[G] - RGB_BG_GRN) / DECAY_MPLIER;
+ color[B] = color[B] - (color[B] - RGB_BG_BLU) / DECAY_MPLIER;
+}
+</code></pre></div></div>
+
+<p>The blending function emulates the phosphor decay by gradually transitioning
+each raindrop’s color towards the background color. The multiplier is the
+number of passes over the rain track needed before the afterglow disappears.</p>
+
+<p>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.</p>
+
+<p>Lastly, to compile and run:</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>“All I see is blonde, brunette, red head.”</p>
+
+<p>Files: <a href="source.tar.gz">source.tar.gz</a></p>