Moving bloom strength math to the combine steps, and fixing a redundant multiply issue in the REGL based renderer

This commit is contained in:
Rezmason
2022-10-04 21:53:53 -07:00
parent 507f907096
commit 3843dd90d1
17 changed files with 28 additions and 46 deletions

View File

@@ -1,18 +1,6 @@
TODO: TODO:
Bloom comparison: WebGPU vs REGL Seems like bloom size and resolution impact the REGL and WebGPU bloom implementations differently
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
Audio system Audio system
Toggle (or number representing frequency) Toggle (or number representing frequency)

View File

@@ -7,13 +7,11 @@ const defaultBGURL = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/
export default ({ regl, config }, inputs) => { export default ({ regl, config }, inputs) => {
const output = makePassFBO(regl, config.useHalfFloat); const output = makePassFBO(regl, config.useHalfFloat);
const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL; const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL;
const bloomStrength = config.bloomStrength;
const background = loadImage(regl, bgURL); const background = loadImage(regl, bgURL);
const imagePassFrag = loadText("shaders/glsl/imagePass.frag.glsl"); const imagePassFrag = loadText("shaders/glsl/imagePass.frag.glsl");
const render = regl({ const render = regl({
frag: regl.prop("frag"), frag: regl.prop("frag"),
uniforms: { uniforms: {
bloomStrength,
backgroundTex: background.texture, backgroundTex: background.texture,
tex: inputs.primary, tex: inputs.primary,
bloomTex: inputs.bloom, bloomTex: inputs.bloom,

View File

@@ -57,7 +57,7 @@ const makePalette = (regl, entries) => {
export default ({ regl, config }, inputs) => { export default ({ regl, config }, inputs) => {
const output = makePassFBO(regl, config.useHalfFloat); const output = makePassFBO(regl, config.useHalfFloat);
const paletteTex = makePalette(regl, config.palette); 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"); const palettePassFrag = loadText("shaders/glsl/palettePass.frag.glsl");
@@ -69,7 +69,6 @@ export default ({ regl, config }, inputs) => {
cursorColor: colorToRGB(cursorColor), cursorColor: colorToRGB(cursorColor),
glintColor: colorToRGB(glintColor), glintColor: colorToRGB(glintColor),
ditherMagnitude, ditherMagnitude,
bloomStrength,
tex: inputs.primary, tex: inputs.primary,
bloomTex: inputs.bloom, bloomTex: inputs.bloom,
paletteTex, paletteTex,

View File

@@ -30,7 +30,7 @@ const prideStripeColors = [
export default ({ regl, config }, inputs) => { export default ({ regl, config }, inputs) => {
const output = makePassFBO(regl, config.useHalfFloat); 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 // Expand and convert stripe colors into 1D texture data
const stripeColors = "stripeColors" in config ? config.stripeColors : config.effect === "pride" ? prideStripeColors : transPrideStripeColors; const stripeColors = "stripeColors" in config ? config.stripeColors : config.effect === "pride" ? prideStripeColors : transPrideStripeColors;
@@ -49,7 +49,6 @@ export default ({ regl, config }, inputs) => {
cursorColor: colorToRGB(cursorColor), cursorColor: colorToRGB(cursorColor),
glintColor: colorToRGB(glintColor), glintColor: colorToRGB(glintColor),
ditherMagnitude, ditherMagnitude,
bloomStrength,
tex: inputs.primary, tex: inputs.primary,
bloomTex: inputs.bloom, bloomTex: inputs.bloom,
stripeTex, stripeTex,

View File

@@ -20,7 +20,7 @@ const makePyramid = (device, size, pyramidHeight) =>
.map((_, index) => .map((_, index) =>
makeComputeTarget( makeComputeTarget(
device, 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] }); vBlurBuffer = makeUniformBuffer(device, blurUniforms, { bloomRadius, direction: [0, 1] });
const combineUniforms = structs.from(combineShader.code).Config; const combineUniforms = structs.from(combineShader.code).Config;
combineBuffer = makeUniformBuffer(device, combineUniforms, { pyramidHeight }); combineBuffer = makeUniformBuffer(device, combineUniforms, { pyramidHeight, bloomStrength });
})(); })();
const build = (screenSize, inputs) => { const build = (screenSize, inputs) => {

View File

@@ -35,7 +35,7 @@ export default ({ config, device }) => {
}); });
const configUniforms = structs.from(imageShader.code).Config; const configUniforms = structs.from(imageShader.code).Config;
configBuffer = makeUniformBuffer(device, configUniforms, { bloomStrength: config.bloomStrength }); configBuffer = makeUniformBuffer(device, configUniforms, { unused: 0 });
})(); })();
const build = (size, inputs) => { const build = (size, inputs) => {

View File

@@ -50,7 +50,7 @@ export default ({ config, device, cameraTex, cameraAspectRatio, timeBuffer }) =>
const mirrorShaderUniforms = structs.from(mirrorShader.code); const mirrorShaderUniforms = structs.from(mirrorShader.code);
const configUniforms = mirrorShaderUniforms.Config; const configUniforms = mirrorShaderUniforms.Config;
configBuffer = makeUniformBuffer(device, configUniforms, { bloomStrength: config.bloomStrength }); configBuffer = makeUniformBuffer(device, configUniforms, { unused: 0 });
sceneUniforms = mirrorShaderUniforms.Scene; sceneUniforms = mirrorShaderUniforms.Scene;
sceneBuffer = makeUniformBuffer(device, sceneUniforms); sceneBuffer = makeUniformBuffer(device, sceneUniforms);

View File

@@ -96,7 +96,6 @@ export default ({ config, device, timeBuffer }) => {
const paletteShaderUniforms = structs.from(paletteShader.code); const paletteShaderUniforms = structs.from(paletteShader.code);
const configUniforms = paletteShaderUniforms.Config; const configUniforms = paletteShaderUniforms.Config;
configBuffer = makeUniformBuffer(device, configUniforms, { configBuffer = makeUniformBuffer(device, configUniforms, {
bloomStrength: config.bloomStrength,
ditherMagnitude: config.ditherMagnitude, ditherMagnitude: config.ditherMagnitude,
backgroundColor: colorToRGB(config.backgroundColor), backgroundColor: colorToRGB(config.backgroundColor),
cursorColor: colorToRGB(config.cursorColor), cursorColor: colorToRGB(config.cursorColor),

View File

@@ -71,7 +71,6 @@ export default ({ config, device, timeBuffer }) => {
const configUniforms = structs.from(stripeShader.code).Config; const configUniforms = structs.from(stripeShader.code).Config;
configBuffer = makeUniformBuffer(device, configUniforms, { configBuffer = makeUniformBuffer(device, configUniforms, {
bloomStrength: config.bloomStrength,
ditherMagnitude: config.ditherMagnitude, ditherMagnitude: config.ditherMagnitude,
backgroundColor: colorToRGB(config.backgroundColor), backgroundColor: colorToRGB(config.backgroundColor),
cursorColor: colorToRGB(config.cursorColor), cursorColor: colorToRGB(config.cursorColor),

View File

@@ -2,13 +2,12 @@ precision mediump float;
uniform sampler2D tex; uniform sampler2D tex;
uniform sampler2D bloomTex; uniform sampler2D bloomTex;
uniform sampler2D backgroundTex; uniform sampler2D backgroundTex;
uniform float bloomStrength;
varying vec2 vUV; varying vec2 vUV;
vec4 getBrightness(vec2 uv) { vec4 getBrightness(vec2 uv) {
vec4 primary = texture2D(tex, uv); vec4 primary = texture2D(tex, uv);
vec4 bloom = texture2D(bloomTex, uv) * bloomStrength; vec4 bloom = texture2D(bloomTex, uv);
return min((primary + bloom) * (2.0 - bloomStrength), 1.0); return primary + bloom;
} }
void main() { void main() {

View File

@@ -4,7 +4,6 @@ precision mediump float;
uniform sampler2D tex; uniform sampler2D tex;
uniform sampler2D bloomTex; uniform sampler2D bloomTex;
uniform sampler2D paletteTex; uniform sampler2D paletteTex;
uniform float bloomStrength;
uniform float ditherMagnitude; uniform float ditherMagnitude;
uniform float time; uniform float time;
uniform vec3 backgroundColor, cursorColor, glintColor; 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 getBrightness(vec2 uv) {
vec4 primary = texture2D(tex, uv); vec4 primary = texture2D(tex, uv);
vec4 bloom = texture2D(bloomTex, uv) * bloomStrength; vec4 bloom = texture2D(bloomTex, uv);
return min((primary + bloom) * (2.0 - bloomStrength), 1.0); return primary + bloom;
} }
void main() { void main() {

View File

@@ -3,7 +3,6 @@ precision mediump float;
uniform sampler2D tex; uniform sampler2D tex;
uniform sampler2D bloomTex; uniform sampler2D bloomTex;
uniform float bloomStrength;
uniform sampler2D stripeTex; uniform sampler2D stripeTex;
uniform float ditherMagnitude; uniform float ditherMagnitude;
uniform float time; uniform float time;
@@ -18,8 +17,8 @@ highp float rand( const in vec2 uv, const in float t ) {
vec4 getBrightness(vec2 uv) { vec4 getBrightness(vec2 uv) {
vec4 primary = texture2D(tex, uv); vec4 primary = texture2D(tex, uv);
vec4 bloom = texture2D(bloomTex, uv) * bloomStrength; vec4 bloom = texture2D(bloomTex, uv);
return min((primary + bloom) * (2.0 - bloomStrength), 1.0); return primary + bloom;
} }
void main() { void main() {

View File

@@ -1,5 +1,6 @@
struct Config { struct Config {
pyramidHeight : f32, pyramidHeight : f32,
bloomStrength : f32
}; };
@group(0) @binding(0) var<uniform> config : Config; @group(0) @binding(0) var<uniform> config : Config;
@@ -62,5 +63,5 @@ struct ComputeInput {
sum += textureSampleLevel( tex4, linearSampler, uv, i + 1.0 ) * weight; sum += textureSampleLevel( tex4, linearSampler, uv, i + 1.0 ) * weight;
} }
textureStore(outputTex, coord, sum); textureStore(outputTex, coord, sum * config.bloomStrength);
} }

View File

@@ -1,5 +1,5 @@
struct Config { struct Config {
bloomStrength : f32, unused : f32,
}; };
@group(0) @binding(0) var<uniform> config : Config; @group(0) @binding(0) var<uniform> config : Config;
@@ -15,12 +15,14 @@ struct ComputeInput {
fn getBrightness(uv : vec2<f32>) -> vec4<f32> { fn getBrightness(uv : vec2<f32>) -> vec4<f32> {
var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); 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 min((primary + bloom) * (2.0 - config.bloomStrength), vec4<f32>(1.0)); return primary + bloom;
} }
@compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {
var unused = config.unused;
// Resolve the invocation ID to a texel coordinate // Resolve the invocation ID to a texel coordinate
var coord = vec2<i32>(input.id.xy); var coord = vec2<i32>(input.id.xy);
var screenSize = textureDimensions(tex); var screenSize = textureDimensions(tex);

View File

@@ -1,5 +1,5 @@
struct Config { struct Config {
bloomStrength : f32, unused : f32,
}; };
struct Time { struct Time {
@@ -33,13 +33,15 @@ struct ComputeInput {
fn getBrightness(uv : vec2<f32>, intensity : f32) -> vec4<f32> { fn getBrightness(uv : vec2<f32>, intensity : f32) -> vec4<f32> {
var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); 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; return primary * (1.0 + intensity * 0.3) + bloom * 0.5;
} }
@compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {
var unused = config.unused;
// Resolve the invocation ID to a texel coordinate // Resolve the invocation ID to a texel coordinate
var coord = vec2<i32>(input.id.xy); var coord = vec2<i32>(input.id.xy);
var screenSize = textureDimensions(tex); var screenSize = textureDimensions(tex);

View File

@@ -1,5 +1,4 @@
struct Config { struct Config {
bloomStrength : f32,
ditherMagnitude : f32, ditherMagnitude : f32,
backgroundColor : vec3<f32>, backgroundColor : vec3<f32>,
cursorColor : vec3<f32>, cursorColor : vec3<f32>,
@@ -40,8 +39,8 @@ fn randomFloat( uv : vec2<f32> ) -> f32 {
fn getBrightness(uv : vec2<f32>) -> vec4<f32> { fn getBrightness(uv : vec2<f32>) -> vec4<f32> {
var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); 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 min((primary + bloom) * (2.0 - config.bloomStrength), vec4<f32>(1.0)); return primary + bloom;
} }
@compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {

View File

@@ -1,5 +1,4 @@
struct Config { struct Config {
bloomStrength : f32,
ditherMagnitude : f32, ditherMagnitude : f32,
backgroundColor : vec3<f32>, backgroundColor : vec3<f32>,
cursorColor : vec3<f32>, cursorColor : vec3<f32>,
@@ -36,8 +35,8 @@ fn randomFloat( uv : vec2<f32> ) -> f32 {
fn getBrightness(uv : vec2<f32>) -> vec4<f32> { fn getBrightness(uv : vec2<f32>) -> vec4<f32> {
var primary = textureSampleLevel(tex, linearSampler, uv, 0.0); 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 min((primary + bloom) * (2.0 - config.bloomStrength), vec4<f32>(1.0)); return primary + bloom;
} }
@compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) { @compute @workgroup_size(32, 1, 1) fn computeMain(input : ComputeInput) {