mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
More cleanup
This commit is contained in:
@@ -42,7 +42,7 @@
|
||||
import {
|
||||
loadImages,
|
||||
makeFullScreenQuad,
|
||||
makePalette
|
||||
make1DTexture
|
||||
} from "./js/utils.js";
|
||||
import makeConfig from "./js/config.js";
|
||||
import makeMatrixRenderer from "./js/renderer.js";
|
||||
@@ -67,7 +67,7 @@
|
||||
});
|
||||
|
||||
const [config, uniforms] = makeConfig(window.location.search, data =>
|
||||
makePalette(regl, data)
|
||||
make1DTexture(regl, data)
|
||||
);
|
||||
|
||||
const resize = () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { makePassFBO, makePyramid, resizePyramid } from "./utils.js";
|
||||
import { makePassFBO, makePyramid, resizePyramid, makePass } from "./utils.js";
|
||||
|
||||
// The bloom pass is basically an added high-pass blur.
|
||||
|
||||
@@ -11,32 +11,30 @@ const levelStrengths = Array(pyramidHeight)
|
||||
.reverse();
|
||||
|
||||
export default (regl, config, input) => {
|
||||
if (config.effect === "none") {
|
||||
return {
|
||||
output: input,
|
||||
resize: () => {},
|
||||
render: () => {}
|
||||
};
|
||||
if (!config.performBloom) {
|
||||
return makePass(input, null, null);
|
||||
}
|
||||
|
||||
const highPassPyramid = makePyramid(regl, pyramidHeight);
|
||||
const horizontalBlurPyramid = makePyramid(regl, pyramidHeight);
|
||||
const verticalBlurPyramid = makePyramid(regl, pyramidHeight);
|
||||
const hBlurPyramid = makePyramid(regl, pyramidHeight);
|
||||
const vBlurPyramid = makePyramid(regl, pyramidHeight);
|
||||
const output = makePassFBO(regl);
|
||||
|
||||
// The high pass restricts the blur to bright things in our input texture.
|
||||
const highPass = regl({
|
||||
frag: `
|
||||
#define lumaMag vec3(0.2126, 0.7152, 0.0722)
|
||||
precision mediump float;
|
||||
varying vec2 vUV;
|
||||
uniform sampler2D tex;
|
||||
uniform float highPassThreshold;
|
||||
void main() {
|
||||
float value = texture2D(tex, vUV).r;
|
||||
if (value < highPassThreshold) {
|
||||
value = 0.;
|
||||
vec3 lumaColor = texture2D(tex, vUV).rgb * lumaMag;
|
||||
float luma = lumaColor.r + lumaColor.g + lumaColor.b;
|
||||
if (luma < highPassThreshold) {
|
||||
luma = 0.;
|
||||
}
|
||||
gl_FragColor = vec4(vec3(value), 1.0);
|
||||
gl_FragColor = vec4(vec3(luma), 1.0);
|
||||
}
|
||||
`,
|
||||
uniforms: {
|
||||
@@ -79,70 +77,51 @@ export default (regl, config, input) => {
|
||||
frag: `
|
||||
precision mediump float;
|
||||
varying vec2 vUV;
|
||||
${verticalBlurPyramid
|
||||
.map((_, index) => `uniform sampler2D tex_${index};`)
|
||||
${vBlurPyramid
|
||||
.map((_, index) => `uniform sampler2D pyr_${index};`)
|
||||
.join("\n")}
|
||||
uniform sampler2D tex;
|
||||
uniform float bloomStrength;
|
||||
void main() {
|
||||
vec4 total = vec4(0.);
|
||||
${verticalBlurPyramid
|
||||
${vBlurPyramid
|
||||
.map(
|
||||
(_, index) =>
|
||||
`total += texture2D(tex_${index}, vUV) * ${levelStrengths[index]};`
|
||||
`total += texture2D(pyr_${index}, vUV) * ${levelStrengths[index]};`
|
||||
)
|
||||
.join("\n")}
|
||||
gl_FragColor = total * bloomStrength + texture2D(tex, vUV);
|
||||
}
|
||||
`,
|
||||
uniforms: Object.assign(
|
||||
{
|
||||
tex: input
|
||||
},
|
||||
Object.fromEntries(
|
||||
verticalBlurPyramid.map((fbo, index) => [`tex_${index}`, fbo])
|
||||
uniforms: {
|
||||
tex: input,
|
||||
...Object.fromEntries(
|
||||
vBlurPyramid.map((fbo, index) => [`pyr_${index}`, fbo])
|
||||
)
|
||||
),
|
||||
},
|
||||
framebuffer: output
|
||||
});
|
||||
|
||||
return {
|
||||
const scale = config.bloomSize;
|
||||
|
||||
return makePass(
|
||||
output,
|
||||
resize: (viewportWidth, viewportHeight) => {
|
||||
// The blur pyramids can be lower resolution than the screen.
|
||||
resizePyramid(
|
||||
highPassPyramid,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
config.bloomSize
|
||||
);
|
||||
resizePyramid(
|
||||
horizontalBlurPyramid,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
config.bloomSize
|
||||
);
|
||||
resizePyramid(
|
||||
verticalBlurPyramid,
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
config.bloomSize
|
||||
);
|
||||
output.resize(viewportWidth, viewportHeight);
|
||||
},
|
||||
render: () => {
|
||||
() => {
|
||||
highPassPyramid.forEach(fbo => highPass({ fbo, tex: input }));
|
||||
horizontalBlurPyramid.forEach((fbo, index) =>
|
||||
hBlurPyramid.forEach((fbo, index) =>
|
||||
blur({ fbo, tex: highPassPyramid[index], direction: [1, 0] })
|
||||
);
|
||||
verticalBlurPyramid.forEach((fbo, index) =>
|
||||
blur({
|
||||
fbo,
|
||||
tex: horizontalBlurPyramid[index],
|
||||
direction: [0, 1]
|
||||
})
|
||||
vBlurPyramid.forEach((fbo, index) =>
|
||||
blur({ fbo, tex: hBlurPyramid[index], direction: [0, 1] })
|
||||
);
|
||||
combineBloom();
|
||||
},
|
||||
(w, h) => {
|
||||
// The blur pyramids can be lower resolution than the screen.
|
||||
resizePyramid(highPassPyramid, w, h, scale);
|
||||
resizePyramid(hBlurPyramid, w, h, scale);
|
||||
resizePyramid(vBlurPyramid, w, h, scale);
|
||||
output.resize(w, h);
|
||||
}
|
||||
};
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { makePassFBO } from "./utils.js";
|
||||
import { makePassFBO, makePass } from "./utils.js";
|
||||
|
||||
// rendered texture's values are mapped to colors in a palette texture.
|
||||
// A little noise is introduced, to hide the banding that appears
|
||||
// in subtle gradients. The noise is also time-driven, so its grain
|
||||
// won't persist across subsequent frames. This is a safe trick
|
||||
// in screen space.
|
||||
|
||||
const colorizeByPalette = regl =>
|
||||
const colorizeByPalette = (regl, uniforms, framebuffer) =>
|
||||
// The rendered texture's values are mapped to colors in a palette texture.
|
||||
// A little noise is introduced, to hide the banding that appears
|
||||
// in subtle gradients. The noise is also time-driven, so its grain
|
||||
// won't persist across subsequent frames. This is a safe trick
|
||||
// in screen space.
|
||||
regl({
|
||||
frag: `
|
||||
precision mediump float;
|
||||
#define PI 3.14159265359
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D paletteColorData;
|
||||
uniform sampler2D palette;
|
||||
uniform float ditherMagnitude;
|
||||
uniform float time;
|
||||
varying vec2 vUV;
|
||||
@@ -25,23 +24,26 @@ const colorizeByPalette = regl =>
|
||||
}
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D( paletteColorData, vec2( texture2D( tex, vUV ).r - rand( gl_FragCoord.xy, time ) * ditherMagnitude, 0.0 ) );
|
||||
float at = texture2D( tex, vUV ).r - rand( gl_FragCoord.xy, time ) * ditherMagnitude;
|
||||
gl_FragColor = texture2D( palette, vec2(at, 0.0));
|
||||
}
|
||||
`,
|
||||
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
ditherMagnitude: 0.05
|
||||
}
|
||||
},
|
||||
framebuffer
|
||||
});
|
||||
|
||||
const colorizeByStripes = regl =>
|
||||
const colorizeByStripes = (regl, uniforms, framebuffer) =>
|
||||
regl({
|
||||
frag: `
|
||||
precision mediump float;
|
||||
#define PI 3.14159265359
|
||||
|
||||
uniform sampler2D tex;
|
||||
uniform sampler2D stripeColorData;
|
||||
uniform sampler2D stripes;
|
||||
uniform float ditherMagnitude;
|
||||
varying vec2 vUV;
|
||||
|
||||
@@ -52,18 +54,20 @@ const colorizeByStripes = regl =>
|
||||
}
|
||||
|
||||
void main() {
|
||||
float value = texture2D(tex, vUV).r;
|
||||
vec3 value2 = texture2D(stripeColorData, vUV).rgb - rand( gl_FragCoord.xy ) * ditherMagnitude;
|
||||
gl_FragColor = vec4(value2 * value, 1.0);
|
||||
vec3 color = texture2D(stripes, vUV).rgb - rand( gl_FragCoord.xy ) * ditherMagnitude;
|
||||
float brightness = texture2D(tex, vUV).r;
|
||||
gl_FragColor = vec4(color * brightness, 1.0);
|
||||
}
|
||||
`,
|
||||
|
||||
uniforms: {
|
||||
...uniforms,
|
||||
ditherMagnitude: 0.1
|
||||
}
|
||||
},
|
||||
framebuffer
|
||||
});
|
||||
|
||||
const colorizeByImage = (regl, bgTex) =>
|
||||
const colorizeByImage = (regl, uniforms, framebuffer) =>
|
||||
regl({
|
||||
frag: `
|
||||
precision mediump float;
|
||||
@@ -72,12 +76,13 @@ const colorizeByImage = (regl, bgTex) =>
|
||||
varying vec2 vUV;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(texture2D(bgTex, vUV).rgb * (pow(texture2D(tex, vUV).r, 1.5) * 0.995 + 0.005), 1.0);
|
||||
vec3 bgColor = texture2D(bgTex, vUV).rgb;
|
||||
float brightness = pow(texture2D(tex, vUV).r, 1.5);
|
||||
gl_FragColor = vec4(bgColor * brightness, 1.0);
|
||||
}
|
||||
`,
|
||||
uniforms: {
|
||||
bgTex
|
||||
}
|
||||
uniforms,
|
||||
framebuffer
|
||||
});
|
||||
|
||||
const colorizersByEffect = {
|
||||
@@ -89,36 +94,19 @@ const colorizersByEffect = {
|
||||
|
||||
export default (regl, config, { bgTex }, input) => {
|
||||
if (config.effect === "none") {
|
||||
return {
|
||||
output: input,
|
||||
resize: () => {},
|
||||
render: () => {}
|
||||
};
|
||||
return makePass(input, null, null);
|
||||
}
|
||||
|
||||
if (bgTex == null) {
|
||||
bgTex = 0;
|
||||
}
|
||||
|
||||
const output = makePassFBO(regl);
|
||||
|
||||
const colorize = regl({
|
||||
uniforms: {
|
||||
tex: regl.prop("tex")
|
||||
},
|
||||
framebuffer: output
|
||||
});
|
||||
|
||||
const colorizer = (config.effect in colorizersByEffect
|
||||
? colorizersByEffect[config.effect]
|
||||
: colorizeByPalette)(regl, bgTex);
|
||||
|
||||
return {
|
||||
return makePass(
|
||||
output,
|
||||
resize: output.resize,
|
||||
render: resources => {
|
||||
colorize(
|
||||
{
|
||||
tex: input
|
||||
},
|
||||
() => colorizer(resources)
|
||||
);
|
||||
}
|
||||
};
|
||||
(config.effect in colorizersByEffect
|
||||
? colorizersByEffect[config.effect]
|
||||
: colorizeByPalette)(regl, { bgTex, tex: input }, output)
|
||||
);
|
||||
};
|
||||
|
||||
25
js/config.js
25
js/config.js
@@ -38,7 +38,7 @@ const versions = {
|
||||
rippleScale: 30,
|
||||
rippleSpeed: 0.1,
|
||||
numColumns: 30,
|
||||
palette: [
|
||||
paletteEntries: [
|
||||
{ rgb: [0.0, 0.0, 0.0], at: 0.0 },
|
||||
{ rgb: [0.52, 0.17, 0.05], at: 0.4 },
|
||||
{ rgb: [0.82, 0.37, 0.12], at: 0.7 },
|
||||
@@ -69,7 +69,7 @@ const versions = {
|
||||
rippleScale: 30,
|
||||
rippleSpeed: 0.2,
|
||||
numColumns: 60,
|
||||
palette: [
|
||||
paletteEntries: [
|
||||
{ rgb: [0.0, 0.0, 0.0], at: 0.0 },
|
||||
{ rgb: [0.32, 0.06, 0.0], at: 0.2 },
|
||||
{ rgb: [0.82, 0.06, 0.05], at: 0.4 },
|
||||
@@ -100,7 +100,7 @@ const versions = {
|
||||
rippleScale: 30,
|
||||
rippleSpeed: 0.2,
|
||||
numColumns: 80,
|
||||
palette: [
|
||||
paletteEntries: [
|
||||
{ rgb: [0 / 255, 0 / 255, 0 / 255], at: 0 / 16 },
|
||||
{ rgb: [6 / 255, 16 / 255, 8 / 255], at: 1 / 16 },
|
||||
{ rgb: [11 / 255, 28 / 255, 15 / 255], at: 2 / 16 },
|
||||
@@ -143,7 +143,7 @@ const versions = {
|
||||
rippleScale: 30,
|
||||
rippleSpeed: 0.2,
|
||||
numColumns: 108,
|
||||
palette: [
|
||||
paletteEntries: [
|
||||
{ rgb: [0.0, 0.0, 0.0], at: 0.0 },
|
||||
{ rgb: [0.18, 0.9, 0.35], at: 0.6 },
|
||||
{ rgb: [0.9, 1.0, 0.9], at: 1.0 }
|
||||
@@ -155,7 +155,7 @@ const versions = {
|
||||
versions.throwback = versions.operator;
|
||||
versions["1999"] = versions.classic;
|
||||
|
||||
export default (searchString, makePaletteTexture) => {
|
||||
export default (searchString, make1DTexture) => {
|
||||
const urlParams = new URLSearchParams(searchString);
|
||||
const getParam = (keyOrKeys, defaultValue) => {
|
||||
if (Array.isArray(keyOrKeys)) {
|
||||
@@ -215,6 +215,11 @@ export default (searchString, makePaletteTexture) => {
|
||||
.split(",")
|
||||
.map(parseFloat);
|
||||
config.showComputationTexture = config.effect === "none";
|
||||
config.performBloom =
|
||||
config.effect !== "none" &&
|
||||
config.bloomSize > 0 &&
|
||||
config.bloomStrength > 0;
|
||||
console.log(config.effect, config.bloomSize, config.bloomStrength);
|
||||
|
||||
switch (config.cycleStyleName) {
|
||||
case "cycleFasterWhenDimmed":
|
||||
@@ -239,7 +244,7 @@ export default (searchString, makePaletteTexture) => {
|
||||
|
||||
const PALETTE_SIZE = 2048;
|
||||
const paletteColors = Array(PALETTE_SIZE);
|
||||
const sortedEntries = version.palette
|
||||
const sortedEntries = version.paletteEntries
|
||||
.slice()
|
||||
.sort((e1, e2) => e1.at - e2.at)
|
||||
.map(entry => ({
|
||||
@@ -269,9 +274,7 @@ export default (searchString, makePaletteTexture) => {
|
||||
}
|
||||
});
|
||||
|
||||
config.paletteColorData = makePaletteTexture(
|
||||
paletteColors.flat().map(i => i * 0xff)
|
||||
);
|
||||
config.palette = make1DTexture(paletteColors.flat().map(i => i * 0xff));
|
||||
|
||||
let stripeColors = [0, 0, 0];
|
||||
|
||||
@@ -292,9 +295,7 @@ export default (searchString, makePaletteTexture) => {
|
||||
stripeColors = config.customStripes.slice(0, numFlagColors * 3);
|
||||
}
|
||||
|
||||
config.stripeColorData = makePaletteTexture(
|
||||
stripeColors.map(f => Math.floor(f * 0xff))
|
||||
);
|
||||
config.stripes = make1DTexture(stripeColors.map(f => Math.floor(f * 0xff)));
|
||||
|
||||
const uniforms = Object.fromEntries(
|
||||
Object.entries(config).filter(([key, value]) => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { makePassFBO, makeDoubleBuffer } from "./utils.js";
|
||||
import { makePassFBO, makeDoubleBuffer, makePass } from "./utils.js";
|
||||
|
||||
export default (regl, config, { msdfTex }) => {
|
||||
// These two framebuffers are used to compute the raining code.
|
||||
@@ -292,12 +292,8 @@ export default (regl, config, { msdfTex }) => {
|
||||
framebuffer: output
|
||||
});
|
||||
|
||||
return {
|
||||
resize: output.resize,
|
||||
output,
|
||||
render: resources => {
|
||||
update();
|
||||
render(resources);
|
||||
}
|
||||
};
|
||||
return makePass(output, resources => {
|
||||
update();
|
||||
render(resources);
|
||||
});
|
||||
};
|
||||
|
||||
23
js/utils.js
23
js/utils.js
@@ -99,7 +99,7 @@ const makeFullScreenQuad = (regl, uniforms = {}, context = {}) =>
|
||||
count: 3
|
||||
});
|
||||
|
||||
const makePalette = (regl, data) =>
|
||||
const make1DTexture = (regl, data) =>
|
||||
regl.texture({
|
||||
data,
|
||||
width: data.length / 3,
|
||||
@@ -109,6 +109,24 @@ const makePalette = (regl, data) =>
|
||||
min: "linear"
|
||||
});
|
||||
|
||||
const makePass = (output, render, resize) => {
|
||||
if (render == null) {
|
||||
render = () => {};
|
||||
}
|
||||
if (resize === undefined) {
|
||||
// "default" resize function is on the FBO
|
||||
resize = (w, h) => output.resize(w, h);
|
||||
}
|
||||
if (resize == null) {
|
||||
resize = () => {};
|
||||
}
|
||||
return {
|
||||
output,
|
||||
render,
|
||||
resize
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
makePassTexture,
|
||||
makePassFBO,
|
||||
@@ -118,5 +136,6 @@ export {
|
||||
loadImage,
|
||||
loadImages,
|
||||
makeFullScreenQuad,
|
||||
makePalette
|
||||
make1DTexture,
|
||||
makePass
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user