mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
Freeing up a rain pass channel
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
- [Raw compute texture (`effect=none`) (_epilepsy warning_: lots of flickering)](https://rezmason.github.io/matrix/?effect=none)
|
||||
|
||||
- [The free font (TrueType).](https://github.com/Rezmason/matrix/raw/master/assets/Matrix-Code.ttf)
|
||||
- [The unofficial glyph database.](https://docs.google.com/spreadsheets/d/1NRJP88EzQlj_ghBbtjkGi-NbluZzlWpAqVIAq1MDGJc)
|
||||
---
|
||||
### about
|
||||
|
||||
@@ -40,8 +41,9 @@ The way I see it, there's four kinds of Matrix effects people call ["digital rai
|
||||
|
||||
While there have been a lot of attempts at #1 and #3, they're all missing important parts of #4 that make digital rain so iconic. Here are the requirements for my implementation:
|
||||
|
||||
- **Get the right glyphs**. Like the actual ones. Everyone knows Matrix glyphs are some treatment of [Katakana](https://en.wikipedia.org/wiki/Katakana), but they also include a few characters from [Susan Kare's Chicago typeface](https://en.wikipedia.org/wiki/Chicago_(typeface)). The Matrix glyphs in *this* project come from the source: cleaned up vectors [from an old SWF](https://web.archive.org/web/20070914173039/http://www.atari.com:80/thematrixpathofneo/) for an official Matrix product, archived back in 2007. That's how deep this rabbit hole goes, friends.
|
||||
- **Get the right glyphs**. Like the actual ones. By now everyone's heard how the Matrix glyphs are some treatment of [Katakana](https://en.wikipedia.org/wiki/Katakana), but they also include a few characters from [Susan Kare's Chicago typeface](https://en.wikipedia.org/wiki/Chicago_(typeface)). The Matrix glyphs in *this* project come from the source: cleaned up vectors [from an old SWF](https://web.archive.org/web/20070914173039/http://www.atari.com:80/thematrixpathofneo/) for an official Matrix product, archived back in 2007. That's how deep this rabbit hole goes, friends.
|
||||
(Please support the [Internet Archive!](https://archive.org/about/))
|
||||
- **Get the new glyphs**. When *Resurrections* hit theaters, it debuted an expanded glyph set with a daunting *135 symbols*. Fortunately, in this age of higher resolution reference material and tie-in marketing, a decent sized sample of new glyphs were reverse-engineered from [a sparkly watch ad](https://www.hamiltonwatch.com/en-int/thematrixresurrections), and the rest were lovingly synthesized from frames of a [behind-the-scenes VFX video](https://buf.com/films/the-matrix-resurrections).
|
||||
- **Make it look sweet in 2D.** This is not a cop-out. There is just no scene in the movies as iconic as the digital rain itself, and while depth effects are cool, they take away from these other details that make the difference between a goodtrix and a *greatrix*.
|
||||
- **Make it look sweet in 3D, too.** This is not me caving to pressure! To facilitate future support of stereoscopic and holographic displays, it makes sense to nail down a 3D variation.
|
||||
- **The 2D glyphs are in a *fixed grid* and *don't move*.** The "raindrops" we see in the 2D effect are changes in the brightness of symbols that occupy a column. To get a closer look at this, try setting the `fallSpeed` to a number close to 0.
|
||||
|
||||
5
TODO.txt
5
TODO.txt
@@ -2,8 +2,8 @@ TODO:
|
||||
|
||||
Random cycling should actually be random
|
||||
Compute shader should have separate channels for cycle and symbol
|
||||
Move depth math to vertex shader, free that channel up
|
||||
Pass it into fragment shader with varying
|
||||
|
||||
Try to identify cursors more consistently
|
||||
|
||||
Audio system
|
||||
Toggle (or number representing frequency)
|
||||
@@ -13,7 +13,6 @@ Audio system
|
||||
Random volume?
|
||||
Randomize pitch a little?
|
||||
|
||||
|
||||
Playdate version
|
||||
Regenerate texture
|
||||
At this point, pay someone to make the sound effect or something
|
||||
|
||||
@@ -26,7 +26,7 @@ const fonts = {
|
||||
resurrections: {
|
||||
// The glyphs seen in the film trilogy
|
||||
glyphTexURL: "assets/resurrections_msdf.png",
|
||||
glyphSequenceLength: 133,
|
||||
glyphSequenceLength: 135,
|
||||
glyphTextureGridSize: [13, 12],
|
||||
},
|
||||
huberfishA: {
|
||||
@@ -66,7 +66,7 @@ const defaults = {
|
||||
cycleStyleName: "cycleFasterWhenDimmed", // The way glyphs cycle, either proportional to their brightness or randomly
|
||||
cursorEffectThreshold: 1, // The minimum brightness for a glyph to still be lit up as a cursor at the bottom of a raindrop
|
||||
baseBrightness: -0.5, // The brightness of the glyphs, before any effects are applied
|
||||
baseContrast: 1.25, // The contrast of the glyphs, before any effects are applied
|
||||
baseContrast: 1.1, // The contrast of the glyphs, before any effects are applied
|
||||
brightnessOverride: 0.0, // A global override to the brightness of displayed glyphs. Only used if it is > 0.
|
||||
brightnessThreshold: 0, // The minimum brightness for a glyph to still be considered visible
|
||||
brightnessDecay: 1.0, // The rate at which glyphs light up and dim
|
||||
@@ -108,13 +108,15 @@ const versions = {
|
||||
width: 40,
|
||||
},
|
||||
operator: {
|
||||
baseBrightness: -0.3,
|
||||
baseContrast: 1,
|
||||
bloomSize: 0.6,
|
||||
bloomStrength: 0.75,
|
||||
highPassThreshold: 0.0,
|
||||
cycleSpeed: 0.2,
|
||||
cycleFrameSkip: 8,
|
||||
cycleStyleName: "cycleRandomly",
|
||||
cursorEffectThreshold: 0.725,
|
||||
cursorEffectThreshold: 0.69,
|
||||
brightnessOverride: 0.22,
|
||||
brightnessThreshold: 0,
|
||||
fallSpeed: 0.6,
|
||||
@@ -243,6 +245,7 @@ const versions = {
|
||||
['3d']: {
|
||||
volumetric: true,
|
||||
fallSpeed: 0.5,
|
||||
cycleSpeed: 1,
|
||||
baseBrightness: -0.9,
|
||||
baseContrast: 1.5,
|
||||
raindropLength: 0.3
|
||||
|
||||
@@ -3,7 +3,7 @@ precision highp float;
|
||||
// This shader is the star of the show. For each glyph, it determines its:
|
||||
// R: brightness
|
||||
// G: progress through the glyph sequence
|
||||
// B: depth, aka distance from the screen
|
||||
// B: unused!
|
||||
// A: additional brightness for effects
|
||||
|
||||
// Listen.
|
||||
@@ -24,7 +24,7 @@ uniform bool hasSun, hasThunder, loops;
|
||||
uniform bool showComputationTexture;
|
||||
uniform float brightnessOverride, brightnessThreshold, brightnessDecay;
|
||||
uniform float baseContrast, baseBrightness;
|
||||
uniform float raindropLength, glyphHeightToWidth;
|
||||
uniform float raindropLength, glyphHeightToWidth, glyphSequenceLength;
|
||||
uniform int cycleStyle, rippleType;
|
||||
uniform float rippleScale, rippleSpeed, rippleThickness;
|
||||
uniform float cursorEffectThreshold;
|
||||
@@ -188,10 +188,7 @@ vec4 computeResult(bool isFirstFrame, vec4 previousResult, vec2 glyphPos, vec2 s
|
||||
brightness = mix(previousBrightness, brightness, brightnessDecay);
|
||||
}
|
||||
|
||||
// Determine the glyph depth. This is a static value for each column.
|
||||
float depth = randomFloat(vec2(screenPos.x, 0.));
|
||||
|
||||
vec4 result = vec4(brightness, cycle, depth, effect);
|
||||
vec4 result = vec4(brightness, cycle, 0.0, effect);
|
||||
|
||||
// Better use of the alpha channel, for demonstrating how the glyph cycle works
|
||||
if (showComputationTexture) {
|
||||
|
||||
@@ -18,15 +18,21 @@ uniform bool volumetric;
|
||||
varying vec2 vUV;
|
||||
varying vec3 vChannel;
|
||||
varying vec4 vGlyph;
|
||||
varying float vDepth;
|
||||
|
||||
float median3(vec3 i) {
|
||||
return max(min(i.r, i.g), min(max(i.r, i.g), i.b));
|
||||
}
|
||||
|
||||
float modI(float a, float b) {
|
||||
float m = a - floor((a + 0.5) / b) * b;
|
||||
return floor(m + 0.5);
|
||||
}
|
||||
|
||||
vec2 getSymbolUV(float glyphCycle) {
|
||||
float symbol = floor((glyphSequenceLength) * glyphCycle) + 1.0;
|
||||
float symbolX = mod(symbol, glyphTextureGridSize.x);
|
||||
float symbolY = mod(floor(symbol / glyphTextureGridSize.x), glyphTextureGridSize.y);
|
||||
float symbol = floor((glyphSequenceLength) * glyphCycle);
|
||||
float symbolX = modI(symbol, glyphTextureGridSize.x);
|
||||
float symbolY = (symbol - symbolX) / glyphTextureGridSize.x;
|
||||
symbolY = glyphTextureGridSize.y - symbolY - 1.0;
|
||||
return vec2(symbolX, symbolY);
|
||||
}
|
||||
@@ -59,13 +65,12 @@ void main() {
|
||||
vec4 glyph = volumetric ? vGlyph : texture2D(state, uv);
|
||||
float brightness = glyph.r;
|
||||
vec2 symbolUV = getSymbolUV(glyph.g);
|
||||
float quadDepth = glyph.b;
|
||||
float effect = glyph.a;
|
||||
|
||||
brightness = max(effect, brightness);
|
||||
// In volumetric mode, distant glyphs are dimmer
|
||||
if (volumetric) {
|
||||
brightness = brightness * min(1.0, quadDepth);
|
||||
brightness = brightness * min(1.0, vDepth);
|
||||
}
|
||||
|
||||
// resolve UV to cropped position of glyph in MSDF texture
|
||||
|
||||
@@ -12,6 +12,7 @@ uniform bool volumetric;
|
||||
varying vec2 vUV;
|
||||
varying vec3 vChannel;
|
||||
varying vec4 vGlyph;
|
||||
varying float vDepth;
|
||||
|
||||
highp float rand( const in vec2 uv ) {
|
||||
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
|
||||
@@ -27,8 +28,9 @@ void main() {
|
||||
// Calculate the world space position
|
||||
float quadDepth = 0.0;
|
||||
if (volumetric) {
|
||||
quadDepth = fract(vGlyph.b + time * animationSpeed * forwardSpeed);
|
||||
vGlyph.b = quadDepth;
|
||||
float startDepth = rand(vec2(aPosition.x, 0.));
|
||||
quadDepth = fract(startDepth + time * animationSpeed * forwardSpeed);
|
||||
vDepth = quadDepth;
|
||||
}
|
||||
vec2 position = (aPosition * vec2(1., glyphVerticalSpacing) + aCorner * vec2(density, 1.)) * quadSize;
|
||||
vec4 pos = vec4((position - 0.5) * 2.0, quadDepth, 1.0);
|
||||
|
||||
Reference in New Issue
Block a user