diff --git a/js/bloomPass.js b/js/bloomPass.js index 8971bb1..2698074 100644 --- a/js/bloomPass.js +++ b/js/bloomPass.js @@ -22,10 +22,10 @@ export default (regl, config, inputs) => { "highPassThreshold" ]); - const highPassPyramid = makePyramid(regl, pyramidHeight); - const hBlurPyramid = makePyramid(regl, pyramidHeight); - const vBlurPyramid = makePyramid(regl, pyramidHeight); - const output = makePassFBO(regl); + const highPassPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat); + const hBlurPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat); + const vBlurPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat); + const output = makePassFBO(regl, config.useHalfFloat); // The high pass restricts the blur to bright things in our input texture. const highPass = regl({ @@ -126,13 +126,15 @@ export default (regl, config, inputs) => { bloom: output }, () => { - highPassPyramid.forEach(fbo => highPass({ fbo, tex: inputs.primary })); - hBlurPyramid.forEach((fbo, index) => - blur({ fbo, tex: highPassPyramid[index], direction: [1, 0] }) - ); - vBlurPyramid.forEach((fbo, index) => - blur({ fbo, tex: hBlurPyramid[index], direction: [0, 1] }) - ); + for (let i = 0; i < pyramidHeight; i++) { + const highPassFBO = highPassPyramid[i]; + const hBlurFBO = hBlurPyramid[i]; + const vBlurFBO = vBlurPyramid[i]; + highPass({ fbo: highPassFBO, tex: inputs.primary }); + blur({ fbo: hBlurFBO, tex: highPassFBO, direction: [1, 0] }); + blur({ fbo: vBlurFBO, tex: hBlurFBO, direction: [0, 1] }); + } + flattenPyramid(); }, (w, h) => { diff --git a/js/config.js b/js/config.js index ad10fa0..72b1d53 100644 --- a/js/config.js +++ b/js/config.js @@ -19,7 +19,7 @@ const fonts = { const defaults = { animationSpeed: 1, bloomStrength: 1, - bloomSize: 0.5, + bloomSize: 0.6, highPassThreshold: 0.3, cycleSpeed: 1, cycleStyleName: "cycleFasterWhenDimmed", @@ -47,7 +47,8 @@ const defaults = { ], raindropLength: 1, slant: 0, - resolution: 1 + resolution: 1, + useHalfFloat: false, }; const versions = { diff --git a/js/imagePass.js b/js/imagePass.js index 5e2142a..cee672e 100644 --- a/js/imagePass.js +++ b/js/imagePass.js @@ -4,7 +4,7 @@ const defaultBGURL = "https://upload.wikimedia.org/wikipedia/commons/0/0a/Flammarion_Colored.jpg"; export default (regl, config, inputs) => { - const output = makePassFBO(regl); + const output = makePassFBO(regl, config.useHalfFloat); const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL; const bgLoader = loadImage(regl, bgURL); return makePass( diff --git a/js/main.js b/js/main.js index b942767..8838fe1 100644 --- a/js/main.js +++ b/js/main.js @@ -43,6 +43,8 @@ const resize = () => { window.onresize = resize; resize(); +const dimensions = { width: 1, height: 1 }; + document.body.onload = async () => { // All this takes place in a full screen quad. const fullScreenQuad = makeFullScreenQuad(regl); @@ -64,9 +66,20 @@ document.body.onload = async () => { await Promise.all(pipeline.map(({ ready }) => ready)); const tick = regl.frame(({ viewportWidth, viewportHeight }) => { // 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(() => { - pipeline.forEach(({ render }) => render()); + for (const pass of pipeline) { + pass.render(); + } drawToScreen(); }); }); diff --git a/js/palettePass.js b/js/palettePass.js index 3ba069f..9236a16 100644 --- a/js/palettePass.js +++ b/js/palettePass.js @@ -46,7 +46,7 @@ const makePalette = (regl, entries) => { // in screen space. export default (regl, config, inputs) => { - const output = makePassFBO(regl); + const output = makePassFBO(regl, config.useHalfFloat); const palette = makePalette(regl, config.paletteEntries); return makePass( diff --git a/js/renderer.js b/js/renderer.js index 95f0bf7..148f55e 100644 --- a/js/renderer.js +++ b/js/renderer.js @@ -30,7 +30,7 @@ export default (regl, config) => { type: "half float" }); - const output = makePassFBO(regl); + const output = makePassFBO(regl, config.useHalfFloat); const uniforms = extractEntries(config, [ // rain general diff --git a/js/stripePass.js b/js/stripePass.js index f4a0ed1..be5fd2b 100644 --- a/js/stripePass.js +++ b/js/stripePass.js @@ -19,7 +19,7 @@ const prideStripeColors = [ ].flat(); export default (regl, config, inputs) => { - const output = makePassFBO(regl); + const output = makePassFBO(regl, config.useHalfFloat); const stripeColors = "stripeColors" in config diff --git a/js/utils.js b/js/utils.js index 1d224b5..9c11e7a 100644 --- a/js/utils.js +++ b/js/utils.js @@ -3,24 +3,24 @@ const extractEntries = (src, keys) => Array.from(Object.entries(src)).filter(([key]) => keys.includes(key)) ); -const makePassTexture = regl => +const makePassTexture = (regl, halfFloat) => regl.texture({ width: 1, height: 1, - type: "half float", + type: halfFloat ? "half float" : "uint8", wrap: "clamp", min: "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 // and half the height of the FBO below it. -const makePyramid = (regl, height) => +const makePyramid = (regl, height, halfFloat) => Array(height) .fill() - .map(_ => makePassFBO(regl)); + .map(_ => makePassFBO(regl, halfFloat)); const makeDoubleBuffer = (regl, props) => { const state = Array(2)