Came up with some performance improvements. Hopefully this will help it run better on more machines leading up to the sequel coming out.

This commit is contained in:
Rezmason
2021-07-11 18:18:13 -07:00
parent d094f7e0b7
commit 6708ab03a7
8 changed files with 40 additions and 24 deletions

View File

@@ -22,10 +22,10 @@ export default (regl, config, inputs) => {
"highPassThreshold" "highPassThreshold"
]); ]);
const highPassPyramid = makePyramid(regl, pyramidHeight); const highPassPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat);
const hBlurPyramid = makePyramid(regl, pyramidHeight); const hBlurPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat);
const vBlurPyramid = makePyramid(regl, pyramidHeight); const vBlurPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat);
const output = makePassFBO(regl); const output = makePassFBO(regl, config.useHalfFloat);
// 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({
@@ -126,13 +126,15 @@ export default (regl, config, inputs) => {
bloom: output bloom: output
}, },
() => { () => {
highPassPyramid.forEach(fbo => highPass({ fbo, tex: inputs.primary })); for (let i = 0; i < pyramidHeight; i++) {
hBlurPyramid.forEach((fbo, index) => const highPassFBO = highPassPyramid[i];
blur({ fbo, tex: highPassPyramid[index], direction: [1, 0] }) const hBlurFBO = hBlurPyramid[i];
); const vBlurFBO = vBlurPyramid[i];
vBlurPyramid.forEach((fbo, index) => highPass({ fbo: highPassFBO, tex: inputs.primary });
blur({ fbo, tex: hBlurPyramid[index], direction: [0, 1] }) blur({ fbo: hBlurFBO, tex: highPassFBO, direction: [1, 0] });
); blur({ fbo: vBlurFBO, tex: hBlurFBO, direction: [0, 1] });
}
flattenPyramid(); flattenPyramid();
}, },
(w, h) => { (w, h) => {

View File

@@ -19,7 +19,7 @@ const fonts = {
const defaults = { const defaults = {
animationSpeed: 1, animationSpeed: 1,
bloomStrength: 1, bloomStrength: 1,
bloomSize: 0.5, bloomSize: 0.6,
highPassThreshold: 0.3, highPassThreshold: 0.3,
cycleSpeed: 1, cycleSpeed: 1,
cycleStyleName: "cycleFasterWhenDimmed", cycleStyleName: "cycleFasterWhenDimmed",
@@ -47,7 +47,8 @@ const defaults = {
], ],
raindropLength: 1, raindropLength: 1,
slant: 0, slant: 0,
resolution: 1 resolution: 1,
useHalfFloat: false,
}; };
const versions = { const versions = {

View File

@@ -4,7 +4,7 @@ const defaultBGURL =
"https://upload.wikimedia.org/wikipedia/commons/0/0a/Flammarion_Colored.jpg"; "https://upload.wikimedia.org/wikipedia/commons/0/0a/Flammarion_Colored.jpg";
export default (regl, config, inputs) => { export default (regl, config, inputs) => {
const output = makePassFBO(regl); const output = makePassFBO(regl, config.useHalfFloat);
const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL; const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL;
const bgLoader = loadImage(regl, bgURL); const bgLoader = loadImage(regl, bgURL);
return makePass( return makePass(

View File

@@ -43,6 +43,8 @@ const resize = () => {
window.onresize = resize; window.onresize = resize;
resize(); resize();
const dimensions = { width: 1, height: 1 };
document.body.onload = async () => { document.body.onload = async () => {
// All this takes place in a full screen quad. // All this takes place in a full screen quad.
const fullScreenQuad = makeFullScreenQuad(regl); const fullScreenQuad = makeFullScreenQuad(regl);
@@ -64,9 +66,20 @@ document.body.onload = async () => {
await Promise.all(pipeline.map(({ ready }) => ready)); await Promise.all(pipeline.map(({ ready }) => ready));
const tick = regl.frame(({ viewportWidth, viewportHeight }) => { const tick = regl.frame(({ viewportWidth, viewportHeight }) => {
// tick.cancel(); // tick.cancel();
pipeline.forEach(({ resize }) => resize(viewportWidth, viewportHeight)); if (
dimensions.width !== viewportWidth ||
dimensions.height !== viewportHeight
) {
dimensions.width = viewportWidth;
dimensions.height = viewportHeight;
for (const pass of pipeline) {
pass.resize(viewportWidth, viewportHeight);
}
}
fullScreenQuad(() => { fullScreenQuad(() => {
pipeline.forEach(({ render }) => render()); for (const pass of pipeline) {
pass.render();
}
drawToScreen(); drawToScreen();
}); });
}); });

View File

@@ -46,7 +46,7 @@ const makePalette = (regl, entries) => {
// in screen space. // in screen space.
export default (regl, config, inputs) => { export default (regl, config, inputs) => {
const output = makePassFBO(regl); const output = makePassFBO(regl, config.useHalfFloat);
const palette = makePalette(regl, config.paletteEntries); const palette = makePalette(regl, config.paletteEntries);
return makePass( return makePass(

View File

@@ -30,7 +30,7 @@ export default (regl, config) => {
type: "half float" type: "half float"
}); });
const output = makePassFBO(regl); const output = makePassFBO(regl, config.useHalfFloat);
const uniforms = extractEntries(config, [ const uniforms = extractEntries(config, [
// rain general // rain general

View File

@@ -19,7 +19,7 @@ const prideStripeColors = [
].flat(); ].flat();
export default (regl, config, inputs) => { export default (regl, config, inputs) => {
const output = makePassFBO(regl); const output = makePassFBO(regl, config.useHalfFloat);
const stripeColors = const stripeColors =
"stripeColors" in config "stripeColors" in config

View File

@@ -3,24 +3,24 @@ const extractEntries = (src, keys) =>
Array.from(Object.entries(src)).filter(([key]) => keys.includes(key)) Array.from(Object.entries(src)).filter(([key]) => keys.includes(key))
); );
const makePassTexture = regl => const makePassTexture = (regl, halfFloat) =>
regl.texture({ regl.texture({
width: 1, width: 1,
height: 1, height: 1,
type: "half float", type: halfFloat ? "half float" : "uint8",
wrap: "clamp", wrap: "clamp",
min: "linear", min: "linear",
mag: "linear" mag: "linear"
}); });
const makePassFBO = regl => regl.framebuffer({ color: makePassTexture(regl) }); const makePassFBO = (regl, halfFloat) => regl.framebuffer({ color: makePassTexture(regl, halfFloat) });
// A pyramid is just an array of FBOs, where each FBO is half the width // A pyramid is just an array of FBOs, where each FBO is half the width
// and half the height of the FBO below it. // and half the height of the FBO below it.
const makePyramid = (regl, height) => const makePyramid = (regl, height, halfFloat) =>
Array(height) Array(height)
.fill() .fill()
.map(_ => makePassFBO(regl)); .map(_ => makePassFBO(regl, halfFloat));
const makeDoubleBuffer = (regl, props) => { const makeDoubleBuffer = (regl, props) => {
const state = Array(2) const state = Array(2)