Backdrop Path + Cybersteel (#23)

Co-authored-by: Zachary Levy <zachary@sunforge.is>
Reviewed-on: #23
This commit was merged in pull request #23.
This commit is contained in:
2026-05-01 05:43:10 +00:00
parent e36229a3ef
commit 5317b8f142
66 changed files with 5806 additions and 2427 deletions
+10 -19
View File
@@ -6,8 +6,8 @@ layout(location = 1) in vec2 f_local_or_uv;
layout(location = 2) in vec4 f_params;
layout(location = 3) in vec4 f_params2;
layout(location = 4) flat in uint f_flags;
layout(location = 5) flat in uint f_rotation_sc;
layout(location = 6) flat in uvec4 f_uv_or_effects;
layout(location = 6) flat in vec4 f_uv_rect;
layout(location = 7) flat in uvec4 f_effects;
// --- Output ---
layout(location = 0) out vec4 out_color;
@@ -83,16 +83,7 @@ void main() {
float h = 0.5; // half-feather width; overwritten per shape kind
vec2 half_size = f_params.xy; // used by RRect and as reference size for gradients
vec2 p_local = f_local_or_uv;
// Apply inverse rotation using pre-computed sin/cos (no per-pixel trig).
// .Rotated flag = bit 4 = 16u
if ((flags & 16u) != 0u) {
vec2 sc = unpackHalf2x16(f_rotation_sc); // .x = sin(angle), .y = cos(angle)
// Inverse rotation matrix R(-angle) = [[cos, sin], [-sin, cos]]
p_local = vec2(sc.y * p_local.x + sc.x * p_local.y,
-sc.x * p_local.x + sc.y * p_local.y);
}
vec2 p_local = f_local_or_uv; // arrives rotated; vertex shader handled .Rotated
if (kind == 1u) {
// RRect — half_feather in params2.z
@@ -151,7 +142,7 @@ void main() {
if ((flags & 2u) != 0u) {
// Gradient active (bit 1)
mediump vec4 gradient_start = f_color;
mediump vec4 gradient_end = unpackUnorm4x8(f_uv_or_effects.x);
mediump vec4 gradient_end = unpackUnorm4x8(f_effects.x);
if ((flags & 4u) != 0u) {
// Radial gradient (bit 2): t from distance to center
@@ -159,13 +150,13 @@ void main() {
shape_color = gradient_2color(gradient_start, gradient_end, t);
} else {
// Linear gradient: direction pre-computed on CPU as (cos, sin) f16 pair
vec2 direction = unpackHalf2x16(f_uv_or_effects.z);
vec2 direction = unpackHalf2x16(f_effects.z);
mediump float t = dot(p_local / half_size, direction) * 0.5 + 0.5;
shape_color = gradient_2color(gradient_start, gradient_end, t);
}
} else if ((flags & 1u) != 0u) {
// Textured (bit 0) — RRect only in practice
vec4 uv_rect = uintBitsToFloat(f_uv_or_effects);
// Textured (bit 0)
vec4 uv_rect = f_uv_rect;
vec2 local_uv = p_local / half_size * 0.5 + 0.5;
vec2 uv = mix(uv_rect.xy, uv_rect.zw, local_uv);
shape_color = f_color * texture(tex, uv);
@@ -180,9 +171,9 @@ void main() {
// AA at d=ol_width. The outline band's coverage is total_cov - fill_cov.
// Output is premultiplied: blend state is ONE, ONE_MINUS_SRC_ALPHA.
if ((flags & 8u) != 0u) {
mediump vec4 ol_color = unpackUnorm4x8(f_uv_or_effects.y);
// Outline width in f_uv_or_effects.w (low f16 half)
float ol_width = unpackHalf2x16(f_uv_or_effects.w).x / grad_magnitude;
mediump vec4 ol_color = unpackUnorm4x8(f_effects.y);
// Outline width in f_effects.w (low f16 half)
float ol_width = unpackHalf2x16(f_effects.w).x / grad_magnitude;
float fill_cov = sdf_alpha(d, h);
float total_cov = sdf_alpha(d - ol_width, h);