More cleanup

This commit is contained in:
Rezmason
2020-01-22 08:31:13 -08:00
parent 1d629a20c4
commit cadd769b63
6 changed files with 75 additions and 71 deletions

View File

@@ -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();
}); });
}); });

View File

@@ -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 }));

View File

@@ -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)
); );

View File

@@ -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"
); );

View File

@@ -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);
}
}; };
}; };

View File

@@ -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,