diff --git a/TODO.txt b/TODO.txt index 854c54d..b4bb4bd 100644 --- a/TODO.txt +++ b/TODO.txt @@ -2,13 +2,12 @@ TODO: Improve forkability - Document every variable in config.js + Should the OPERATOR and PARADISE specific config values still exist? + Rename compute.frag to rain.compute + Rename bloom tex to blur tex + And rename bloom pass to blur pass Document every variable, method, and section of the main function in compute.frag Maybe rewrite it? Make the time based stuff easier to read? - Document resurrectionPass - Label it a WIP - List intended characteristics - Comment makePalette Write a document (and include images) that explains the underlying principle of the rain pass diff --git a/js/config.js b/js/config.js index d646ff1..b34f3c2 100644 --- a/js/config.js +++ b/js/config.js @@ -1,15 +1,18 @@ const fonts = { coptic: { + // The script the Gnostic codices were written in glyphTexURL: "coptic_msdf.png", glyphSequenceLength: 32, glyphTextureColumns: 8, }, gothic: { + // The script the Codex Argenteus was written in glyphTexURL: "gothic_msdf.png", glyphSequenceLength: 27, glyphTextureColumns: 8, }, matrixcode: { + // The glyphs seen in the film trilogy glyphTexURL: "matrixcode_msdf.png", glyphSequenceLength: 57, glyphTextureColumns: 8, @@ -17,42 +20,43 @@ const fonts = { }; const defaults = { - backgroundColor: [0, 0, 0], - volumetric: false, - resurrectingCodeRatio: 0, - animationSpeed: 1, - forwardSpeed: 0.25, - bloomStrength: 1, - bloomSize: 0.6, - highPassThreshold: 0.1, - cycleSpeed: 1, - cycleStyleName: "cycleFasterWhenDimmed", - cursorEffectThreshold: 1, - brightnessOffset: 0.0, - brightnessMultiplier: 1.0, - brightnessMix: 1.0, - brightnessMinimum: 0, - fallSpeed: 1, - glyphEdgeCrop: 0.0, - glyphHeightToWidth: 1, - hasSun: false, - hasThunder: false, - isPolar: false, - rippleTypeName: null, - rippleThickness: 0.2, - rippleScale: 30, - rippleSpeed: 0.2, - numColumns: 80, - density: 1, + backgroundColor: [0, 0, 0], // The color "behind" the glyphs + volumetric: false, // A mode where the raindrops appear in perspective + resurrectingCodeRatio: 0, // The percent of columns that flow upward + animationSpeed: 1, // The global rate that all animations progress + forwardSpeed: 0.25, // The speed volumetric rain approaches the eye + bloomStrength: 1, // The intensity of the bloom + bloomSize: 0.6, // The amount the bloom calculation is scaled + highPassThreshold: 0.1, // The minimum brightness that is still blurred + cycleSpeed: 1, // The speed glyphs change + 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 + brightnessOffset: 0.0, // OPERATOR + brightnessMultiplier: 1.0, // OPERATOR + brightnessMinimum: 0, // OPERATOR + brightnessMix: 1.0, // The decay at which a glyph lights up and dims + fallSpeed: 1, // The speed the raindrops progress downwards + glyphEdgeCrop: 0.0, // The border around a glyph in a font texture that should be cropped out + glyphHeightToWidth: 1, // The aspect ratio of glyphs + hasSun: false, // Makes the glyphs more radiant. Admittedly not very technical. + hasThunder: false, // An effect that adds dramatic lightning flashes + isPolar: false, // Whether the glyphs arc across the screen or sit in a standard grid + rippleTypeName: null, // The variety of the ripple effect + rippleThickness: 0.2, // The thickness of the ripple effect + rippleScale: 30, // The size of the ripple effect + rippleSpeed: 0.2, // The rate at which the ripple effect progresses + numColumns: 80, // The maximum dimension of the glyph grid + density: 1, // In volumetric mode, the number of actual columns compared to the grid paletteEntries: [ + // The color palette that glyph brightness is color mapped to { hsl: [0.3, 0.9, 0.0], at: 0.0 }, { hsl: [0.3, 0.9, 0.2], at: 0.2 }, { hsl: [0.3, 0.9, 0.7], at: 0.7 }, { hsl: [0.3, 0.9, 0.8], at: 0.8 }, ], - raindropLength: 1, - slant: 0, - resolution: 1, + raindropLength: 1, // Adjusts the frequency of raindrops (and their length) in a column + slant: 0, // The angle at which rain falls; the orientation of the glyph grid + resolution: 1, // An overall scale multiplier useHalfFloat: false, }; diff --git a/js/palettePass.js b/js/palettePass.js index 2bc3cb6..d94fdde 100644 --- a/js/palettePass.js +++ b/js/palettePass.js @@ -17,6 +17,8 @@ const colorToRGB = ([hue, saturation, lightness]) => { const makePalette = (regl, entries) => { const PALETTE_SIZE = 2048; const paletteColors = Array(PALETTE_SIZE); + + // Convert HSL gradient into sorted RGB gradient, capping the ends const sortedEntries = entries .slice() .sort((e1, e2) => e1.at - e2.at) @@ -29,6 +31,9 @@ const makePalette = (regl, entries) => { rgb: sortedEntries[sortedEntries.length - 1].rgb, arrayIndex: PALETTE_SIZE - 1, }); + + // Interpolate between the sorted RGB entries to generate + // the palette texture data sortedEntries.forEach((entry, index) => { paletteColors[entry.arrayIndex] = entry.rgb.slice(); if (index + 1 < sortedEntries.length) { diff --git a/js/resurrectionPass.js b/js/resurrectionPass.js index 938c795..14531d3 100644 --- a/js/resurrectionPass.js +++ b/js/resurrectionPass.js @@ -1,5 +1,13 @@ import { loadText, make1DTexture, makePassFBO, makePass } from "./utils.js"; +// Matrix Resurrections isn't in theaters yet, +// and this version of the effect is still a WIP. + +// Criteria: +// Upward-flowing glyphs should be golden +// Downward-flowing glyphs should be tinted slightly blue on top and golden on the bottom +// Cheat a lens blur, interpolating between the texture and bloom at the edges + export default (regl, config, inputs) => { const output = makePassFBO(regl, config.useHalfFloat); const { backgroundColor } = config; diff --git a/shaders/resurrectionPass.frag b/shaders/resurrectionPass.frag index 62fc4ee..0d73a83 100644 --- a/shaders/resurrectionPass.frag +++ b/shaders/resurrectionPass.frag @@ -35,10 +35,24 @@ vec3 hslToRgb(float h, float s, float l){ void main() { - vec3 brightness = mix(texture2D( bloomTex, vUV ).rgb, texture2D( tex, vUV ).rgb, (0.7 - length(vUV - 0.5))) * 1.25 - rand( gl_FragCoord.xy, time ) * ditherMagnitude; + // Mix the texture and bloom based on distance from center, + // to approximate a lens blur + vec3 brightness = mix( + texture2D( bloomTex, vUV ).rgb, + texture2D( tex, vUV ).rgb, + (0.7 - length(vUV - 0.5)) + ) * 1.25; + // Dither: subtract a random value from the brightness + brightness = brightness - rand( gl_FragCoord.xy, time ) * ditherMagnitude; + + // Calculate a hue based on distance from center float hue = 0.35 + (length(vUV - vec2(0.5, 1.0)) * -0.4 + 0.2); + + // Convert HSL to RGB vec3 rgb = hslToRgb(hue, 0.8, max(0., brightness.r)) * vec3(0.8, 1.0, 0.7); + + // Calculate a separate RGB for upward-flowing glyphs vec3 resurrectionRGB = hslToRgb(0.13, 1.0, max(0., brightness.g) * 0.9); gl_FragColor = vec4(rgb + resurrectionRGB + backgroundColor, 1.0); }