Added backdrop effects pipeline (blur)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
#version 450 core
|
||||
|
||||
// Unified backdrop blur vertex shader.
|
||||
// Handles both H-blur (fullscreen triangle, mode 0) and V-blur+composite (instanced
|
||||
// unit-quad over Backdrop_Primitive storage buffer, mode 1) for the second PSO of
|
||||
// the backdrop bracket. The first PSO (downsample) uses backdrop_fullscreen.vert.
|
||||
//
|
||||
// No vertex buffer for either mode. Mode 0 uses gl_VertexIndex 0..2 for a single
|
||||
// fullscreen triangle; mode 1 uses gl_VertexIndex 0..5 for a unit-quad (two
|
||||
// triangles, TRIANGLELIST topology) and gl_InstanceIndex to select the primitive.
|
||||
//
|
||||
// Mode 0 viewport+scissor are CPU-set per layer-bracket to the work region (union
|
||||
// AABB of backdrop primitives + 3*max_sigma, clamped to swapchain bounds). Mode 1
|
||||
// renders into the main render target with the screen-space orthographic projection;
|
||||
// the per-primitive bounds drive the quad in screen space.
|
||||
//
|
||||
// Backdrop primitives have NO rotation — backdrop sampling is in screen space, so
|
||||
// a rotated mask over a stationary blur sample would look wrong.
|
||||
|
||||
// --- Outputs to fragment shader ---
|
||||
// p_local: shape-local position in physical pixels (origin at shape center).
|
||||
// Only meaningful in mode 1 (V-composite). Zero-init for mode 0.
|
||||
layout(location = 0) out vec2 p_local;
|
||||
// f_color: tint, unpacked from primitive.color. Only meaningful in mode 1.
|
||||
layout(location = 1) out mediump vec4 f_color;
|
||||
// f_half_size: RRect half extents in physical pixels (mode 1 only).
|
||||
layout(location = 2) flat out vec2 f_half_size;
|
||||
// f_radii: per-corner radii in physical pixels (mode 1 only).
|
||||
layout(location = 3) flat out vec4 f_radii;
|
||||
// f_half_feather: SDF anti-aliasing feather (mode 1 only).
|
||||
layout(location = 4) flat out float f_half_feather;
|
||||
|
||||
// --- Uniforms (set 1) ---
|
||||
// Backdrop pipeline's own uniform block — distinct from the main pipeline's
|
||||
// Vertex_Uniforms. `mode` selects between H-blur (0) and V-composite (1).
|
||||
layout(set = 1, binding = 0) uniform Uniforms {
|
||||
mat4 projection;
|
||||
float dpi_scale;
|
||||
uint mode; // 0 = H-blur, 1 = V-composite
|
||||
vec2 _pad0;
|
||||
};
|
||||
|
||||
// --- Backdrop primitive storage buffer (set 0) ---
|
||||
// 48 bytes, std430-natural layout (no implicit padding). vec4 members are
|
||||
// front-loaded so their 16-byte alignment is satisfied without holes; the
|
||||
// vec2 and scalar tail packs tight to land the struct at a clean 48-byte
|
||||
// stride (a multiple of 16, so the array stride needs no rounding either).
|
||||
// Field semantics match the CPU-side Backdrop_Primitive declared in
|
||||
// levlib/draw/pipeline_2d_backdrop.odin; keep both in sync.
|
||||
//
|
||||
// Backdrop primitives are tint-only in v1: outline is intentionally absent.
|
||||
// Future specialized effects (e.g. liquid-glass-style edges) would be a
|
||||
// dedicated primitive type with its own pipeline rather than a flag bit here.
|
||||
struct Backdrop_Primitive {
|
||||
vec4 bounds; // 0-15: min_xy, max_xy (world-space)
|
||||
vec4 radii; // 16-31: per-corner radii (physical px)
|
||||
vec2 half_size; // 32-39: RRect half extents (physical px)
|
||||
float half_feather; // 40-43: SDF anti-aliasing feather (physical px)
|
||||
uint color; // 44-47: tint, packed RGBA u8x4
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = 0) readonly buffer Backdrop_Primitives {
|
||||
Backdrop_Primitive primitives[];
|
||||
};
|
||||
|
||||
void main() {
|
||||
if (mode == 0u) {
|
||||
// ---- Mode 0: H-blur fullscreen triangle ----
|
||||
// gl_VertexIndex 0 -> ( -1, -1)
|
||||
// gl_VertexIndex 1 -> ( 3, -1)
|
||||
// gl_VertexIndex 2 -> ( -1, 3)
|
||||
vec2 ndc = vec2(
|
||||
(gl_VertexIndex == 1) ? 3.0 : -1.0,
|
||||
(gl_VertexIndex == 2) ? 3.0 : -1.0);
|
||||
gl_Position = vec4(ndc, 0.0, 1.0);
|
||||
|
||||
// Mode 0 doesn't read the per-primitive varyings; zero-init for safety.
|
||||
p_local = vec2(0.0);
|
||||
f_color = vec4(0.0);
|
||||
f_half_size = vec2(0.0);
|
||||
f_radii = vec4(0.0);
|
||||
f_half_feather = 0.0;
|
||||
} else {
|
||||
// ---- Mode 1: V-composite instanced unit-quad over Backdrop_Primitive ----
|
||||
Backdrop_Primitive p = primitives[gl_InstanceIndex];
|
||||
|
||||
// Unit-quad corners for TRIANGLELIST (2 triangles, 6 vertices):
|
||||
// index 0 -> (0,0) index 3 -> (0,1)
|
||||
// index 1 -> (1,0) index 4 -> (1,0)
|
||||
// index 2 -> (0,1) index 5 -> (1,1)
|
||||
vec2 quad_corners[6] = vec2[6](
|
||||
vec2(0.0, 0.0), vec2(1.0, 0.0), vec2(0.0, 1.0),
|
||||
vec2(0.0, 1.0), vec2(1.0, 0.0), vec2(1.0, 1.0));
|
||||
vec2 corner = quad_corners[gl_VertexIndex];
|
||||
|
||||
vec2 world_pos = mix(p.bounds.xy, p.bounds.zw, corner);
|
||||
vec2 center = 0.5 * (p.bounds.xy + p.bounds.zw);
|
||||
|
||||
// Shape-local position in physical pixels (no rotation for backdrops).
|
||||
p_local = (world_pos - center) * dpi_scale;
|
||||
|
||||
f_color = unpackUnorm4x8(p.color);
|
||||
f_half_size = p.half_size;
|
||||
f_radii = p.radii;
|
||||
f_half_feather = p.half_feather;
|
||||
|
||||
gl_Position = projection * vec4(world_pos * dpi_scale, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user