mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
Adding "glint", the shapes that appear on top of the glyphs in the Resurrections opening titles.
This commit is contained in:
36
js/config.js
36
js/config.js
@@ -26,6 +26,7 @@ const fonts = {
|
||||
resurrections: {
|
||||
// The glyphs seen in the film trilogy
|
||||
glyphTexURL: "assets/resurrections_msdf.png",
|
||||
glintTexURL: "assets/resurrections_glint_msdf.png",
|
||||
glyphSequenceLength: 135,
|
||||
glyphTextureGridSize: [13, 12],
|
||||
},
|
||||
@@ -57,6 +58,8 @@ const defaults = {
|
||||
backgroundColor: [0, 0, 0], // The color "behind" the glyphs
|
||||
isolateCursor: true, // Whether the "cursor"— the brightest glyph at the bottom of a raindrop— has its own color
|
||||
cursorColor: [1.5, 2, 0.9], // The color of the cursor
|
||||
isolateGlint: false, // Whether the "glint"— highlights on certain symbols in the font— should appear
|
||||
glintColor: [1, 1, 1], // The color of the glint
|
||||
volumetric: false, // A mode where the raindrops appear in perspective
|
||||
animationSpeed: 1, // The global rate that all animations progress
|
||||
forwardSpeed: 0.25, // The speed volumetric rain approaches the eye
|
||||
@@ -188,6 +191,28 @@ const versions = {
|
||||
{ hsl: [0.375, 1.0, 1.0], at: 1.0 },
|
||||
],
|
||||
},
|
||||
trinity: {
|
||||
font: "resurrections",
|
||||
glyphEdgeCrop: 0.1,
|
||||
cursorColor: [1.4, 2, 1.2],
|
||||
isolateGlint: true,
|
||||
glintColor: [2, 1.5, 0.5],
|
||||
baseBrightness: -0.9,
|
||||
baseContrast: 1.5,
|
||||
highPassThreshold: 0,
|
||||
numColumns: 50,
|
||||
cycleSpeed: 0.03,
|
||||
bloomStrength: 0.7,
|
||||
fallSpeed: 0.3,
|
||||
paletteEntries: [
|
||||
{ hsl: [0.4, 0.9, 0.0], at: 0.0 },
|
||||
{ hsl: [0.4, 1.0, 0.5], at: 1.0 },
|
||||
],
|
||||
volumetric: true,
|
||||
forwardSpeed: 0.2,
|
||||
raindropLength: 0.3,
|
||||
density: 0.5,
|
||||
},
|
||||
palimpsest: {
|
||||
font: "huberfishA",
|
||||
isolateCursor: false,
|
||||
@@ -303,6 +328,7 @@ const paramMapping = {
|
||||
stripeColors: { key: "stripeColors", parser: (s) => s },
|
||||
backgroundColor: { key: "backgroundColor", parser: (s) => s.split(",").map(parseFloat) },
|
||||
cursorColor: { key: "cursorColor", parser: (s) => s.split(",").map(parseFloat) },
|
||||
glintColor: { key: "glintColor", parser: (s) => s.split(",").map(parseFloat) },
|
||||
volumetric: { key: "volumetric", parser: (s) => s.toLowerCase().includes("true") },
|
||||
loops: { key: "loops", parser: (s) => s.toLowerCase().includes("true") },
|
||||
renderer: { key: "renderer", parser: (s) => s },
|
||||
@@ -321,8 +347,14 @@ export default (urlParams) => {
|
||||
.filter(([_, value]) => value != null)
|
||||
);
|
||||
|
||||
if (validParams.effect != null && validParams.cursorColor == null) {
|
||||
validParams.cursorColor = [2, 2, 2];
|
||||
if (validParams.effect != null) {
|
||||
if (validParams.cursorColor == null) {
|
||||
validParams.cursorColor = [2, 2, 2];
|
||||
}
|
||||
|
||||
if (validParams.glintColor == null) {
|
||||
validParams.glintColor = [1, 1, 1];
|
||||
}
|
||||
}
|
||||
|
||||
const version = validParams.version in versions ? versions[validParams.version] : versions.classic;
|
||||
|
||||
@@ -65,7 +65,7 @@ const makePalette = (regl, entries) => {
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
const palette = makePalette(regl, config.paletteEntries);
|
||||
const { backgroundColor, cursorColor, ditherMagnitude, bloomStrength } = config;
|
||||
const { backgroundColor, cursorColor, glintColor, ditherMagnitude, bloomStrength } = config;
|
||||
|
||||
const palettePassFrag = loadText("shaders/glsl/palettePass.frag.glsl");
|
||||
|
||||
@@ -75,6 +75,7 @@ export default ({ regl, config }, inputs) => {
|
||||
uniforms: {
|
||||
backgroundColor,
|
||||
cursorColor,
|
||||
glintColor,
|
||||
ditherMagnitude,
|
||||
bloomStrength,
|
||||
tex: inputs.primary,
|
||||
|
||||
@@ -116,6 +116,7 @@ export default ({ regl, config, lkg }) => {
|
||||
|
||||
// We render the code into an FBO using MSDFs: https://github.com/Chlumsky/msdfgen
|
||||
const msdf = loadImage(regl, config.glyphTexURL);
|
||||
const glintMSDF = loadImage(regl, config.glintTexURL);
|
||||
const rainPassVert = loadText("shaders/glsl/rainPass.vert.glsl");
|
||||
const rainPassFrag = loadText("shaders/glsl/rainPass.frag.glsl");
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
@@ -131,6 +132,7 @@ export default ({ regl, config, lkg }) => {
|
||||
"brightnessThreshold",
|
||||
"brightnessOverride",
|
||||
"isolateCursor",
|
||||
"isolateGlint",
|
||||
"glyphEdgeCrop",
|
||||
"isPolar",
|
||||
]),
|
||||
@@ -160,6 +162,7 @@ export default ({ regl, config, lkg }) => {
|
||||
symbolState: symbolDoubleBuffer.front,
|
||||
effectState: effectDoubleBuffer.front,
|
||||
glyphTex: msdf.texture,
|
||||
glintTex: glintMSDF.texture,
|
||||
|
||||
camera: regl.prop("camera"),
|
||||
transform: regl.prop("transform"),
|
||||
@@ -201,7 +204,7 @@ export default ({ regl, config, lkg }) => {
|
||||
{
|
||||
primary: output,
|
||||
},
|
||||
Promise.all([msdf.loaded, rainPassShine.loaded, rainPassSymbol.loaded, rainPassVert.loaded, rainPassFrag.loaded]),
|
||||
Promise.all([msdf.loaded, glintMSDF.loaded, rainPassShine.loaded, rainPassSymbol.loaded, rainPassVert.loaded, rainPassFrag.loaded]),
|
||||
(w, h) => {
|
||||
output.resize(w, h);
|
||||
const aspectRatio = w / h;
|
||||
|
||||
@@ -31,7 +31,7 @@ const prideStripeColors = [
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
|
||||
const { backgroundColor, cursorColor, ditherMagnitude, bloomStrength } = config;
|
||||
const { backgroundColor, cursorColor, glintColor, ditherMagnitude, bloomStrength } = config;
|
||||
|
||||
// Expand and convert stripe colors into 1D texture data
|
||||
const stripeColors =
|
||||
@@ -50,6 +50,7 @@ export default ({ regl, config }, inputs) => {
|
||||
uniforms: {
|
||||
backgroundColor,
|
||||
cursorColor,
|
||||
glintColor,
|
||||
ditherMagnitude,
|
||||
bloomStrength,
|
||||
tex: inputs.primary,
|
||||
|
||||
@@ -30,7 +30,7 @@ const loadImage = (regl, url) => {
|
||||
let loaded = false;
|
||||
return {
|
||||
texture: () => {
|
||||
if (!loaded) {
|
||||
if (!loaded && url != null) {
|
||||
console.warn(`texture still loading: ${url}`);
|
||||
}
|
||||
return texture;
|
||||
|
||||
@@ -108,6 +108,7 @@ export default ({ config, device, timeBuffer }) => {
|
||||
ditherMagnitude: config.ditherMagnitude,
|
||||
backgroundColor: config.backgroundColor,
|
||||
cursorColor: config.cursorColor,
|
||||
glintColor: config.glintColor,
|
||||
});
|
||||
|
||||
const paletteUniforms = paletteShaderUniforms.Palette;
|
||||
|
||||
@@ -26,7 +26,7 @@ const makeConfigBuffer = (device, configUniforms, config, density, gridSize) =>
|
||||
export default ({ config, device, timeBuffer }) => {
|
||||
const { mat4, vec3 } = glMatrix;
|
||||
|
||||
const assets = [loadTexture(device, config.glyphTexURL), loadShader(device, "shaders/wgsl/rainPass.wgsl")];
|
||||
const assets = [loadTexture(device, config.glyphTexURL), loadTexture(device, config.glintTexURL), loadShader(device, "shaders/wgsl/rainPass.wgsl")];
|
||||
|
||||
// The volumetric mode multiplies the number of columns
|
||||
// to reach the desired density, and then overlaps them
|
||||
@@ -85,7 +85,7 @@ export default ({ config, device, timeBuffer }) => {
|
||||
let highPassOutput;
|
||||
|
||||
const loaded = (async () => {
|
||||
const [msdfTexture, rainShader] = await Promise.all(assets);
|
||||
const [msdfTexture, glintMSDFTexture, rainShader] = await Promise.all(assets);
|
||||
|
||||
const rainShaderUniforms = structs.from(rainShader.code);
|
||||
configBuffer = makeConfigBuffer(device, rainShaderUniforms.Config, config, density, gridSize);
|
||||
@@ -143,7 +143,15 @@ export default ({ config, device, timeBuffer }) => {
|
||||
]);
|
||||
|
||||
computeBindGroup = makeBindGroup(device, computePipeline, 0, [configBuffer, timeBuffer, cellsBuffer]);
|
||||
renderBindGroup = makeBindGroup(device, renderPipeline, 0, [configBuffer, timeBuffer, sceneBuffer, linearSampler, msdfTexture.createView(), cellsBuffer]);
|
||||
renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
||||
configBuffer,
|
||||
timeBuffer,
|
||||
sceneBuffer,
|
||||
linearSampler,
|
||||
msdfTexture.createView(),
|
||||
glintMSDFTexture.createView(),
|
||||
cellsBuffer,
|
||||
]);
|
||||
})();
|
||||
|
||||
const build = (size) => {
|
||||
|
||||
@@ -79,6 +79,7 @@ export default ({ config, device, timeBuffer }) => {
|
||||
ditherMagnitude: config.ditherMagnitude,
|
||||
backgroundColor: config.backgroundColor,
|
||||
cursorColor: config.cursorColor,
|
||||
glintColor: config.glintColor,
|
||||
});
|
||||
})();
|
||||
|
||||
|
||||
@@ -20,6 +20,14 @@ const loadTexture = async (device, url) => {
|
||||
*/
|
||||
|
||||
const loadTexture = async (device, url) => {
|
||||
if (url == null) {
|
||||
return device.createTexture({
|
||||
size: [1, 1, 1],
|
||||
format: "rgba8unorm",
|
||||
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,
|
||||
});
|
||||
}
|
||||
|
||||
const image = new Image();
|
||||
image.crossOrigin = "Anonymous";
|
||||
image.src = url;
|
||||
|
||||
Reference in New Issue
Block a user