61 lines
2.3 KiB
GLSL
61 lines
2.3 KiB
GLSL
// Custom UI compute shader. Demonstrates the Tier 1 dispatch path:
|
|
// the user defines their own item struct, writes their own GLSL alongside
|
|
// the standard shaders (sharing the same UIDispatchHeader contract via
|
|
// ui-shared.glsl), and dispatches it via UIRenderer::Dispatch.
|
|
//
|
|
// What it does: each item is a circle. For every pixel the workgroup tile
|
|
// owns, if the pixel falls inside any item-circle, the pixel's RGB is
|
|
// inverted (1 - rgb). Composes naturally with whatever previous dispatches
|
|
// drew into the swapchain image — works on top of standard quads, custom
|
|
// effects, anything.
|
|
#version 460
|
|
#extension GL_GOOGLE_include_directive : enable
|
|
#include "ui-shared.glsl"
|
|
|
|
// Application-defined item: just (cx, cy, radius, _pad). Layout matches the
|
|
// C++ InverseCircleItem struct in main.cpp byte-for-byte under std430.
|
|
struct InverseCircleItem {
|
|
vec4 centerRadius;
|
|
};
|
|
|
|
layout(descriptor_heap, std430) readonly buffer InvCircleBuf {
|
|
InverseCircleItem items[];
|
|
} invCircleHeap[];
|
|
|
|
// NVIDIA workaround — same per-member-load pattern the library shaders use
|
|
// for the descriptor-heap'd SSBO composite-load issue.
|
|
InverseCircleItem LoadInverseCircleItem(uint heap, uint i) {
|
|
InverseCircleItem it;
|
|
it.centerRadius = invCircleHeap[heap].items[i].centerRadius;
|
|
return it;
|
|
}
|
|
|
|
layout(push_constant) uniform PC {
|
|
UIDispatchHeader hdr;
|
|
} pc;
|
|
|
|
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|
|
|
void main() {
|
|
ivec2 screenPx;
|
|
if (!uiResolveScreenPixel(pc.hdr, screenPx)) return;
|
|
|
|
vec2 sp = vec2(screenPx) + 0.5;
|
|
|
|
// Find the strongest circle coverage at this pixel — using max instead
|
|
// of literal per-item invert so overlapping circles don't double-invert
|
|
// back to the original.
|
|
float coverage = 0.0;
|
|
for (uint i = 0u; i < pc.hdr.itemCount; ++i) {
|
|
InverseCircleItem it = LoadInverseCircleItem(pc.hdr.itemBuffer, i);
|
|
vec2 c = it.centerRadius.xy;
|
|
float r = it.centerRadius.z;
|
|
float d = length(sp - c) - r;
|
|
coverage = max(coverage, clamp(0.5 - d, 0.0, 1.0));
|
|
}
|
|
if (coverage <= 0.0) return;
|
|
|
|
vec4 dst = imageLoad(uiImages[pc.hdr.outImage], screenPx);
|
|
dst.rgb = mix(dst.rgb, vec3(1.0) - dst.rgb, coverage);
|
|
imageStore(uiImages[pc.hdr.outImage], screenPx, dst);
|
|
}
|