10 threshold_precomputations: vec4<f32>, 16@group(0) @binding(0) var input_texture: texture_2d<f32>; 17@group(0) @binding(1) var s: sampler; 19@group(0) @binding(2) var<uniform> uniforms: BloomUniforms; 21#ifdef FIRST_DOWNSAMPLE 23fn soft_threshold(color: vec3<f32>) -> vec3<f32> { 24 let brightness = max(color.r, max(color.g, color.b)); 25 var softness = brightness - uniforms.threshold_precomputations.y; 26 softness = clamp(softness, 0.0, uniforms.threshold_precomputations.z); 27 softness = softness * softness * uniforms.threshold_precomputations.w; 28 var contribution = max(brightness - uniforms.threshold_precomputations.x, softness); 29 contribution /= max(brightness, 0.00001); 30 return color * contribution; 36fn tonemapping_luminance(v: vec3<f32>) -> f32 { 37 return dot(v, vec3<f32>(0.2126, 0.7152, 0.0722)); 40fn rgb_to_srgb_simple(color: vec3<f32>) -> vec3<f32> { 41 return pow(color, vec3<f32>(1.0 / 2.2)); 45fn karis_average(color: vec3<f32>) -> f32 { 48 let luma = tonemapping_luminance(rgb_to_srgb_simple(color)) / 4.0; 49 return 1.0 / (1.0 + luma); 53fn sample_input_13_tap(uv: vec2<f32>) -> vec3<f32> { 62 let a = textureSample(input_texture, s, uv, vec2<i32>(-2, 2)).rgb; 63 let b = textureSample(input_texture, s, uv, vec2<i32>(0, 2)).rgb; 64 let c = textureSample(input_texture, s, uv, vec2<i32>(2, 2)).rgb; 65 let d = textureSample(input_texture, s, uv, vec2<i32>(-2, 0)).rgb; 66 let e = textureSample(input_texture, s, uv).rgb; 67 let f = textureSample(input_texture, s, uv, vec2<i32>(2, 0)).rgb; 68 let g = textureSample(input_texture, s, uv, vec2<i32>(-2, -2)).rgb; 69 let h = textureSample(input_texture, s, uv, vec2<i32>(0, -2)).rgb; 70 let i = textureSample(input_texture, s, uv, vec2<i32>(2, -2)).rgb; 71 let j = textureSample(input_texture, s, uv, vec2<i32>(-1, 1)).rgb; 72 let k = textureSample(input_texture, s, uv, vec2<i32>(1, 1)).rgb; 73 let l = textureSample(input_texture, s, uv, vec2<i32>(-1, -1)).rgb; 74 let m = textureSample(input_texture, s, uv, vec2<i32>(1, -1)).rgb; 85 let scale = uniforms.scale; 86 let ps = scale / vec2<f32>(textureDimensions(input_texture)); 90 let a = textureSample(input_texture, s, uv + vec2<f32>(nl.x, pl.y)).rgb; 91 let b = textureSample(input_texture, s, uv + vec2<f32>(0.00, pl.y)).rgb; 92 let c = textureSample(input_texture, s, uv + vec2<f32>(pl.x, pl.y)).rgb; 93 let d = textureSample(input_texture, s, uv + vec2<f32>(nl.x, 0.00)).rgb; 94 let e = textureSample(input_texture, s, uv).rgb; 95 let f = textureSample(input_texture, s, uv + vec2<f32>(pl.x, 0.00)).rgb; 96 let g = textureSample(input_texture, s, uv + vec2<f32>(nl.x, nl.y)).rgb; 97 let h = textureSample(input_texture, s, uv + vec2<f32>(0.00, nl.y)).rgb; 98 let i = textureSample(input_texture, s, uv + vec2<f32>(pl.x, nl.y)).rgb; 99 let j = textureSample(input_texture, s, uv + vec2<f32>(ns.x, ps.y)).rgb; 100 let k = textureSample(input_texture, s, uv + vec2<f32>(ps.x, ps.y)).rgb; 101 let l = textureSample(input_texture, s, uv + vec2<f32>(ns.x, ns.y)).rgb; 102 let m = textureSample(input_texture, s, uv + vec2<f32>(ps.x, ns.y)).rgb; 105#ifdef FIRST_DOWNSAMPLE 114 var group0 = (a + b + d + e) * (0.125f / 4.0f); 115 var group1 = (b + c + e + f) * (0.125f / 4.0f); 116 var group2 = (d + e + g + h) * (0.125f / 4.0f); 117 var group3 = (e + f + h + i) * (0.125f / 4.0f); 118 var group4 = (j + k + l + m) * (0.5f / 4.0f); 119 group0 *= karis_average(group0); 120 group1 *= karis_average(group1); 121 group2 *= karis_average(group2); 122 group3 *= karis_average(group3); 123 group4 *= karis_average(group4); 124 return group0 + group1 + group2 + group3 + group4; 126 var sample = (a + c + g + i) * 0.03125; 127 sample += (b + d + f + h) * 0.0625; 128 sample += (e + j + k + l + m) * 0.125; 134fn sample_input_3x3_tent(uv: vec2<f32>) -> vec3<f32> { 137 let frag_size = uniforms.scale / vec2<f32>(textureDimensions(input_texture)); 141 let a = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y + y)).rgb; 142 let b = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y + y)).rgb; 143 let c = textureSample(input_texture, s, vec2<f32>(uv.x + x, uv.y + y)).rgb; 145 let d = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y)).rgb; 146 let e = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y)).rgb; 147 let f = textureSample(input_texture, s, vec2<f32>(uv.x + x, uv.y)).rgb; 149 let g = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y - y)).rgb; 150 let h = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y - y)).rgb; 151 let i = textureSample(input_texture, s, vec2<f32>(uv.x + x, uv.y - y)).rgb; 153 var sample = e * 0.25; 154 sample += (b + d + f + h) * 0.125; 155 sample += (a + c + g + i) * 0.0625; 160#ifdef FIRST_DOWNSAMPLE 162fn downsample_first(@location(0) output_uv: vec2<f32>) -> @location(0) vec4<f32> { 163 let sample_uv = uniforms.viewport.xy + output_uv * uniforms.viewport.zw; 164 var sample = sample_input_13_tap(sample_uv); 169 sample = clamp(sample, vec3<f32>(0.0001), vec3<f32>(3.40282347E+37)); 172 sample = soft_threshold(sample); 175 return vec4<f32>(sample, 1.0); 180fn downsample(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> { 181 return vec4<f32>(sample_input_13_tap(uv), 1.0); 185fn upsample(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> { 186 return vec4<f32>(sample_input_3x3_tent(uv), 1.0);