Crafter.Graphics/examples/HDRBloom/threshold.comp.wgsl

30 lines
1.4 KiB
WebGPU Shading Language
Raw Normal View History

2026-07-22 18:09:06 +02:00
//SPDX-License-Identifier: MIT
//SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
// HDRBloom threshold pass (PlainComputeShader). Reads the linear HDR scene
// (rgba16float, written by the RT RESOLVE stage), keeps only the radiance
// above 1.0, and writes it into the bloom mip (also rgba16float). This is
// the primitive the issue asks for: sample a float texture (group 1
// binding 0) and WRITE a user-owned float storage texture (group 1
// binding 1) at an app-chosen binding.
//
// Layout (PlainComputeShader, no rayQuery → user groups start at 1):
// @group(0) @binding(0) uniform Dim (surface size)
// @group(1) @binding(0) texture_2d<f32> src (sampled, float)
// @group(1) @binding(1) storage rgba16float dst (write)
struct Dim { w: u32, h: u32, _0: u32, _1: u32 };
@group(0) @binding(0) var<uniform> dim : Dim;
@group(1) @binding(0) var src : texture_2d<f32>;
@group(1) @binding(1) var dst : texture_storage_2d<rgba16float, write>;
@compute @workgroup_size(8, 8, 1)
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
if (gid.x >= dim.w || gid.y >= dim.h) { return; }
let coord = vec2<i32>(i32(gid.x), i32(gid.y));
let c = textureLoad(src, coord, 0).rgb;
// Soft knee around 1.0 so the extracted highlights ramp in smoothly.
let lum = dot(c, vec3<f32>(0.2126, 0.7152, 0.0722));
let keep = max(0.0, lum - 1.0) / max(lum, 1e-4);
textureStore(dst, coord, vec4<f32>(c * keep, 1.0));
}