mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-21 15:29:30 -07:00
More cleanup
This commit is contained in:
43
index.html
43
index.html
@@ -70,17 +70,6 @@
|
|||||||
makePalette(regl, data)
|
makePalette(regl, data)
|
||||||
);
|
);
|
||||||
|
|
||||||
// All this takes place in a full screen quad.
|
|
||||||
const fullScreenQuad = makeFullScreenQuad(regl, uniforms);
|
|
||||||
const renderer = makeMatrixRenderer(regl, config);
|
|
||||||
const bloomPass = makeBloomPass(regl, config, renderer.fbo);
|
|
||||||
const colorPass = makeColorPass(regl, config, bloomPass.fbo);
|
|
||||||
const drawToScreen = regl({
|
|
||||||
uniforms: {
|
|
||||||
tex: colorPass.fbo
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const resize = () => {
|
const resize = () => {
|
||||||
canvas.width = canvas.clientWidth;
|
canvas.width = canvas.clientWidth;
|
||||||
canvas.height = canvas.clientHeight;
|
canvas.height = canvas.clientHeight;
|
||||||
@@ -88,27 +77,29 @@
|
|||||||
window.onresize = resize;
|
window.onresize = resize;
|
||||||
resize();
|
resize();
|
||||||
|
|
||||||
fullScreenQuad(renderer.update);
|
|
||||||
|
|
||||||
document.body.onload = async () => {
|
document.body.onload = async () => {
|
||||||
const resources = await loadImages(regl, {
|
const images = await loadImages(regl, {
|
||||||
msdfTex: config.glyphTexURL,
|
msdfTex: config.glyphTexURL,
|
||||||
backgroundTex:
|
bgTex: config.effect === "image" ? config.bgURL : null
|
||||||
config.effect === "image" ? config.backgroundImage : null
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const loop = regl.frame(({ viewportWidth, viewportHeight }) => {
|
// All this takes place in a full screen quad.
|
||||||
// All the FBOs except the compute FBOs need to be sized to the window.
|
const fullScreenQuad = makeFullScreenQuad(regl, uniforms);
|
||||||
renderer.resize(viewportWidth, viewportHeight);
|
const renderer = makeMatrixRenderer(regl, config, images);
|
||||||
bloomPass.resize(viewportWidth, viewportHeight);
|
const bloomPass = makeBloomPass(regl, config, renderer.output);
|
||||||
colorPass.resize(viewportWidth, viewportHeight);
|
const colorPass = makeColorPass(regl, config, images, bloomPass.output);
|
||||||
|
const drawToScreen = regl({
|
||||||
|
uniforms: {
|
||||||
|
tex: colorPass.output
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// And here is the full draw sequence.
|
const passes = [renderer, bloomPass, colorPass];
|
||||||
|
|
||||||
|
const loop = regl.frame(({ viewportWidth, viewportHeight }) => {
|
||||||
|
passes.forEach(pass => pass.resize(viewportWidth, viewportHeight));
|
||||||
fullScreenQuad(() => {
|
fullScreenQuad(() => {
|
||||||
renderer.update();
|
passes.forEach(pass => pass.render());
|
||||||
renderer.render(resources);
|
|
||||||
bloomPass.render();
|
|
||||||
colorPass.render(resources);
|
|
||||||
drawToScreen();
|
drawToScreen();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const levelStrengths = Array(pyramidHeight)
|
|||||||
export default (regl, config, input) => {
|
export default (regl, config, input) => {
|
||||||
if (config.effect === "none") {
|
if (config.effect === "none") {
|
||||||
return {
|
return {
|
||||||
fbo: input,
|
output: input,
|
||||||
resize: () => {},
|
resize: () => {},
|
||||||
render: () => {}
|
render: () => {}
|
||||||
};
|
};
|
||||||
@@ -22,7 +22,7 @@ export default (regl, config, input) => {
|
|||||||
const highPassPyramid = makePyramid(regl, pyramidHeight);
|
const highPassPyramid = makePyramid(regl, pyramidHeight);
|
||||||
const horizontalBlurPyramid = makePyramid(regl, pyramidHeight);
|
const horizontalBlurPyramid = makePyramid(regl, pyramidHeight);
|
||||||
const verticalBlurPyramid = makePyramid(regl, pyramidHeight);
|
const verticalBlurPyramid = makePyramid(regl, pyramidHeight);
|
||||||
const fbo = makePassFBO(regl);
|
const output = makePassFBO(regl);
|
||||||
|
|
||||||
// The high pass restricts the blur to bright things in our input texture.
|
// The high pass restricts the blur to bright things in our input texture.
|
||||||
const highPass = regl({
|
const highPass = regl({
|
||||||
@@ -103,11 +103,11 @@ export default (regl, config, input) => {
|
|||||||
verticalBlurPyramid.map((fbo, index) => [`tex_${index}`, fbo])
|
verticalBlurPyramid.map((fbo, index) => [`tex_${index}`, fbo])
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
framebuffer: fbo
|
framebuffer: output
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fbo,
|
output,
|
||||||
resize: (viewportWidth, viewportHeight) => {
|
resize: (viewportWidth, viewportHeight) => {
|
||||||
// The blur pyramids can be lower resolution than the screen.
|
// The blur pyramids can be lower resolution than the screen.
|
||||||
resizePyramid(
|
resizePyramid(
|
||||||
@@ -128,7 +128,7 @@ export default (regl, config, input) => {
|
|||||||
viewportHeight,
|
viewportHeight,
|
||||||
config.bloomSize
|
config.bloomSize
|
||||||
);
|
);
|
||||||
fbo.resize(viewportWidth, viewportHeight);
|
output.resize(viewportWidth, viewportHeight);
|
||||||
},
|
},
|
||||||
render: () => {
|
render: () => {
|
||||||
highPassPyramid.forEach(fbo => highPass({ fbo, tex: input }));
|
highPassPyramid.forEach(fbo => highPass({ fbo, tex: input }));
|
||||||
|
|||||||
@@ -63,20 +63,20 @@ const colorizeByStripes = regl =>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const colorizeByImage = regl =>
|
const colorizeByImage = (regl, bgTex) =>
|
||||||
regl({
|
regl({
|
||||||
frag: `
|
frag: `
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform sampler2D backgroundTex;
|
uniform sampler2D bgTex;
|
||||||
varying vec2 vUV;
|
varying vec2 vUV;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragColor = vec4(texture2D(backgroundTex, vUV).rgb * (pow(texture2D(tex, vUV).r, 1.5) * 0.995 + 0.005), 1.0);
|
gl_FragColor = vec4(texture2D(bgTex, vUV).rgb * (pow(texture2D(tex, vUV).r, 1.5) * 0.995 + 0.005), 1.0);
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
uniforms: {
|
uniforms: {
|
||||||
backgroundTex: regl.prop("backgroundTex")
|
bgTex
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -87,35 +87,35 @@ const colorizersByEffect = {
|
|||||||
image: colorizeByImage
|
image: colorizeByImage
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (regl, config, inputFBO) => {
|
export default (regl, config, { bgTex }, input) => {
|
||||||
const fbo = makePassFBO(regl);
|
|
||||||
|
|
||||||
if (config.effect === "none") {
|
if (config.effect === "none") {
|
||||||
return {
|
return {
|
||||||
fbo: inputFBO,
|
output: input,
|
||||||
resize: () => {},
|
resize: () => {},
|
||||||
render: () => {}
|
render: () => {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const output = makePassFBO(regl);
|
||||||
|
|
||||||
const colorize = regl({
|
const colorize = regl({
|
||||||
uniforms: {
|
uniforms: {
|
||||||
tex: regl.prop("tex")
|
tex: regl.prop("tex")
|
||||||
},
|
},
|
||||||
framebuffer: fbo
|
framebuffer: output
|
||||||
});
|
});
|
||||||
|
|
||||||
const colorizer = (config.effect in colorizersByEffect
|
const colorizer = (config.effect in colorizersByEffect
|
||||||
? colorizersByEffect[config.effect]
|
? colorizersByEffect[config.effect]
|
||||||
: colorizeByPalette)(regl);
|
: colorizeByPalette)(regl, bgTex);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fbo,
|
output,
|
||||||
resize: fbo.resize,
|
resize: output.resize,
|
||||||
render: resources => {
|
render: resources => {
|
||||||
colorize(
|
colorize(
|
||||||
{
|
{
|
||||||
tex: inputFBO
|
tex: input
|
||||||
},
|
},
|
||||||
() => colorizer(resources)
|
() => colorizer(resources)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ export default (searchString, makePaletteTexture) => {
|
|||||||
config.animationSpeed * config.fallSpeed == 0
|
config.animationSpeed * config.fallSpeed == 0
|
||||||
? 1
|
? 1
|
||||||
: Math.min(1, Math.abs(config.animationSpeed * config.fallSpeed));
|
: Math.min(1, Math.abs(config.animationSpeed * config.fallSpeed));
|
||||||
config.backgroundImage = getParam(
|
config.bgURL = getParam(
|
||||||
"url",
|
"url",
|
||||||
"https://upload.wikimedia.org/wikipedia/commons/0/0a/Flammarion_Colored.jpg"
|
"https://upload.wikimedia.org/wikipedia/commons/0/0a/Flammarion_Colored.jpg"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,20 @@
|
|||||||
import { makePassFBO } from "./utils.js";
|
import { makePassFBO, makeDoubleBuffer } from "./utils.js";
|
||||||
|
|
||||||
export default (regl, config) => {
|
export default (regl, config, { msdfTex }) => {
|
||||||
// These two framebuffers are used to compute the raining code.
|
// These two framebuffers are used to compute the raining code.
|
||||||
// they take turns being the source and destination of the "compute" shader.
|
// they take turns being the source and destination of the "compute" shader.
|
||||||
// The half float data type is crucial! It lets us store almost any real number,
|
// The half float data type is crucial! It lets us store almost any real number,
|
||||||
// whereas the default type limits us to integers between 0 and 255.
|
// whereas the default type limits us to integers between 0 and 255.
|
||||||
|
|
||||||
// These FBOs are smaller than the screen, because their pixels correspond
|
// This double buffer is smaller than the screen, because its pixels correspond
|
||||||
// with glyphs in the final image, and the glyphs are much larger than a pixel.
|
// with glyphs in the final image, and the glyphs are much larger than a pixel.
|
||||||
const state = Array(2)
|
const doubleBuffer = makeDoubleBuffer(regl, {
|
||||||
.fill()
|
radius: config.numColumns,
|
||||||
.map(() =>
|
wrapT: "clamp",
|
||||||
regl.framebuffer({
|
type: "half float"
|
||||||
color: regl.texture({
|
});
|
||||||
radius: config.numColumns,
|
|
||||||
wrapT: "clamp",
|
|
||||||
type: "half float"
|
|
||||||
}),
|
|
||||||
depthStencil: false
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const fbo = makePassFBO(regl);
|
const output = makePassFBO(regl);
|
||||||
|
|
||||||
const update = regl({
|
const update = regl({
|
||||||
frag: `
|
frag: `
|
||||||
@@ -195,10 +188,10 @@ export default (regl, config) => {
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
uniforms: {
|
uniforms: {
|
||||||
lastState: ({ tick }) => state[tick % 2]
|
lastState: doubleBuffer.back
|
||||||
},
|
},
|
||||||
|
|
||||||
framebuffer: ({ tick }) => state[(tick + 1) % 2] // The crucial state FBO alternator
|
framebuffer: doubleBuffer.front
|
||||||
});
|
});
|
||||||
|
|
||||||
// We render the code into an FBO using MSDFs: https://github.com/Chlumsky/msdfgen
|
// We render the code into an FBO using MSDFs: https://github.com/Chlumsky/msdfgen
|
||||||
@@ -290,19 +283,21 @@ export default (regl, config) => {
|
|||||||
`,
|
`,
|
||||||
|
|
||||||
uniforms: {
|
uniforms: {
|
||||||
msdfTex: regl.prop("msdfTex"),
|
msdfTex,
|
||||||
height: regl.context("viewportWidth"),
|
height: regl.context("viewportWidth"),
|
||||||
width: regl.context("viewportHeight"),
|
width: regl.context("viewportHeight"),
|
||||||
lastState: ({ tick }) => state[tick % 2]
|
lastState: doubleBuffer.front
|
||||||
},
|
},
|
||||||
|
|
||||||
framebuffer: fbo
|
framebuffer: output
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
resize: fbo.resize,
|
resize: output.resize,
|
||||||
fbo,
|
output,
|
||||||
update,
|
render: resources => {
|
||||||
render
|
update();
|
||||||
|
render(resources);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
20
js/utils.js
20
js/utils.js
@@ -17,6 +17,21 @@ const makePyramid = (regl, height) =>
|
|||||||
.fill()
|
.fill()
|
||||||
.map(_ => makePassFBO(regl));
|
.map(_ => makePassFBO(regl));
|
||||||
|
|
||||||
|
const makeDoubleBuffer = (regl, props) => {
|
||||||
|
const state = Array(2)
|
||||||
|
.fill()
|
||||||
|
.map(() =>
|
||||||
|
regl.framebuffer({
|
||||||
|
color: regl.texture(props),
|
||||||
|
depthStencil: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
front: ({ tick }) => state[tick % 2],
|
||||||
|
back: ({ tick }) => state[(tick + 1) % 2]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const resizePyramid = (pyramid, vw, vh, scale) =>
|
const resizePyramid = (pyramid, vw, vh, scale) =>
|
||||||
pyramid.forEach((fbo, index) =>
|
pyramid.forEach((fbo, index) =>
|
||||||
fbo.resize(
|
fbo.resize(
|
||||||
@@ -48,7 +63,7 @@ const loadImage = async (regl, url) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeFullScreenQuad = (regl, uniforms) =>
|
const makeFullScreenQuad = (regl, uniforms = {}, context = {}) =>
|
||||||
regl({
|
regl({
|
||||||
vert: `
|
vert: `
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
@@ -78,6 +93,8 @@ const makeFullScreenQuad = (regl, uniforms) =>
|
|||||||
time: regl.context("time")
|
time: regl.context("time")
|
||||||
},
|
},
|
||||||
|
|
||||||
|
context,
|
||||||
|
|
||||||
depth: { enable: false },
|
depth: { enable: false },
|
||||||
count: 3
|
count: 3
|
||||||
});
|
});
|
||||||
@@ -95,6 +112,7 @@ const makePalette = (regl, data) =>
|
|||||||
export {
|
export {
|
||||||
makePassTexture,
|
makePassTexture,
|
||||||
makePassFBO,
|
makePassFBO,
|
||||||
|
makeDoubleBuffer,
|
||||||
makePyramid,
|
makePyramid,
|
||||||
resizePyramid,
|
resizePyramid,
|
||||||
loadImage,
|
loadImage,
|
||||||
|
|||||||
Reference in New Issue
Block a user