Added backdrop effects pipeline (blur)

This commit is contained in:
Zachary Levy
2026-04-28 22:12:25 -07:00
parent ff29dbd92f
commit 16989cbb71
29 changed files with 2931 additions and 415 deletions
+31 -12
View File
@@ -11,8 +11,9 @@ layout(location = 1) out vec2 f_local_or_uv;
layout(location = 2) out vec4 f_params;
layout(location = 3) out vec4 f_params2;
layout(location = 4) flat out uint f_flags;
layout(location = 5) flat out uint f_rotation_sc;
layout(location = 6) flat out uvec4 f_uv_or_effects;
layout(location = 6) flat out vec4 f_uv_rect;
layout(location = 7) flat out uvec4 f_effects;
// ---------- Uniforms (single block — avoids spirv-cross reordering on Metal) ----------
layout(set = 1, binding = 0) uniform Uniforms {
@@ -22,7 +23,10 @@ layout(set = 1, binding = 0) uniform Uniforms {
};
// ---------- SDF primitive storage buffer ----------
struct Primitive {
// Mirrors the CPU-side Base_2D_Primitive in pipeline_2d_base.odin. Named with the
// pipeline prefix so a project-wide grep on the type name matches both the GLSL
// declaration and the Odin declaration.
struct Base_2D_Primitive {
vec4 bounds; // 0-15
uint color; // 16-19
uint flags; // 20-23
@@ -30,11 +34,12 @@ struct Primitive {
float _pad; // 28-31
vec4 params; // 32-47
vec4 params2; // 48-63
uvec4 uv_or_effects; // 64-79
vec4 uv_rect; // 64-79: texture UV coordinates (read when .Textured)
uvec4 effects; // 80-95: gradient/outline parameters (read when .Gradient/.Outline)
};
layout(std430, set = 0, binding = 0) readonly buffer Primitives {
Primitive primitives[];
layout(std430, set = 0, binding = 0) readonly buffer Base_2D_Primitives {
Base_2D_Primitive primitives[];
};
// ---------- Entry point ----------
@@ -46,25 +51,39 @@ void main() {
f_params = vec4(0.0);
f_params2 = vec4(0.0);
f_flags = 0u;
f_rotation_sc = 0u;
f_uv_or_effects = uvec4(0);
f_uv_rect = vec4(0.0);
f_effects = uvec4(0);
gl_Position = projection * vec4(v_position * dpi_scale, 0.0, 1.0);
} else {
// ---- Mode 1: SDF instanced quads ----
Primitive p = primitives[gl_InstanceIndex];
Base_2D_Primitive p = primitives[gl_InstanceIndex];
vec2 corner = v_position; // unit quad corners: (0,0)-(1,1)
vec2 world_pos = mix(p.bounds.xy, p.bounds.zw, corner);
vec2 center = 0.5 * (p.bounds.xy + p.bounds.zw);
// Compute shape-local position. Apply inverse rotation here in the vertex
// shader; the rasterizer interpolates the rotated values across the quad,
// which is mathematically equivalent to per-fragment rotation under 2D ortho
// projection. Frees one fragment-shader varying and per-pixel rotation math.
vec2 local = (world_pos - center) * dpi_scale;
uint flags = (p.flags >> 8u) & 0xFFu;
if ((flags & 16u) != 0u) {
// Rotated flag (bit 4); rotation_sc holds packed f16 (sin, cos).
// Inverse rotation matrix R(-angle) = [[cos, sin], [-sin, cos]].
vec2 sc = unpackHalf2x16(p.rotation_sc);
local = vec2(sc.y * local.x + sc.x * local.y,
-sc.x * local.x + sc.y * local.y);
}
f_color = unpackUnorm4x8(p.color);
f_local_or_uv = (world_pos - center) * dpi_scale; // shape-centered physical pixels
f_local_or_uv = local; // shape-local physical pixels (rotated if .Rotated set)
f_params = p.params;
f_params2 = p.params2;
f_flags = p.flags;
f_rotation_sc = p.rotation_sc;
f_uv_or_effects = p.uv_or_effects;
f_uv_rect = p.uv_rect;
f_effects = p.effects;
gl_Position = projection * vec4(world_pos * dpi_scale, 0.0, 1.0);
}