diff options
Diffstat (limited to '_site/projects')
| -rw-r--r-- | _site/projects/bumblebee/index.html | 8 | ||||
| -rw-r--r-- | _site/projects/matrix-digital-rain/index.html | 106 |
2 files changed, 98 insertions, 16 deletions
diff --git a/_site/projects/bumblebee/index.html b/_site/projects/bumblebee/index.html index d6873e4..d8fded3 100644 --- a/_site/projects/bumblebee/index.html +++ b/_site/projects/bumblebee/index.html @@ -74,10 +74,10 @@ the script at any point during the session (using the embedded <a src="https://g events, and block hidden elements and scripts.</p> <p>Before settling on a desktop application, we contemplated designing Bumblebee -as a browser extension. We decided against that because we didn’t want the -browser vendors to dictate Bumblebee’s capabilities. Besides, the company’s -security policy, which prohibited browser extensions, would have complicated -the deployment of an extension-based solution. The initial prototype used a C# +as a browser extension. We chose the desktop app because extensions don’t offer +the deep, event-based control we needed. Besides, the company’s security +policy, which prohibited browser extensions, would have complicated the +deployment of an extension-based solution. The initial prototype used a C# wrapper of the Chromium project instead of WebView. WebView’s more intuitive API and its seamless integration with Windows Forms led us to choose it over the Chromium wrapper.</p> diff --git a/_site/projects/matrix-digital-rain/index.html b/_site/projects/matrix-digital-rain/index.html index 666456b..5c33db1 100644 --- a/_site/projects/matrix-digital-rain/index.html +++ b/_site/projects/matrix-digital-rain/index.html @@ -44,23 +44,105 @@ <h2 class="center" id="title">THE MATRIX DIGITAL RAIN</h2> <h6 class="center">12 JANUARY 2024</h5> <br> - <div class="twocol justify"><p>The famous digital rain from The Matrix, implemented in C.</p> + <div class="twocol justify"><p>“All I see is blonde, brunette, red head.” The iconic digital rain from The +Matrix implemented in C without dependencies (not even ncurses).</p> <video style="max-width:100%;" controls="" poster="thumb.png"> <source src="matrix.mp4" type="video/mp4" /> </video> -<p>This project is a fork of Domsson’s beautiful <a href="https://github.com/domsson/fakesteak" class="external" target="_blank" rel="noopener noreferrer">Fakesteak</a>.</p> - -<p>There are three color settings: head, tail, and background. They are configured -by setting the 24-bit RGB channels 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. 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.</p> - -<p>In addition, this implementation supports UTF-32 character sets. The -<code class="language-plaintext highlighter-rouge">UNICODE_MIN</code> and <code class="language-plaintext highlighter-rouge">UNICODE_MAX</code> controls the Unicode block used. For -instance, setting them to <code class="language-plaintext highlighter-rouge">0x30A1</code> and <code class="language-plaintext highlighter-rouge">0x30F6</code> rains Katakana:</p> +<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>. As I was going through the fakesteak +code, I thought about what it might take to recreate the original rain from the +first Matrix movie without losing the program’s minimalism and elegance.</p> + +<p>My version of the matrix has the following features:</p> + +<ul> + <li>Unicode characters.</li> + <li>Fully customizable 24-bit RGB (truecolor) colors.</li> + <li>Glitches in the matrix.</li> + <li>Ghosting effect of old monochrome displays.</li> + <li>Closely resembles the one seen in the background while Neo and Cypher were +talking in the first Matrix movie.</li> +</ul> + +<p>As there are no dependencies, you can compile and run it however you want:</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 <code class="language-plaintext highlighter-rouge">matrix</code> struct makes use of two 2D arrays to encode the Matrix: the <code class="language-plaintext highlighter-rouge">code</code> +array for 32-bit Unicode characters and the <code class="language-plaintext highlighter-rouge">rgb</code> array for RGB values of the +characters (foreground color). The dimensions of these arrays depend on the +size of the terminal window. Each slot in the array corresponds to a cursor +position on the screen.</p> + +<p>The ghosting effect, which is arguably the crowning feature of my version, is +implemented by carefully scaling and mixing the RGB channels:</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) +{ + 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; +} +</code></pre></div></div> + +<p>The above algorithm achieves transparency by iteratively bringing the +foreground color closer to the background color with each pass of the rain. +This approach offers multiple advantages, such as simpler and more natural +color configuration (background, foreground, and the color of the first drop) +that lends itself well to Unix ricing, and of course, recreates The Matrix rain +with high fidelity.</p> + +<p>Rather than heavy-weight graphics tool kits, we use ANSI escape codes to +control the terminal screen. It’s the effective use of the ANSI escape codes +that greatly contributes to the minimalism of the solution:</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->rgb[idx].color[R], + mat->rgb[idx].color[G], + mat->rgb[idx].color[B], + mat->code[idx]); +} +</code></pre></div></div> + +<p>Finally, the glitch effect is controlled by the following code:</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>if (mat.row[i] > 0 && rand() % 6 == 0) { + j = rand() % mat.row[i]; + if (mat.code[mat_idx(&mat, j, mat.col[i])] != ' ') { + mat_put_code(&mat, j, mat.col[i]); + term_print(&mat, j, mat.col[i]); + } +} +</code></pre></div></div> + +<p>The above code causes glitches in the Matrix with a probablity of 1/6.</p> + +<h2 id="customizing-the-rain">Customizing the rain</h2> + +<p>While you can customize almost any aspect of the rain including its speed, +glitch frequency, and the density of the rain, the most useful settings for +ricing are the color scheme and the character set used for the rain.</p> + +<p>There are three color settings: the head, the tail, and the background. They +are configured by setting the <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 in main.c. 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 instance, setting them to <code class="language-plaintext highlighter-rouge">0x30A1</code> and <code class="language-plaintext highlighter-rouge">0x30F6</code> rains +Katakana code points:</p> <p><img style="width: 100%;" src="katakana.png" /></p> |
