58 lines
2.1 KiB
WebGPU Shading Language
58 lines
2.1 KiB
WebGPU Shading Language
|
|
// DOM-mode port of inverse-circle.comp.glsl. Inverts RGB inside each
|
||
|
|
// user-supplied circle; passes through every other pixel so the
|
||
|
|
// ping-pong carries the prior dispatch's scene forward.
|
||
|
|
//
|
||
|
|
// Bind-group contract (mirrors :WebGPUComputeShader.cppm):
|
||
|
|
// group 0 binding 0 — uniform UIDispatchHeader (auto-injected)
|
||
|
|
// group 1 binding 0 — texture_storage_2d<rgba8unorm, write> out (auto)
|
||
|
|
// group 1 binding 1 — texture_2d<f32> prev (auto)
|
||
|
|
// group 2 binding 0 — items SSBO declared by the C++ side via
|
||
|
|
// UICustomBinding { group=2, binding=0,
|
||
|
|
// kind=Buffer, pushOffset=offsetof(hdr.itemBuffer) }
|
||
|
|
|
||
|
|
struct UIDispatchHeader {
|
||
|
|
outImage: u32,
|
||
|
|
itemBuffer: u32,
|
||
|
|
surfaceW: u32,
|
||
|
|
surfaceH: u32,
|
||
|
|
clipX: f32,
|
||
|
|
clipY: f32,
|
||
|
|
clipW: f32,
|
||
|
|
clipH: f32,
|
||
|
|
itemCount: u32,
|
||
|
|
frameIdx: u32,
|
||
|
|
flags: u32,
|
||
|
|
_pad: u32,
|
||
|
|
};
|
||
|
|
@group(0) @binding(0) var<uniform> hdr : UIDispatchHeader;
|
||
|
|
@group(1) @binding(0) var outTex : texture_storage_2d<rgba8unorm, write>;
|
||
|
|
@group(1) @binding(1) var prevTex : texture_2d<f32>;
|
||
|
|
|
||
|
|
struct InverseCircleItem {
|
||
|
|
centerRadius: vec4<f32>,
|
||
|
|
};
|
||
|
|
@group(2) @binding(0) var<storage, read> items : array<InverseCircleItem>;
|
||
|
|
|
||
|
|
@compute @workgroup_size(8, 8, 1)
|
||
|
|
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
||
|
|
if (gid.x >= hdr.surfaceW || gid.y >= hdr.surfaceH) { return; }
|
||
|
|
let coord = vec2<i32>(i32(gid.x), i32(gid.y));
|
||
|
|
let sp = vec2<f32>(f32(gid.x) + 0.5, f32(gid.y) + 0.5);
|
||
|
|
|
||
|
|
// Max-coverage over all items, so overlapping circles don't
|
||
|
|
// double-invert back to the original.
|
||
|
|
var coverage: f32 = 0.0;
|
||
|
|
for (var i: u32 = 0u; i < hdr.itemCount; i = i + 1u) {
|
||
|
|
let it = items[i];
|
||
|
|
let c = it.centerRadius.xy;
|
||
|
|
let r = it.centerRadius.z;
|
||
|
|
let d = length(sp - c) - r;
|
||
|
|
coverage = max(coverage, clamp(0.5 - d, 0.0, 1.0));
|
||
|
|
}
|
||
|
|
|
||
|
|
var dst = textureLoad(prevTex, coord, 0);
|
||
|
|
if (coverage > 0.0) {
|
||
|
|
dst = vec4<f32>(mix(dst.rgb, vec3<f32>(1.0) - dst.rgb, coverage), dst.a);
|
||
|
|
}
|
||
|
|
textureStore(outTex, coord, dst);
|
||
|
|
}
|