diff --git a/TODO.txt b/TODO.txt index 30718f4..b0dd5d5 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,18 +1,6 @@ TODO: -Bloom comparison: WebGPU vs REGL - Why are they different? - Create a project that tests them side-by-side - That's right, two canvases, one regl and one webgpu - program them both to do the same basic ops in a floating point texture - display that texture - Retrieve the texture from the GPU and spit it out - Possible causes of difference - Color space - Intermediate texture formats around high pass filter - Floating point math - Texture interpolation - Blur implementation +Seems like bloom size and resolution impact the REGL and WebGPU bloom implementations differently Audio system Toggle (or number representing frequency) diff --git a/js/regl/imagePass.js b/js/regl/imagePass.js index fb3765a..f78106f 100644 --- a/js/regl/imagePass.js +++ b/js/regl/imagePass.js @@ -7,13 +7,11 @@ const defaultBGURL = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/ export default ({ regl, config }, inputs) => { const output = makePassFBO(regl, config.useHalfFloat); const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL; - const bloomStrength = config.bloomStrength; const background = loadImage(regl, bgURL); const imagePassFrag = loadText("shaders/glsl/imagePass.frag.glsl"); const render = regl({ frag: regl.prop("frag"), uniforms: { - bloomStrength, backgroundTex: background.texture, tex: inputs.primary, bloomTex: inputs.bloom, diff --git a/js/regl/palettePass.js b/js/regl/palettePass.js index 2a24cc0..4a3c31a 100644 --- a/js/regl/palettePass.js +++ b/js/regl/palettePass.js @@ -57,7 +57,7 @@ const makePalette = (regl, entries) => { export default ({ regl, config }, inputs) => { const output = makePassFBO(regl, config.useHalfFloat); const paletteTex = makePalette(regl, config.palette); - const { backgroundColor, cursorColor, glintColor, ditherMagnitude, bloomStrength } = config; + const { backgroundColor, cursorColor, glintColor, ditherMagnitude } = config; const palettePassFrag = loadText("shaders/glsl/palettePass.frag.glsl"); @@ -69,7 +69,6 @@ export default ({ regl, config }, inputs) => { cursorColor: colorToRGB(cursorColor), glintColor: colorToRGB(glintColor), ditherMagnitude, - bloomStrength, tex: inputs.primary, bloomTex: inputs.bloom, paletteTex, diff --git a/js/regl/stripePass.js b/js/regl/stripePass.js index cdd7084..1c75911 100644 --- a/js/regl/stripePass.js +++ b/js/regl/stripePass.js @@ -30,7 +30,7 @@ const prideStripeColors = [ export default ({ regl, config }, inputs) => { const output = makePassFBO(regl, config.useHalfFloat); - const { backgroundColor, cursorColor, glintColor, ditherMagnitude, bloomStrength } = config; + const { backgroundColor, cursorColor, glintColor, ditherMagnitude } = config; // Expand and convert stripe colors into 1D texture data const stripeColors = "stripeColors" in config ? config.stripeColors : config.effect === "pride" ? prideStripeColors : transPrideStripeColors; @@ -49,7 +49,6 @@ export default ({ regl, config }, inputs) => { cursorColor: colorToRGB(cursorColor), glintColor: colorToRGB(glintColor), ditherMagnitude, - bloomStrength, tex: inputs.primary, bloomTex: inputs.bloom, stripeTex, diff --git a/js/webgpu/bloomPass.js b/js/webgpu/bloomPass.js index 06d1b29..78c3a4e 100644 --- a/js/webgpu/bloomPass.js +++ b/js/webgpu/bloomPass.js @@ -20,7 +20,7 @@ const makePyramid = (device, size, pyramidHeight) => .map((_, index) => makeComputeTarget( device, - size.map((x) => Math.floor(x * 2 ** -(index + 1))) + size.map((x) => Math.floor(x * 2 ** -index)) ) ); @@ -97,7 +97,7 @@ export default ({ config, device }) => { vBlurBuffer = makeUniformBuffer(device, blurUniforms, { bloomRadius, direction: [0, 1] }); const combineUniforms = structs.from(combineShader.code).Config; - combineBuffer = makeUniformBuffer(device, combineUniforms, { pyramidHeight }); + combineBuffer = makeUniformBuffer(device, combineUniforms, { pyramidHeight, bloomStrength }); })(); const build = (screenSize, inputs) => { diff --git a/js/webgpu/imagePass.js b/js/webgpu/imagePass.js index 6626ad2..ee859de 100644 --- a/js/webgpu/imagePass.js +++ b/js/webgpu/imagePass.js @@ -35,7 +35,7 @@ export default ({ config, device }) => { }); const configUniforms = structs.from(imageShader.code).Config; - configBuffer = makeUniformBuffer(device, configUniforms, { bloomStrength: config.bloomStrength }); + configBuffer = makeUniformBuffer(device, configUniforms, { unused: 0 }); })(); const build = (size, inputs) => { diff --git a/js/webgpu/mirrorPass.js b/js/webgpu/mirrorPass.js index 7b8d4b9..9de12af 100644 --- a/js/webgpu/mirrorPass.js +++ b/js/webgpu/mirrorPass.js @@ -50,7 +50,7 @@ export default ({ config, device, cameraTex, cameraAspectRatio, timeBuffer }) => const mirrorShaderUniforms = structs.from(mirrorShader.code); const configUniforms = mirrorShaderUniforms.Config; - configBuffer = makeUniformBuffer(device, configUniforms, { bloomStrength: config.bloomStrength }); + configBuffer = makeUniformBuffer(device, configUniforms, { unused: 0 }); sceneUniforms = mirrorShaderUniforms.Scene; sceneBuffer = makeUniformBuffer(device, sceneUniforms); diff --git a/js/webgpu/palettePass.js b/js/webgpu/palettePass.js index 544e210..2550db0 100644 --- a/js/webgpu/palettePass.js +++ b/js/webgpu/palettePass.js @@ -96,7 +96,6 @@ export default ({ config, device, timeBuffer }) => { const paletteShaderUniforms = structs.from(paletteShader.code); const configUniforms = paletteShaderUniforms.Config; configBuffer = makeUniformBuffer(device, configUniforms, { - bloomStrength: config.bloomStrength, ditherMagnitude: config.ditherMagnitude, backgroundColor: colorToRGB(config.backgroundColor), cursorColor: colorToRGB(config.cursorColor), diff --git a/js/webgpu/stripePass.js b/js/webgpu/stripePass.js index e59092b..972b223 100644 --- a/js/webgpu/stripePass.js +++ b/js/webgpu/stripePass.js @@ -71,7 +71,6 @@ export default ({ config, device, timeBuffer }) => { const configUniforms = structs.from(stripeShader.code).Config; configBuffer = makeUniformBuffer(device, configUniforms, { - bloomStrength: config.bloomStrength, ditherMagnitude: config.ditherMagnitude, backgroundColor: colorToRGB(config.backgroundColor), cursorColor: colorToRGB(config.cursorColor), diff --git a/shaders/glsl/imagePass.frag.glsl b/shaders/glsl/imagePass.frag.glsl index 397f94f..1de22d6 100644 --- a/shaders/glsl/imagePass.frag.glsl +++ b/shaders/glsl/imagePass.frag.glsl @@ -2,13 +2,12 @@ precision mediump float; uniform sampler2D tex; uniform sampler2D bloomTex; uniform sampler2D backgroundTex; -uniform float bloomStrength; varying vec2 vUV; vec4 getBrightness(vec2 uv) { vec4 primary = texture2D(tex, uv); - vec4 bloom = texture2D(bloomTex, uv) * bloomStrength; - return min((primary + bloom) * (2.0 - bloomStrength), 1.0); + vec4 bloom = texture2D(bloomTex, uv); + return primary + bloom; } void main() { diff --git a/shaders/glsl/palettePass.frag.glsl b/shaders/glsl/palettePass.frag.glsl index 4d32b88..148bdef 100644 --- a/shaders/glsl/palettePass.frag.glsl +++ b/shaders/glsl/palettePass.frag.glsl @@ -4,7 +4,6 @@ precision mediump float; uniform sampler2D tex; uniform sampler2D bloomTex; uniform sampler2D paletteTex; -uniform float bloomStrength; uniform float ditherMagnitude; uniform float time; uniform vec3 backgroundColor, cursorColor, glintColor; @@ -18,8 +17,8 @@ highp float rand( const in vec2 uv, const in float t ) { vec4 getBrightness(vec2 uv) { vec4 primary = texture2D(tex, uv); - vec4 bloom = texture2D(bloomTex, uv) * bloomStrength; - return min((primary + bloom) * (2.0 - bloomStrength), 1.0); + vec4 bloom = texture2D(bloomTex, uv); + return primary + bloom; } void main() { diff --git a/shaders/glsl/stripePass.frag.glsl b/shaders/glsl/stripePass.frag.glsl index 2143404..da96760 100644 --- a/shaders/glsl/stripePass.frag.glsl +++ b/shaders/glsl/stripePass.frag.glsl @@ -3,7 +3,6 @@ precision mediump float; uniform sampler2D tex; uniform sampler2D bloomTex; -uniform float bloomStrength; uniform sampler2D stripeTex; uniform float ditherMagnitude; uniform float time; @@ -18,8 +17,8 @@ highp float rand( const in vec2 uv, const in float t ) { vec4 getBrightness(vec2 uv) { vec4 primary = texture2D(tex, uv); - vec4 bloom = texture2D(bloomTex, uv) * bloomStrength; - return min((primary + bloom) * (2.0 - bloomStrength), 1.0); + vec4 bloom = texture2D(bloomTex, uv); + return primary + bloom; } void main() { diff --git a/shaders/wgsl/bloomCombine.wgsl b/shaders/wgsl/bloomCombine.wgsl index 027f6c9..68f7580 100644 --- a/shaders/wgsl/bloomCombine.wgsl +++ b/shaders/wgsl/bloomCombine.wgsl @@ -1,5 +1,6 @@ struct Config { pyramidHeight : f32, + bloomStrength : f32 }; @group(0) @binding(0) var config : Config; @@ -62,5 +63,5 @@ struct ComputeInput { sum += textureSampleLevel( tex4, linearSampler, uv, i + 1.0 ) * weight; } - textureStore(outputTex, coord, sum); + textureStore(outputTex, coord, sum * config.bloomStrength); } diff --git a/shaders/wgsl/imagePass.wgsl b/shaders/wgsl/imagePass.wgsl index 8aeb477..b2e3bb9 100644 --- a/shaders/wgsl/imagePass.wgsl +++ b/shaders/wgsl/imagePass.wgsl @@ -1,5 +1,5 @@ struct Config { - bloomStrength : f32, + unused : f32, }; @group(0) @binding(0) var config : Config; @@ -15,12 +15,14 @@ struct ComputeInput { fn getBrightness(uv : vec2) -> vec4 { var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); - var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0) * config.bloomStrength; - return min((primary + bloom) * (2.0 - config.bloomStrength), vec4(1.0)); + var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0); + return primary + bloom; } @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { + var unused = config.unused; + // Resolve the invocation ID to a texel coordinate var coord = vec2(input.id.xy); var screenSize = textureDimensions(tex); diff --git a/shaders/wgsl/mirrorPass.wgsl b/shaders/wgsl/mirrorPass.wgsl index 7604e17..b9f37d3 100644 --- a/shaders/wgsl/mirrorPass.wgsl +++ b/shaders/wgsl/mirrorPass.wgsl @@ -1,5 +1,5 @@ struct Config { - bloomStrength : f32, + unused : f32, }; struct Time { @@ -33,13 +33,15 @@ struct ComputeInput { fn getBrightness(uv : vec2, intensity : f32) -> vec4 { var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); - var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0) * config.bloomStrength; + var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0); return primary * (1.0 + intensity * 0.3) + bloom * 0.5; } @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { + var unused = config.unused; + // Resolve the invocation ID to a texel coordinate var coord = vec2(input.id.xy); var screenSize = textureDimensions(tex); diff --git a/shaders/wgsl/palettePass.wgsl b/shaders/wgsl/palettePass.wgsl index d46365e..2ad8455 100644 --- a/shaders/wgsl/palettePass.wgsl +++ b/shaders/wgsl/palettePass.wgsl @@ -1,5 +1,4 @@ struct Config { - bloomStrength : f32, ditherMagnitude : f32, backgroundColor : vec3, cursorColor : vec3, @@ -40,8 +39,8 @@ fn randomFloat( uv : vec2 ) -> f32 { fn getBrightness(uv : vec2) -> vec4 { var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); - var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0) * config.bloomStrength; - return min((primary + bloom) * (2.0 - config.bloomStrength), vec4(1.0)); + var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0); + return primary + bloom; } @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { diff --git a/shaders/wgsl/stripePass.wgsl b/shaders/wgsl/stripePass.wgsl index 38c6726..5bd9ed2 100644 --- a/shaders/wgsl/stripePass.wgsl +++ b/shaders/wgsl/stripePass.wgsl @@ -1,5 +1,4 @@ struct Config { - bloomStrength : f32, ditherMagnitude : f32, backgroundColor : vec3, cursorColor : vec3, @@ -36,8 +35,8 @@ fn randomFloat( uv : vec2 ) -> f32 { fn getBrightness(uv : vec2) -> vec4 { var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); - var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0) * config.bloomStrength; - return min((primary + bloom) * (2.0 - config.bloomStrength), vec4(1.0)); + var bloom = textureSampleLevel(bloomTex, linearSampler, uv, 0.0); + return primary + bloom; } @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {