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)); 41fn karis_average(color: vec3<f32>) -> f32 { 44 let luma = tonemapping_luminance(color) / 4.0; 45 return 1.0 / (1.0 + luma); 49fn sample_input_13_tap(uv: vec2<f32>) -> vec3<f32> { 58 let a = textureSample(input_texture, s, uv, vec2<i32>(-2, 2)).rgb; 59 let b = textureSample(input_texture, s, uv, vec2<i32>(0, 2)).rgb; 60 let c = textureSample(input_texture, s, uv, vec2<i32>(2, 2)).rgb; 61 let d = textureSample(input_texture, s, uv, vec2<i32>(-2, 0)).rgb; 62 let e = textureSample(input_texture, s, uv).rgb; 63 let f = textureSample(input_texture, s, uv, vec2<i32>(2, 0)).rgb; 64 let g = textureSample(input_texture, s, uv, vec2<i32>(-2, -2)).rgb; 65 let h = textureSample(input_texture, s, uv, vec2<i32>(0, -2)).rgb; 66 let i = textureSample(input_texture, s, uv, vec2<i32>(2, -2)).rgb; 67 let j = textureSample(input_texture, s, uv, vec2<i32>(-1, 1)).rgb; 68 let k = textureSample(input_texture, s, uv, vec2<i32>(1, 1)).rgb; 69 let l = textureSample(input_texture, s, uv, vec2<i32>(-1, -1)).rgb; 70 let m = textureSample(input_texture, s, uv, vec2<i32>(1, -1)).rgb; 81 let scale = uniforms.scale; 82 let ps = scale / vec2<f32>(textureDimensions(input_texture)); 86 let a = textureSample(input_texture, s, uv + vec2<f32>(nl.x, pl.y)).rgb; 87 let b = textureSample(input_texture, s, uv + vec2<f32>(0.00, pl.y)).rgb; 88 let c = textureSample(input_texture, s, uv + vec2<f32>(pl.x, pl.y)).rgb; 89 let d = textureSample(input_texture, s, uv + vec2<f32>(nl.x, 0.00)).rgb; 90 let e = textureSample(input_texture, s, uv).rgb; 91 let f = textureSample(input_texture, s, uv + vec2<f32>(pl.x, 0.00)).rgb; 92 let g = textureSample(input_texture, s, uv + vec2<f32>(nl.x, nl.y)).rgb; 93 let h = textureSample(input_texture, s, uv + vec2<f32>(0.00, nl.y)).rgb; 94 let i = textureSample(input_texture, s, uv + vec2<f32>(pl.x, nl.y)).rgb; 95 let j = textureSample(input_texture, s, uv + vec2<f32>(ns.x, ps.y)).rgb; 96 let k = textureSample(input_texture, s, uv + vec2<f32>(ps.x, ps.y)).rgb; 97 let l = textureSample(input_texture, s, uv + vec2<f32>(ns.x, ns.y)).rgb; 98 let m = textureSample(input_texture, s, uv + vec2<f32>(ps.x, ns.y)).rgb; 101#ifdef FIRST_DOWNSAMPLE 110 var group0 = (a + b + d + e) * (0.125f / 4.0f); 111 var group1 = (b + c + e + f) * (0.125f / 4.0f); 112 var group2 = (d + e + g + h) * (0.125f / 4.0f); 113 var group3 = (e + f + h + i) * (0.125f / 4.0f); 114 var group4 = (j + k + l + m) * (0.5f / 4.0f); 115 group0 *= karis_average(group0); 116 group1 *= karis_average(group1); 117 group2 *= karis_average(group2); 118 group3 *= karis_average(group3); 119 group4 *= karis_average(group4); 120 return group0 + group1 + group2 + group3 + group4; 122 var sample = (a + c + g + i) * 0.03125; 123 sample += (b + d + f + h) * 0.0625; 124 sample += (e + j + k + l + m) * 0.125; 130fn sample_input_3x3_tent(uv: vec2<f32>) -> vec3<f32> { 133 let frag_size = uniforms.scale / vec2<f32>(textureDimensions(input_texture)); 137 let a = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y + y)).rgb; 138 let b = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y + y)).rgb; 139 let c = textureSample(input_texture, s, vec2<f32>(uv.x + x, uv.y + y)).rgb; 141 let d = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y)).rgb; 142 let e = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y)).rgb; 143 let f = textureSample(input_texture, s, vec2<f32>(uv.x + x, uv.y)).rgb; 145 let g = textureSample(input_texture, s, vec2<f32>(uv.x - x, uv.y - y)).rgb; 146 let h = textureSample(input_texture, s, vec2<f32>(uv.x, uv.y - y)).rgb; 147 let i = textureSample(input_texture, s, vec2<f32>(uv.x + x, uv.y - y)).rgb; 149 var sample = e * 0.25; 150 sample += (b + d + f + h) * 0.125; 151 sample += (a + c + g + i) * 0.0625; 156#ifdef FIRST_DOWNSAMPLE 158fn downsample_first(@location(0) output_uv: vec2<f32>) -> @location(0) vec4<f32> { 159 let sample_uv = uniforms.viewport.xy + output_uv * uniforms.viewport.zw; 160 var sample = sample_input_13_tap(sample_uv); 165 sample = clamp(sample, vec3<f32>(0.0001), vec3<f32>(3.40282347E+37)); 168 sample = soft_threshold(sample); 171 return vec4<f32>(sample, 1.0); 176fn downsample(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> { 177 return vec4<f32>(sample_input_13_tap(uv), 1.0); 181fn upsample(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> { 182 return vec4<f32>(sample_input_3x3_tent(uv), 1.0);