GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
src/draw/shader2d.wgsl (69.6K)
1 // The toolkit's 2D pipeline shader — the union of the two wgpu-era dialects:
2 // the engine shader's wavy-blob effect (clip_circle.x == -999 sentinel) and the
3 // designer shader's window-corner rounding + circle clip + blur-behind branch
4 // (negative alpha samples the backdrop). Clients that don't use a feature pay
5 // nothing: radius 0 disables corner rounding, the backdrop is renderer-managed,
6 // and plain quads take the final `return in.color` path.
7
8 @group(0) @binding(0) var t_backdrop: texture_2d<f32>;
9 @group(0) @binding(1) var s_backdrop: sampler;
10
11 struct WindowInfo {
12 window_size: vec2<f32>,
13 corner_radius: f32,
14 // Corner-shape exponent shared with the plates and the rounded-rect clip:
15 // circular arc at 2, superellipse squircle above.
16 corner_shape: f32,
17 // Custom bevel/carve profile (cce_ui::layout::set_bevel_profile_keys):
18 // x nonzero enables it, y = live sample count in `profile`.
19 profile_meta: vec4f,
20 // Slope samples of the profile's height curve h(v) (v 0 = plateau, 1 =
21 // carve floor / boss crest), sample i at v = (i + 0.5) / count, packed 4
22 // per vec4. carve_slope reads these in place of its analytic smoothstep.
23 profile: array<vec4f, 8>,
24 // Custom EDGE profile for the plate perimeter roll
25 // (cce_ui::layout::set_roll_profile_keys) — same encoding, read by
26 // roll_slope in place of the analytic superellipse quadrant. The curve is
27 // the roll's descent progress: 0 at the face join, 1 at the silhouette.
28 roll_meta: vec4f,
29 roll_profile: array<vec4f, 8>,
30 // Pinned relief heights in physical px (cce_ui::layout::bevel_height /
31 // roll_height): x = a carve's drop, y = the plate roll's rise. 0 = follow
32 // the wall width — RECESS_DEPTH × width for a carve, a quarter-round of
33 // radius width for the roll. Divided by the batch's own wall width
34 // (p_light.w) they become the slope scale, so a pinned 0.5 mm drop is
35 // the same geometry whatever wall it is cut with.
36 relief_meta: vec4f,
37 }
38
39 @group(0) @binding(2) var<uniform> window_info: WindowInfo;
40
41 // One carve (recess) belonging to an SDF-lit plate: a rounded box subtracted
42 // from the plate's material. rect = center + half-extents, radii per-corner
43 // (both physical px; a wall the carve shares with the plate's edge is encoded
44 // by extending the box past the plate on that side). params = [transition
45 // width px, depth px, 0, 0].
46 struct PlateFeature {
47 rect: vec4f,
48 radii: vec4f,
49 params: vec4f,
50 }
51 // Double-buffered by frame-in-flight: slot k's 64 entries belong to frame
52 // index k. The plate's push constants carry the absolute offset.
53 struct PlateFeatures {
54 items: array<PlateFeature, 128>,
55 }
56 @group(0) @binding(3) var<uniform> plate_features: PlateFeatures;
57
58 // Signed distance to the window's rounded silhouette at pos: positive outside
59 // the corner arcs (and past the window bounds), large-negative elsewhere so the
60 // straight edges keep their exact hard cut at the buffer boundary. The corner
61 // family follows window_info.corner_shape — circular arc at 2, superellipse
62 // squircle above, with the Lp branch's first-order |∇| correction so a feather
63 // built on this distance keeps ~uniform width around the arc (the same
64 // construction as rr_sdf_grad and the tessellated plate corners).
65 fn window_corner_distance(pos: vec2<f32>) -> f32 {
66 let w = window_info.window_size.x;
67 let h = window_info.window_size.y;
68 let r = window_info.corner_radius;
69
70 if (pos.x < 0.0 || pos.x > w || pos.y < 0.0 || pos.y > h) {
71 return 1e5;
72 }
73 if (r <= 0.0) {
74 return -1e5;
75 }
76 let q = abs(pos - vec2f(w * 0.5, h * 0.5)) - vec2f(w * 0.5 - r, h * 0.5 - r);
77 if (q.x > 0.0 && q.y > 0.0) {
78 let shape = window_info.corner_shape;
79 if (shape > 2.001) {
80 let lp = max(pow(pow(q.x, shape) + pow(q.y, shape), 1.0 / shape), 1e-4);
81 let g = vec2f(pow(q.x / lp, shape - 1.0), pow(q.y / lp, shape - 1.0));
82 return (lp - r) / max(length(g), 1e-4);
83 }
84 return length(q) - r;
85 }
86 return -1e5;
87 }
88
89 // Per-batch push constants (112 bytes). The first two vec4s are the rounded-rect
90 // clip: rect0 = [cx, cy, bx, by] (center + SDF half-extents), rect1 = [corner
91 // radius, enabled flag, plate mode, corner shape]. When plate mode is
92 // nonzero the batch is an SDF-lit plate (1 = raised plate, 2 = recess overlay)
93 // and the p_* block describes it. The corner shape exponent selects circular
94 // (2) vs superellipse (> 2) corners for BOTH the clip SDF and the plate —
95 // see rr_sdf_grad; it is set whenever either consumer is live. Physical
96 // pixels, like clip_position.
97 struct RRectClip {
98 rect0: vec4f,
99 rect1: vec4f,
100 // Plate SDF box: center + half-extents. May extend past the drawn cover
101 // quad — that is how a recess suppresses a wall (the edge lies outside the
102 // covered pixels, so its shading never lands).
103 p_rect: vec4f,
104 // Per-corner radii [tl, tr, br, bl].
105 p_radii: vec4f,
106 // xyz = unit vector toward the light (screen space, +z out of the screen),
107 // w = bevel roll width in px.
108 p_light: vec4f,
109 // [shading strength, specular strength, shininess, curvature/AO strength].
110 p_mat: vec4f,
111 // Mode 1 (raised plate): xy = [offset, count] into plate_features — the
112 // carves CSG'd out of this plate's material; z = the plate's FROST
113 // recipe, compression and refraction as 12-bit fixed point in one float
114 // (hi·FROST_PACK_BASE + lo, each over FROST_PACK_MAX — see
115 // material::Frost::pack); w = the blur kernel's sigma in physical px,
116 // 0 = a clear plate (one clean sample). Unread on an opaque plate.
117 // Mode 2 (free recess overlay): the host-plate box (center + half-extents)
118 // the carve fades out against — a wall flush with the host's edge dies
119 // across the host's perimeter roll; far-away sides sit at ±1e5 (no fade).
120 p_host: vec4f,
121 // RGB multiplies the lit roll's specular color — neutral white normally,
122 // a highlight color on a marked (focused) plate. w unused.
123 p_spec_tint: vec4f,
124 }
125 var<push_constant> rrect_clip: RRectClip;
126
127 // Plate modes, as carried in rect1.z (see PlatePush::mode). Compared by EQUALITY
128 // on a rounded int, never by range: the ranges these replaced were ordered, and
129 // the order was load-bearing without saying so — mode 8's branch had to precede
130 // the `> 5.5` fillet branch or the fillet arm would have swallowed it, taken 4
131 // off, and drawn every groove as a ridge. Equality makes a new mode inert
132 // wherever it is added rather than silently captured by a neighbour.
133 // Frost recipe packing — mirrored by `scene::material::Frost`, checked by
134 // its tests against this text.
135 const FROST_PACK_MAX: f32 = 4095.0;
136 const FROST_PACK_BASE: f32 = 4096.0;
137 // The kernel stride a frosted surface with NO recipe uses — the droplet
138 // (its push block is full) and a raw negative-alpha vertex from outside the
139 // display list: the panel's default kernel (Frost::DEFAULT_RADIUS at scale
140 // 2), which is exactly the fixed 5.5 px stride every frosted plate had
141 // before recipes were per plate.
142 const LEGACY_STRIDE: f32 = 5.5;
143
144 const MODE_NONE: i32 = 0; // not a plate batch
145 const MODE_PLATE: i32 = 1; // raised lit plate: fill + rolled perimeter + CSG carves
146 const MODE_RECESS: i32 = 2; // free carve, interior one step DOWN
147 const MODE_BOSS: i32 = 3; // free carve, interior one step UP
148 const MODE_RIDGE: i32 = 4; // raised rim straddling the boundary
149 const MODE_SPHERE: i32 = 5; // hemisphere-lit disc
150 const MODE_FILLET_DOWN: i32 = 6; // concave inside-corner wall, recessed
151 const MODE_FILLET_UP: i32 = 7; // concave inside-corner wall, raised
152 const MODE_GROOVE: i32 = 8; // slab carve about an arbitrary line
153 const MODE_TROUGH: i32 = 9; // sunken valley straddling the boundary
154 const MODE_DROPLET: i32 = 10; // hanging water droplet clinging to the box top
155 const MODE_ROLL: i32 = 11; // fill-less rolled perimeter, composited as an overlay
156 const MODE_DROPLET_SCRIM: i32 = 12; // flat feathered fill of the droplet silhouette
157 const MODE_LATTICE: i32 = 13; // periodic well field: nearest-cell carve, one evaluation
158 const MODE_UNION: i32 = 14; // union of feature boxes carved/raised as one wall
159 const MODE_GROUT: i32 = 15; // flat colour outside a periodic field of rounded cells
160 const MODE_FIELD: i32 = 16; // sunken well ending in a flush run: one outline (Prim::Field)
161 const MODE_FRAME: i32 = 17; // MODE_PLATE inside out: the face is OUTSIDE the box (Prim::Frame)
162 // Fillet modes rejoin the shared free-carve path as their flat equivalents.
163 const FILLET_TO_STEP: i32 = 4; // 6 -> RECESS, 7 -> BOSS
164
165 const TAU: f32 = 6.28318530718;
166 // Ambient floor of the plate lighting model: the fraction of illumination that
167 // arrives from everywhere rather than from the directional light. Keeps shadow
168 // walls readable instead of crushing to black.
169 const PLATE_AMBIENT: f32 = 0.55;
170 // Amplitude of the bright crest line hugging a raised plate's silhouette — the
171 // ambient-catching convex rim that makes glass read as glass.
172 const PLATE_CREST: f32 = 0.25;
173 // The far-edge shade line's strength relative to the glint (roll_shade_line):
174 // 1 is the exact mirror; 0.5 keeps dark faces from bottoming out at black.
175 const PLATE_SHADE_LINE: f32 = 0.5;
176 // The focus treatment (p_spec_tint.w = 1) keeps the relief and recolours it:
177 // the light composites in the accent instead of white, the shadow in a DARK
178 // accent instead of black — so the lit and shaded sides still differ as an
179 // unfocused plate's do, in the accent's hue. A shadow is never lighter than
180 // the unfocused one: a faced plate's takes the accent's hue at the shaded
181 // luminance, and a carve (an overlay, which cannot see what it darkens)
182 // composites the accent at this luminance, near black. Until 2026-10-05 the
183 // shadow was the accent at a quarter of its own brightness, which for a
184 // bright accent on a dark plate is far LIGHTER than the plate: the shaded
185 // side became the brightest part of the ring and the relief read inverted.
186 const FOCUS_SHADOW_LUM: f32 = 0.004;
187 // ...and the light at this gain over the neutral relief: the accent at
188 // white's alpha reads dimmer than white, and a focused plate should read at
189 // least as lit.
190 const FOCUS_GAIN: f32 = 1.5;
191 // Rec. 709 luminance weights, for the colours above (all linear).
192 const LUMA: vec3f = vec3f(0.2126, 0.7152, 0.0722);
193 // Recess depth as a fraction of the roll width (a recess is visually shallower
194 // than a raised plate's full quarter-round).
195 const RECESS_DEPTH: f32 = 0.6;
196
197 // Signed distance and gradient of the plate's rounded box at p, as
198 // (grad.x, grad.y, distance). Analytic — no dpdx/dpdy — so the clip discards
199 // above the plate branch cannot poison derivative quads, and corners need no
200 // special casing: the gradient swings continuously around each arc.
201 //
202 // rect1.w is the corner shape exponent: 2 = circular arcs; > 2 swaps them for
203 // superellipse (Lp-norm) corners — Apple-style continuous curvature, where
204 // curvature ramps smoothly to zero at the edge join instead of jumping from
205 // 1/r, so the lit roll's highlight sweeps a corner without a G2 kink. The Lp
206 // gradient is not unit length, so both the direction and the distance carry a
207 // first-order |∇| correction — exact on the boundary, and well within a shade
208 // step over the roll's few-px band.
209 fn rr_sdf_grad(p: vec2f, prect: vec4f, pradii: vec4f) -> vec3f {
210 let c = p - prect.xy;
211 let side = select(pradii.xw, pradii.yz, c.x > 0.0);
212 let r = select(side.x, side.y, c.y > 0.0);
213 let q = abs(c) - prect.zw + vec2f(r, r);
214 let s = vec2f(select(-1.0, 1.0, c.x >= 0.0), select(-1.0, 1.0, c.y >= 0.0));
215 if (q.x > 0.0 && q.y > 0.0) {
216 let shape = rrect_clip.rect1.w;
217 if (shape > 2.001) {
218 let lp = max(pow(pow(q.x, shape) + pow(q.y, shape), 1.0 / shape), 1e-4);
219 let g = vec2f(pow(q.x / lp, shape - 1.0), pow(q.y / lp, shape - 1.0));
220 let gm = max(length(g), 1e-4);
221 // First-order |∇|-corrected distance: exact on the boundary and on
222 // the axis/diagonal rays, but mid-arc it runs up to ~4% of the
223 // depth low, so the roll band's contours drift off the true
224 // parallels of the arc as the roll widens.
225 let d0 = (lp - r) / gm;
226 let dir = g / gm;
227 // One re-evaluation at the projected near-boundary point tightens
228 // the band to true parallels (error /5 to /10 over the lit part of
229 // the roll). Trusted only near the boundary: past the roll the
230 // projection approaches the Lp field's degenerate center and
231 // diverges, so the step is clamped and the result blends back to
232 // the plain first-order value — beyond 1.5 rolls the field is
233 // bit-identical to the pre-refinement one (flat fill; only
234 // crest/AO tails read it there).
235 let roll = max(rrect_clip.p_light.w, 2.0);
236 let step = clamp(d0, -roll, roll);
237 let q1 = max(q - step * dir, vec2f(1e-4));
238 let lp1 = max(pow(pow(q1.x, shape) + pow(q1.y, shape), 1.0 / shape), 1e-4);
239 let g1 = vec2f(pow(q1.x / lp1, shape - 1.0), pow(q1.y / lp1, shape - 1.0));
240 let gm1 = max(length(g1), 1e-4);
241 let d1 = step + (lp1 - r) / gm1;
242 let w = smoothstep(roll, roll * 1.5 + 2.0, abs(d0));
243 let nrm = normalize(mix(g1 / gm1, dir, w));
244 return vec3f(s * nrm, mix(d1, d0, w));
245 }
246 let len = max(length(q), 1e-4);
247 return vec3f(s * q / len, len - r);
248 }
249 if (q.x > q.y) {
250 return vec3f(s.x, 0.0, q.x - r);
251 }
252 return vec3f(0.0, s.y, q.y - r);
253 }
254
255 // Specular of a roll at tilt `slope` whose outward horizontal facing is along
256 // `g`: the profile alignment (how close the roll's tilt is to the half-vector's
257 // tilt) powered by shininess, times a gentle azimuthal falloff, minus the flat
258 // face's baseline so the face contributes zero. Deliberately DECOUPLED rather
259 // than Blinn-Phong's pow(dot(n, hv), s): coupled, a straight edge's normal can
260 // never fully reach the half-vector (it tilts in one plane only) while a corner
261 // diagonal's can, so the power function crushes edge lines relative to corner
262 // glints and the meeting fattens into a blob that ignores the corner arc.
263 // Decoupled, the band keeps constant inset, width, and peak intensity as it
264 // sweeps a corner — the highlight follows the silhouette.
265 // `sv` is the surface's slope vector — the horizontal part of the unnormalized
266 // normal (-∇height, 1): its magnitude is the tilt, its direction the facing.
267 fn roll_spec(sv: vec2f) -> f32 {
268 return roll_lobe(sv, rrect_clip.p_light.xyz);
269 }
270
271 // The glint's dark counterpart: the SAME decoupled lobe — same inset, width
272 // and peak — on the edges facing AWAY from the light, which is roll_spec
273 // evaluated under the light's azimuth mirrored. Subtracted in colour units
274 // exactly as the glint is added, scaled by PLATE_SHADE_LINE. It exists
275 // because the diffuse fall-off alone cannot answer the glint: with the
276 // ambient floor and the truncated roll the far edge bottoms out near 0.8 of
277 // the face, and only in its last pixel, while the glint adds ~0.17 of white
278 // over a band — so a raised plate read lit on one side and merely unlit on
279 // the other, never shadowed.
280 fn roll_shade_line(sv: vec2f) -> f32 {
281 let l = rrect_clip.p_light.xyz;
282 return roll_lobe(sv, vec3f(-l.xy, l.z)) * PLATE_SHADE_LINE;
283 }
284
285 fn roll_lobe(sv: vec2f, light: vec3f) -> f32 {
286 let m = length(sv);
287 if (m < 1e-5) {
288 return 0.0;
289 }
290 let hv = normalize(light + vec3f(0.0, 0.0, 1.0));
291 let shininess = rrect_clip.p_mat.z;
292 let facing = sv / m;
293 let cos_t = inverseSqrt(1.0 + m * m);
294 let sin_t = m * cos_t;
295 let hxy = length(hv.xy);
296 let prof = cos_t * hv.z + sin_t * hxy; // cos(tilt - half-vector tilt)
297 let az = clamp(dot(facing, hv.xy) / max(hxy, 1e-4), 0.0, 1.0);
298 return rrect_clip.p_mat.y * max(pow(prof, shininess) - pow(hv.z, shininess), 0.0) * az * az;
299 }
300
301 // roll_spec with the azimuth mask dropped: every edge shades as if it faced
302 // the light, so the glint the light-facing edges normally get sweeps the
303 // WHOLE silhouette at the same inset, width, and peak (the decoupled profile
304 // keeps those constant through corners by construction). The focused-plate
305 // treatment: the familiar specular line, accent-tinted, on all four sides.
306 fn roll_spec_wrap(sv: vec2f) -> f32 {
307 let m = length(sv);
308 if (m < 1e-5) {
309 return 0.0;
310 }
311 let hv = normalize(rrect_clip.p_light.xyz + vec3f(0.0, 0.0, 1.0));
312 let shininess = rrect_clip.p_mat.z;
313 let cos_t = inverseSqrt(1.0 + m * m);
314 let sin_t = m * cos_t;
315 let hxy = length(hv.xy);
316 let prof = cos_t * hv.z + sin_t * hxy;
317 return rrect_clip.p_mat.y * max(pow(prof, shininess) - pow(hv.z, shininess), 0.0);
318 }
319
320 // How squarely a rim faces the light's azimuth, 0..1 — the weight on the
321 // plate crest. The crest was a flat +PLATE_CREST on every side, and on the
322 // far (down-light) edges that out-measured the roll's own diffuse fall-off at
323 // every point of the profile: a raised plate had a bright rim toward the
324 // light and NO dark rim away from it. Weighted this way the near edges keep
325 // their crest and the far edges keep only their diffuse shading, so the
326 // silhouette reads lit on one side and shadowed on the other, like the
327 // glint's counterpart. Light from straight overhead has no near or far side
328 // and keeps the crest everywhere.
329 fn crest_weight(facing: vec2f) -> f32 {
330 let lxy = rrect_clip.p_light.xy;
331 let m = length(lxy);
332 if (m < 1e-4) {
333 return 1.0;
334 }
335 return max(dot(facing, lxy) / m, 0.0);
336 }
337
338 // Slope of the raised roll's height profile at f (0 at the face join, 1 at the
339 // silhouette). Circular (shape 2): a quarter-round h = sqrt(1 - f²) — tangent-
340 // continuous with the face but with a curvature JUMP at the join (1/t → 0), the
341 // profile-space twin of a circular plan corner. shape > 2 swaps in the matching
342 // superellipse quadrant h = (1 - f^n)^(1/n): its curvature ramps to zero at the
343 // join, so the roll's shading fades into the face instead of ending on a line.
344 // The slope has the closed form (f/h)^(n-1), which IS the circular formula at
345 // n = 2 — the same one-exponent generalization as the plan corners.
346 // The descent is truncated at ROLL_CUT of the quadrant: the roll shades as if
347 // the slab's rim were cut off partway down, so the profile ends on a bounded
348 // slope instead of plunging vertical at the silhouette (the full quadrant put
349 // nearly all of its drop in the outer third of the roll, reading as a hard
350 // dropoff line at the very edge).
351 const ROLL_CUT: f32 = 0.8;
352
353 fn roll_slope(f: f32) -> f32 {
354 let t = max(rrect_clip.p_light.w, 0.001);
355 let rr = select(1.0, window_info.relief_meta.y / t, window_info.relief_meta.y > 0.0);
356 return roll_slope_unit(f) * rr;
357 }
358
359 // The unit-rise roll (a quarter-round of radius t, or the custom edge LUT);
360 // roll_slope scales it by the pinned rise.
361 fn roll_slope_unit(f: f32) -> f32 {
362 // Custom edge profile: sample the uploaded ramp LUT. Face pixels saturate
363 // at f = 0 (the roll band's interior end), so taper the slope to zero
364 // there or every face pixel would inherit the curve's start slope; the
365 // silhouette end keeps whatever slope the curve was drawn ending on.
366 if (window_info.roll_meta.x > 0.5) {
367 let n = window_info.roll_meta.y;
368 let fcl = clamp(f, 0.0, 1.0);
369 let x = clamp(fcl * n - 0.5, 0.0, n - 1.0);
370 let i0 = u32(floor(x));
371 let i1 = min(i0 + 1u, u32(n) - 1u);
372 let fr = x - floor(x);
373 let s0 = window_info.roll_profile[i0 >> 2u][i0 & 3u];
374 let s1 = window_info.roll_profile[i1 >> 2u][i1 & 3u];
375 let win = clamp(fcl * n * 0.667, 0.0, 1.0);
376 return mix(s0, s1, fr) * win;
377 }
378 let shape = rrect_clip.rect1.w;
379 let fc = f * ROLL_CUT;
380 if (shape > 2.001) {
381 let h = pow(max(1.0 - pow(fc, shape), 1e-4), 1.0 / shape);
382 return pow(fc / h, shape - 1.0);
383 }
384 return fc / sqrt(max(1.0 - fc * fc, 1e-4));
385 }
386
387 // Slope of a carve's transition profile (0 on the surrounding plateau → 1 on
388 // the carve floor) at v in [0, 1] across the wall. With a custom profile
389 // installed (window_info.profile_meta.x), the slope comes from the uploaded
390 // ramp LUT — it may go negative (non-monotonic curves: rims, ogees) and its
391 // integral is the curve's net rise, not necessarily 1. Otherwise the analytic
392 // default: smoothstep normally, smootherstep (zero SECOND derivative at both
393 // plateaus) under a continuous-curvature corner_shape — the step's analog of
394 // the superellipse roll.
395 fn carve_slope(v: f32) -> f32 {
396 if (window_info.profile_meta.x > 0.5) {
397 let n = window_info.profile_meta.y;
398 let vc = clamp(v, 0.0, 1.0);
399 // Samples sit at v = (i + 0.5) / n; lerp between the two neighbors.
400 let x = clamp(vc * n - 0.5, 0.0, n - 1.0);
401 let i0 = u32(floor(x));
402 let i1 = min(i0 + 1u, u32(n) - 1u);
403 let fr = x - floor(x);
404 let s0 = window_info.profile[i0 >> 2u][i0 & 3u];
405 let s1 = window_info.profile[i1 >> 2u][i1 & 3u];
406 // The curve describes ONLY the wall band; the surfaces on either side
407 // are flat by definition, so taper to exactly zero at both ends
408 // (~1.5 samples). Without this every face pixel (v saturates at 1
409 // inside a feature) inherits the endpoint slope, and the SDF
410 // gradient's nearest-edge regions facet the face into triangles.
411 let win = clamp(min(vc, 1.0 - vc) * n * 0.667, 0.0, 1.0);
412 return mix(s0, s1, fr) * win;
413 }
414 if (rrect_clip.rect1.w > 2.001) {
415 let w = v * (1.0 - v);
416 return 30.0 * w * w;
417 }
418 return 6.0 * v * (1.0 - v);
419 }
420
421 // A carve's signed shading value `v` (a free carve's, or what the carves
422 // grouped into a plate add to its roll) composited over colour `c` the way
423 // the free-carve overlay is blended: positive screens toward white, negative
424 // multiplies toward black, |v| the alpha. Exactly `c` at v = 0.
425 fn carve_over(c: vec3f, v: f32) -> vec3f {
426 if (v >= 0.0) {
427 return mix(c, vec3f(1.0), min(v, 1.0));
428 }
429 return mix(c, vec3f(0.0), min(-v, 1.0));
430 }
431
432 // Per-pixel lighting of a plate. The plate is one composite height field:
433 // the host's rolled-edge surface minus every carve's profile, with the carve
434 // depth measured RELATIVE to the local surface (a deboss/etch, not a flat
435 // milling plane — a flat tool would swallow the perimeter roll wherever a
436 // band overlaps it, deleting the plate's own edge shading there). Heights
437 // subtract, so slope vectors ADD: the pixel's normal comes from the summed
438 // analytic slopes of every feature over it, and the junction where a carve's
439 // wall crosses the plate's perimeter roll is the smooth composite of both
440 // tilts, ending in the rim notch a real groove leaves. One normal per pixel —
441 // features never blend with each other. The roll is shaded relative to the
442 // flat face (shade ratio 1.0, specular delta 0.0) so the face keeps exactly
443 // the app's chosen color; what the carves add to it is composited as a free
444 // carve's overlay is (`carve_over`), so a carve reads the same grouped or not.
445 fn plate_shade(frag: vec2f, vcol: vec4f) -> vec4f {
446 let l = rrect_clip.p_light.xyz;
447 let strength = rrect_clip.p_mat.x;
448 let flat_shade = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * l.z;
449 // The mode arrives as a float only because the push block is all f32.
450 let mode = i32(round(rrect_clip.rect1.z));
451
452 // MODE_SPHERE: a sphere-lit disc (the slider thumb). p_rect.xy is the center,
453 // p_rect.z the radius, physical px. The disc is shaded as a hemisphere
454 // under the same light/material as the plates — ambient floor, diffuse off
455 // the sphere normal, the decoupled roll specular (its glint lands where
456 // the surface tilt meets the half-vector, ~a third of the way out toward
457 // the light) — and, like a plate face, the shade is expressed relative to
458 // the flat face so the color at the lit center is exactly the app's.
459 // MODE_GROUT: the vertex colour, flat, everywhere OUTSIDE a periodic
460 // field of identical rounded cells — the grid lines of a graph whose
461 // cells are whatever lies beneath showing through, corners included.
462 // The same fold as MODE_LATTICE (p_rect = one cell's centre and
463 // half-extents, p_host.xy = the period, p_radii = the corner radius),
464 // but no lighting: coverage is the cell SDF's outside, 1px anti-aliased,
465 // so the cells' superellipse corners are exact and the whole grid is one
466 // draw. Flat strips could never paint the notch a rounded cell leaves at
467 // each crossing.
468 if (mode == MODE_GROUT) {
469 let per = max(rrect_clip.p_host.xy, vec2f(1e-3));
470 var gc = frag - rrect_clip.p_rect.xy;
471 gc = gc - per * round(gc / per);
472 let lg = rr_sdf_grad(gc, vec4f(0.0, 0.0, rrect_clip.p_rect.zw), rrect_clip.p_radii);
473 let cov = clamp(lg.z + 0.5, 0.0, 1.0);
474 if (cov <= 0.0) {
475 discard;
476 }
477 return vec4f(vcol.rgb, vcol.a * cov);
478 }
479
480 if (mode == MODE_SPHERE) {
481 let c = frag - rrect_clip.p_rect.xy;
482 let r = max(rrect_clip.p_rect.z, 0.001);
483 let dist = length(c);
484 let aa = clamp(r - dist + 0.5, 0.0, 1.0); // 1px silhouette anti-aliasing
485 if (aa <= 0.0) {
486 discard;
487 }
488 let h = sqrt(max(r * r - dist * dist, 1e-3));
489 let n = vec3f(c / r, h / r); // unit on the sphere's surface
490 let diff = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n, l), 0.0);
491 let shade = 1.0 + (diff / flat_shade - 1.0) * strength;
492 let spec = roll_spec(c / h);
493 return vec4f(vcol.rgb * shade + rrect_clip.p_spec_tint.rgb * (spec * strength), vcol.a * aa);
494 }
495
496 // MODE_DROPLET: a hanging water droplet clinging to the box's TOP edge.
497 // Field reinterpretation (the push block cannot grow):
498 // p_rect = the droplet box, center + half-extents (like a plate);
499 // p_radii = [sag, belly radius, belly half-width, blend k] px;
500 // p_host = [sheet bottom-corner radius px, edge clarity 0-1, dome
501 // amplitude, attach (top-corner) radius px];
502 // p_spec_tint = [core density, contact-shadow reach px, contact-shadow
503 // strength, bottom-bow edge rise px] — a droplet's glint is always
504 // white, so the tint RGB slots are free;
505 // p_mat.w = fresnel rim crest amplitude (droplets carve nothing, so the
506 // AO slot is free); p_light.w = shaded band width px.
507 // The silhouette is the smooth union of a film SHEET attached to the top
508 // edge (square top corners — the attach line; bottom lifted by sag) and a
509 // BELLY capsule resting on the box bottom: the polynomial smin forms the
510 // waist/neck a real drop's surface tension pulls in. Shading reuses the
511 // plate vocabulary — roll_slope tilt over the band, ambient/diffuse,
512 // decoupled roll specular — plus two water terms: a fresnel rim crest
513 // (f³, like PLATE_CREST but tunable) and a thin-edge clarity falloff on
514 // the tint alpha, so the (compositor- or resolve_blur-) frosted backdrop
515 // shows through clearer at the rim.
516 if (mode == MODE_DROPLET || mode == MODE_DROPLET_SCRIM) {
517 let c = rrect_clip.p_rect.xy;
518 let hx = rrect_clip.p_rect.z;
519 let hy = rrect_clip.p_rect.w;
520 let sag = rrect_clip.p_radii.x;
521 let br = rrect_clip.p_radii.y;
522 let bw = rrect_clip.p_radii.z;
523 let k = max(rrect_clip.p_radii.w, 1.0);
524 let sr = rrect_clip.p_host.x;
525 let clarity = rrect_clip.p_host.y;
526 let dome = rrect_clip.p_host.z;
527 let ar = rrect_clip.p_host.w;
528
529 // Sheet: bottom lifted by sag; top corners carry the attach radius —
530 // the meniscus taper that curves the sides into the attach line (0 =
531 // the square-shouldered clinging-pool look).
532 let a_rect = vec4f(c.x, c.y - sag * 0.5, hx, hy - sag * 0.5);
533 let ga = rr_sdf_grad(frag, a_rect, vec4f(ar, ar, sr, sr));
534 var d = ga.z;
535 var g = ga.xy;
536 // Belly (radius > 0 only): a horizontal capsule resting on the box
537 // bottom, joined by polynomial smooth union — one drop, smooth neck.
538 // The gradient is the same weighted mix as the distance, renormalized.
539 if (br > 0.5) {
540 let b_rect = vec4f(c.x, c.y + hy - br, bw, br);
541 let gb = rr_sdf_grad(frag, b_rect, vec4f(br));
542 let hm = clamp(0.5 + 0.5 * (gb.z - ga.z) / k, 0.0, 1.0);
543 d = mix(gb.z, ga.z, hm) - k * hm * (1.0 - hm);
544 g = mix(gb.xy, ga.xy, hm);
545 }
546 // Bottom bow (p_spec_tint.w = edge rise, px): smooth-INTERSECT the
547 // drop with a disc whose lowest point touches the drop's bottom
548 // center — the bottom becomes one continuous circular arc, rising by
549 // the given amount at x = ±hx. The radius follows from that fixed
550 // rise (R = hx²/2·rise), so wide drops flatten toward the middle on
551 // their own. smax = -smin(-a,-b): same polynomial blend, sign flipped.
552 let bow = rrect_clip.p_spec_tint.w;
553 if (bow > 0.25) {
554 let bigr = hx * hx / (2.0 * bow);
555 let cc = vec2f(c.x, c.y + hy - bigr);
556 let pc = frag - cc;
557 let dl = max(length(pc), 1e-3);
558 let dc = dl - bigr;
559 let gc = pc / dl;
560 let hm2 = clamp(0.5 + 0.5 * (d - dc) / k, 0.0, 1.0);
561 d = mix(dc, d, hm2) + k * hm2 * (1.0 - hm2);
562 g = mix(gc, g, hm2);
563 }
564 g = normalize(g);
565
566 let din = -d;
567 let aa2 = clamp(din + 0.5, 0.0, 1.0);
568 // MODE_DROPLET_SCRIM: the same silhouette, filled flat and feathered
569 // inward — a vignette shaped exactly like the drop it sits in, for a
570 // caller that needs a legible ground under text without a second lit
571 // body. It shares this mode's SDF rather than approximating the shape
572 // with a rounded rect, which is the whole point: the two can never
573 // disagree about where the drop's edge is. p_light.w carries the
574 // feather (px) instead of the shading band, which is only read below.
575 if (mode == MODE_DROPLET_SCRIM) {
576 if (aa2 <= 0.0) {
577 discard;
578 }
579 let fth = max(rrect_clip.p_light.w, 0.001);
580 let sa2 = vcol.a * clamp(din / fth, 0.0, 1.0) * aa2;
581 if (sa2 <= 0.004) {
582 discard;
583 }
584 return vec4f(vcol.rgb, sa2);
585 }
586 if (aa2 <= 0.0) {
587 // Outside the silhouette: the contact shadow — a soft dark
588 // falloff cast below the drop's lower arc (weighted by the
589 // outward gradient's downward component, so the attach line and
590 // sides stay clean). The cover quad overhangs the box by the
591 // reach to give these fragments pixels to land on.
592 let sh_reach = rrect_clip.p_spec_tint.y;
593 let sh_amp = rrect_clip.p_spec_tint.z;
594 if (sh_reach < 0.5 || sh_amp <= 0.0) {
595 discard;
596 }
597 let down_sh = clamp(g.y, 0.0, 1.0);
598 let sfall = 1.0 - clamp(d / sh_reach, 0.0, 1.0);
599 let sa = sh_amp * sfall * sfall * down_sh;
600 if (sa <= 0.004) {
601 discard;
602 }
603 return vec4f(0.0, 0.0, 0.0, sa);
604 }
605 var base = vcol;
606 if (vcol.a < 0.0) {
607 // No recipe: every p_host slot is the drop's geometry. The
608 // kernel default, no compression (what a drop always drew).
609 base = resolve_blur(frag, vcol, vec2f(0.0), 0.0, 0.0, LEGACY_STRIDE);
610 }
611 let t2 = max(rrect_clip.p_light.w, 0.001);
612 let u = clamp(din / t2, 0.0, 1.0);
613 let f = 1.0 - u;
614 // Continuous dome: the drop is a spherical-cap height field over the
615 // silhouette — h = sqrt(2u - u²), vertical at the rim, flattening
616 // toward the interior — so the normal varies over the ENTIRE body
617 // and the diffuse rolls from lit shoulder to shaded belly instead of
618 // reading as a flat face inside a shaded band (the old roll_slope
619 // treatment, which only tilted the skirt).
620 let hdome = sqrt(max(2.0 * u - u * u, 1e-4));
621 let sv = g * ((1.0 - u) / hdome * dome);
622 let n = normalize(vec3f(sv, 1.0));
623 let diff = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n, l), 0.0);
624 // Rim crest weighted toward the BOTTOM edge (g.y > 0, y-down): a
625 // hanging drop concentrates transmitted light into a caustic along
626 // its lower arc, while the attach line stays quiet.
627 let down = clamp(g.y, 0.0, 1.0);
628 let extra = rrect_clip.p_mat.w * f * f * f * (0.3 + 1.2 * down * down);
629 let shade = 1.0 + (diff / flat_shade - 1.0 + extra) * strength;
630 let spec = roll_spec(sv);
631 // Thin edges are clearer water; the deep interior densifies by the
632 // core term (thickest water in the middle — the text's field).
633 let body = mix(clarity, 1.0 + rrect_clip.p_spec_tint.x, u);
634 return vec4f(
635 base.rgb * shade + vec3f(spec * strength),
636 min(abs(base.a) * body, 1.0) * aa2,
637 );
638 }
639
640 // MODE_FRAME is MODE_PLATE turned inside out: the box is the plate's
641 // HOLE, so the field is negated — the distance outside the box is the
642 // depth into the face, and the outward gradient points into the hole.
643 // Everything after is the plate's own branch: the roll falls into the
644 // hole, and a corner of the hole is a cove in the face.
645 let gd0 = rr_sdf_grad(frag, rrect_clip.p_rect, rrect_clip.p_radii);
646 let gd = select(gd0, -gd0, mode == MODE_FRAME);
647 let d = -gd.z; // positive inside the plate, in px
648 let t = max(rrect_clip.p_light.w, 0.001);
649
650 if (mode == MODE_PLATE || mode == MODE_FRAME) {
651 let aa = clamp(d + 0.5, 0.0, 1.0); // 1px silhouette anti-aliasing
652 if (aa <= 0.0) {
653 discard;
654 }
655 let u = clamp(d / t, 0.0, 1.0);
656 let f = 1.0 - u;
657 // Host roll slope vector: vertical at the silhouette, flat where the
658 // roll meets the face — then every carve's slope adds to it, and its
659 // shoulder/fillet ambient term joins the roll's crest.
660 var sv = gd.xy * roll_slope(f);
661 // The plate's OWN roll, kept apart from the carves added below: a
662 // focused plate's accent ring traces this alone (see the tinted
663 // branch), so the wells carved into it never wear the ring too.
664 let sv_rim = sv;
665
666 // Rim refraction, resolved BEFORE the shading below because the
667 // backdrop it bends is `base`.
668 //
669 // The roll is a real surface with a real tilt — `sv_rim` IS that tilt
670 // (the horizontal part of the unnormalized normal), already computed
671 // for the specular. Displacing the backdrop sample along it is what a
672 // curved edge does to what you see through it: the view compresses
673 // toward the silhouette and the plate stops being a rectangle of haze
674 // and starts being a slab with a thickness.
675 //
676 // Scaled by the roll width `t`, so a 12px bevel bends more than a 2px
677 // one and the effect tracks the plate's own geometry rather than
678 // drifting off it at another radius. The clarity ramp is f*f — the
679 // clear window belongs to the outer third of the roll, and the face
680 // must reach zero exactly or the whole plate unfrosts.
681 // The plate's own recipe, from its push block (see RRectClip.p_host).
682 let fz = rrect_clip.p_host.z;
683 let fhi = floor(fz / FROST_PACK_BASE);
684 let k_plate = clamp(fhi / FROST_PACK_MAX, 0.0, 1.0);
685 let refr = clamp((fz - fhi * FROST_PACK_BASE) / FROST_PACK_MAX, 0.0, 1.0);
686 let stride = rrect_clip.p_host.w * 0.5;
687 var base = vcol;
688 if (vcol.a < 0.0) {
689 base = resolve_blur(frag, vcol, sv_rim * (refr * t), refr * f * f, k_plate, stride);
690 }
691 // The roll's crest. The carves' shoulder/fillet terms are kept apart
692 // in `curv`: they composite as an overlay's do (below).
693 let crest = PLATE_CREST * f * f * f * crest_weight(gd.xy);
694 var curv = 0.0;
695 let f_off = u32(rrect_clip.p_host.x);
696 let f_cnt = u32(rrect_clip.p_host.y);
697 for (var i = 0u; i < f_cnt; i = i + 1u) {
698 let feat = plate_features.items[f_off + i];
699 let fg = rr_sdf_grad(frag, feat.rect, feat.radii);
700 let ft = max(feat.params.x, 0.001);
701 let v = clamp(-fg.z / ft + 0.5, 0.0, 1.0);
702 if (v <= 0.0) {
703 continue;
704 }
705 // params.y (depth) is signed: positive carves down, negative
706 // raises a boss. The slope vector follows automatically; the
707 // shoulder/fillet ambient term flips with it (a boss's convex
708 // shoulder is at the top of its wall, not the bottom).
709 sv += -(feat.params.y / ft) * carve_slope(v) * fg.xy;
710 curv += rrect_clip.p_mat.w * sin(v * TAU) * sign(feat.params.y);
711 }
712 // The roll alone, lit as a plate: a multiply on the face colour, plus
713 // the glint and its shade line in colour units.
714 let n_r = normalize(vec3f(sv_rim, 1.0));
715 let diff_r = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n_r, l), 0.0);
716 let shade_r = 1.0 + (diff_r / flat_shade - 1.0 + crest) * strength;
717 let spec_r = roll_spec(sv_rim);
718 let dark_r = roll_shade_line(sv_rim);
719 // The carves, as what they ADD to the roll's lighting — the summed
720 // slope's diffuse and glint less the roll's own, plus their
721 // curvature — composited the way a free carve's overlay is: a white
722 // screen up, a black multiply down (`carve_over`). On the face this
723 // is the overlay's `v` term for term, so a carve reads the same
724 // grouped or not; across the roll the normal is still the summed one,
725 // which is the junction grouping exists for. Not a multiply on the
726 // face colour, and no shade line: on a dark face a multiply barely
727 // moves the shoulder while the glint is added whole, and the shade
728 // line — a lobe at the half-vector's tilt — fired twice down every
729 // wall, as the tilt rose through that angle and fell back, each time
730 // subtracted to black: a doubled outline (2026-10-02).
731 let n = normalize(vec3f(sv, 1.0));
732 let diff = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n, l), 0.0);
733 let v_c = ((diff - diff_r) / flat_shade + curv + roll_spec(sv) - spec_r) * strength;
734 // p_spec_tint.w = 1 marks an accent-tinted plate (the focused-pane
735 // treatment). Neutral plates (w = 0) take the plain return below,
736 // byte-identical.
737 let tw = rrect_clip.p_spec_tint.w;
738 if (tw > 0.0) {
739 // A FILL-LESS tinted plate is a pure focus ring (the network
740 // cursor): there is no surface to light, so the specular line
741 // WRAPS — the glint the light-facing edges carry, run round the
742 // whole silhouette in the accent, on the plate's own roll — so
743 // the line traces the same superellipse silhouette, radius
744 // family, and inset as every node and pane, which a
745 // boundary-straddling carve band cannot (outward offsets of an
746 // Lp corner round off).
747 if (abs(base.a) < 0.004) {
748 return vec4f(rrect_clip.p_spec_tint.rgb, roll_spec_wrap(sv_rim) * strength * aa);
749 }
750 // A faced one keeps its relief and recolours it, exactly as a
751 // tinted carve does: the roll's light composites toward the
752 // accent instead of white (at FOCUS_GAIN), its shadow toward a
753 // dark accent instead of black — so the lit and shaded sides
754 // still differ as they do unfocused. The roll alone (sv_rim, and
755 // the crest, which lives on it): with the full slope every well
756 // carved into a focused plate — each parameter control on the
757 // designer's parameter pane — wore the accent too, reading as if
758 // every control were focused alongside the pane. The carves'
759 // neutral shading is composited over it unchanged.
760 let tint = rrect_clip.p_spec_tint.rgb;
761 let rim = base.rgb * shade_r + vec3f((spec_r - dark_r) * strength);
762 // The light: the alpha a carve would composite white at for the
763 // same rise in luminance, then that alpha in the accent.
764 let bl = dot(base.rgb, LUMA);
765 let dl = dot(rim, LUMA) - bl;
766 var lit = base.rgb;
767 if (dl >= 0.0) {
768 lit = mix(base.rgb, tint, min(dl / max(1.0 - bl, 0.05) * FOCUS_GAIN, 1.0));
769 } else {
770 // The shadow: the face's colour turned toward the accent's
771 // hue at the face's own luminance, then darkened to exactly
772 // the luminance the unfocused roll has here. So it is as dark
773 // as an unfocused shadow, never lighter, whatever the accent.
774 let bs = max(bl, 0.004);
775 let toward = tint * (bs / max(dot(tint, LUMA), 0.004));
776 let hued = mix(base.rgb, toward, min(-dl / bs * FOCUS_GAIN, 1.0));
777 lit = min(hued * (max(bl + dl, 0.0) / bs), vec3f(1.0));
778 }
779 return vec4f(carve_over(lit, v_c), abs(base.a) * aa);
780 }
781 let rolled = base.rgb * shade_r + rrect_clip.p_spec_tint.rgb * (spec_r * strength) - vec3f(dark_r * strength);
782 return vec4f(carve_over(rolled, v_c), abs(base.a) * aa);
783 }
784
785 if (mode == MODE_ROLL) {
786 // Fill-less rolled perimeter: MODE_PLATE's roll — same profile, crest
787 // and specular, spanning the full width INSIDE the silhouette — for a
788 // window whose face is not a plate fill (the designer's full-bleed 3D
789 // canvas). With no fill to shade into, it composites like the free
790 // carves: darkening is a black multiply, brightening a translucent
791 // white screen, over whatever is beneath. No CSG features: an overlay
792 // owns no surface, so carves never group into it (the tessellator
793 // never opens it as a host).
794 let aa = clamp(d + 0.5, 0.0, 1.0);
795 if (aa <= 0.0) {
796 discard;
797 }
798 let u = clamp(d / t, 0.0, 1.0);
799 let f = 1.0 - u;
800 let sv = gd.xy * roll_slope(f);
801 let extra = PLATE_CREST * f * f * f * crest_weight(gd.xy);
802 let n = normalize(vec3f(sv, 1.0));
803 let diff = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n, l), 0.0);
804 let spec = roll_spec(sv);
805 let dark = roll_shade_line(sv);
806 let v = (diff / flat_shade - 1.0 + extra + spec - dark) * strength * aa;
807 if (v >= 0.0) {
808 return vec4f(1.0, 1.0, 1.0, min(v, 1.0));
809 }
810 return vec4f(0.0, 0.0, 0.0, min(-v, 1.0));
811 }
812
813 // Free-floating recess, boss, or ridge (one not grouped into a host plate —
814 // e.g. in a widget's own paint): an overlay over whatever is painted
815 // beneath — no fill, no silhouette. Junction behavior here is the heuristic
816 // host-box fade; grouped features get the exact CSG above.
817 // MODE_RECESS = interior one step DOWN, MODE_BOSS = interior one step UP —
818 // the same wall with the height sign flipped. MODE_RIDGE is a
819 // raised bump straddling the boundary, both sides at the base level — ONE
820 // profile evaluation, so its crest carries a single specular/shoulder term
821 // instead of a boss+recess double-stack. MODE_TROUGH is that bump inverted
822 // (a valley), for the same reason: it replaced the recess-ring+boss stack
823 // `inset_plate` used to emit for every flush control in the DE.
824 // All profiles straddle the boundary (span [-t/2, t/2]). Darkening is exact
825 // multiplicative shading (black at alpha 1 - shade); brightening is a
826 // translucent white screen.
827 //
828 // Concave fillet (MODE_FILLET_DOWN / MODE_FILLET_UP): the wall follows a
829 // quarter ARC whose centre sits out in the pocket — the inside-corner
830 // rounding the box SDF cannot express. p_rect.xy = centre, .z = radius;
831 // p_radii.x = the wedge's start angle (quarter span, HARD-cut at the
832 // tangent lines — the straight walls continue the profile exactly there).
833 // Distance/gradient swap to radial; everything downstream is the shared
834 // free-carve path via `eff` (minus FILLET_TO_STEP: 6→RECESS, 7→BOSS).
835 var eff = mode;
836 var fd = d;
837 var fgd = gd.xy;
838 var wedge = 1.0;
839 // MODE_GROOVE: a SLAB carve — the band of half-width p_rect.z about the
840 // line through p_rect.xy with unit normal p_radii.xy. Distance is |signed
841 // distance to that line| minus the half-width, so ONE profile evaluation
842 // yields both walls (the gradient flips sign across the centre line, tilting
843 // them apart) and the groove costs a single specular term. The box SDF is
844 // axis-aligned by construction; this is how a mark runs at an angle.
845 // Rejoins the shared free-carve path as a recess (eff = 2).
846 if (mode == MODE_GROOVE) {
847 let nrm = rrect_clip.p_radii.xy;
848 let c = frag - rrect_clip.p_rect.xy;
849 let s = dot(c, nrm);
850 fd = abs(s) - rrect_clip.p_rect.z;
851 fgd = nrm * select(-1.0, 1.0, s >= 0.0);
852 eff = MODE_RECESS;
853 } else if (mode == MODE_LATTICE) {
854 // MODE_LATTICE: a periodic field of identical rounded wells. Fold
855 // the pixel into the period about one cell's centre (p_rect.xy;
856 // period in p_host.xy) and take the box distance to THAT cell —
857 // identical axis-aligned boxes centred in their period cells, so
858 // the folded cell is always the nearest one and this is the exact
859 // union distance of every well. One profile evaluation, so the
860 // rails between cells and the diagonals at each crossing are true
861 // mitres instead of stacked per-cell overlays. The wall runs from
862 // the cell edge OUTWARD: floor at the edge, plateau one run out.
863 //
864 // The wall's outer edge is NOT the offset curve (every point one run
865 // from the cell): that contour rounds each corner at radius + run,
866 // and with a run of half a rail the crossings read as big sweeping
867 // arcs while the cells themselves keep tight corners. A moulding
868 // does not offset its corners, it mitres them — so the outer edge is
869 // the cell box grown by the run with SHARP corners, and the wall is
870 // the fraction of the way across the band between the two contours
871 // (u = 1 at the cell edge, 0 at the outer contour). On the straight
872 // rails that is exactly distance / run; around a corner the band
873 // widens along the diagonal and four walls meet on the mitre lines.
874 // Sharp, not the cell's radius, so that where the run is half the
875 // rail the four outer boxes meet at a point and the crest lines run
876 // continuously through the crossing as hips — a rounded outer corner
877 // left a flat lozenge on top of every crossing. Lit by the cell's
878 // gradient. The -t/2 recentres the shared path's boundary-straddling
879 // band on [edge, edge + t].
880 let per = max(rrect_clip.p_host.xy, vec2f(1e-3));
881 var c = frag - rrect_clip.p_rect.xy;
882 c = c - per * round(c / per);
883 let lg = rr_sdf_grad(c, vec4f(0.0, 0.0, rrect_clip.p_rect.zw), rrect_clip.p_radii);
884 let lo = rr_sdf_grad(c, vec4f(0.0, 0.0, rrect_clip.p_rect.zw + vec2f(t)), vec4f(0.0));
885 let band = max(lg.z - lo.z, 1e-3);
886 let frac = clamp(lg.z / band, 0.0, 1.0);
887 fd = (0.5 - frac) * t;
888 fgd = lg.xy;
889 eff = MODE_RECESS;
890 } else if (mode == MODE_UNION) {
891 // MODE_UNION: the boxes in the feature run p_host.xy = [offset,
892 // count] are one shape. Each box's wall is MITRED like the lattice's:
893 // the band runs between the box shrunk by t/2 and the box grown by
894 // t/2, both at the box's own corner radius, and the pixel's position
895 // is its fraction across that band (an offset band would round the
896 // outer corners at radius + t/2). The union takes the box the pixel
897 // is deepest in — max over the run of the band coordinate, with that
898 // box's gradient — so a box's wall vanishes inside another and the
899 // outline is evaluated once. p_radii.x = 1 raises the union (boss)
900 // instead of carving it.
901 let u_off = u32(rrect_clip.p_host.x);
902 let u_cnt = u32(rrect_clip.p_host.y);
903 let hw = 0.5 * t;
904 var best = -1e9;
905 var bgrad = vec2f(0.0, -1.0);
906 for (var i = 0u; i < u_cnt; i = i + 1u) {
907 let feat = plate_features.items[u_off + i];
908 let inner = vec4f(feat.rect.xy, max(feat.rect.zw - vec2f(hw), vec2f(0.5)));
909 let outer = vec4f(feat.rect.xy, feat.rect.zw + vec2f(hw));
910 let gi = rr_sdf_grad(frag, inner, feat.radii);
911 let go = rr_sdf_grad(frag, outer, feat.radii);
912 let band = max(gi.z - go.z, 1e-3);
913 let fdi = (0.5 - clamp(gi.z / band, 0.0, 1.0)) * t;
914 if (fdi > best) {
915 best = fdi;
916 bgrad = gi.xy;
917 }
918 }
919 fd = best;
920 fgd = bgrad;
921 eff = select(MODE_RECESS, MODE_BOSS, rrect_clip.p_radii.x > 0.5);
922 } else if (mode == MODE_FIELD) {
923 // The whole field's outline (p_rect / p_radii) as it stands; the
924 // profile branch below blends its wall and adds the seam.
925 eff = MODE_FIELD;
926 } else if (mode == MODE_FILLET_DOWN || mode == MODE_FILLET_UP) {
927 eff = mode - FILLET_TO_STEP;
928 let c = frag - rrect_clip.p_rect.xy;
929 let dist = max(length(c), 1e-4);
930 fd = dist - rrect_clip.p_rect.z;
931 fgd = -c / dist;
932 let a0 = rrect_clip.p_radii.x;
933 let ang = atan2(c.y, c.x);
934 let rel = ang - a0 - floor((ang - a0) / TAU) * TAU;
935 wedge = select(0.0, 1.0, rel <= 1.5707964);
936 }
937 let u = clamp(fd / t + 0.5, 0.0, 1.0);
938 // Drop over run: the pinned height against THIS carve's wall, else the
939 // analytic ratio (the tessellator's CSG features apply the same rule).
940 let cd = select(RECESS_DEPTH, window_info.relief_meta.x / t, window_info.relief_meta.x > 0.0);
941 var slope = 0.0;
942 var curv = 0.0;
943 // A second wall's slope and curvature, summed with the outline's: the
944 // seam of a MODE_FIELD.
945 var sv_seam = vec2f(0.0);
946 var curv_seam = 0.0;
947 if (eff == MODE_FIELD) {
948 // A well (the interior one step DOWN) left of the seam at
949 // p_host.x, a flush run (a valley on the outline, the interior back
950 // at the surface) right of it — one outline. Three walls:
951 //
952 // * The OUTLINE, whose outer half — the fall from the surface to
953 // half the step — is the well's profile all the way round the
954 // field, so the edge never breaks. Over the well its inner half
955 // falls on to the floor; over the run it is not the outline's at
956 // all (below). (MODE_TROUGH fits its whole fall and rise into the
957 // wall's width, a compressed copy of a step that read differently
958 // from the well beside it; this valley's outer half IS the well's.)
959 // * The run's FACE, a rounded rect inset half a wall on every side
960 // — from the outline on the top, right and bottom, from the seam
961 // on the left — whose lip is the fall mirrored back up. Its left
962 // corners are its right corners, so the button reads the same at
963 // both ends: the same padding, the same rounding. Where the face's
964 // rounded corner leaves room by the straight outline, that is the
965 // valley's floor, flat.
966 // * The SEAM, the well's own right wall's inner half: from half the
967 // step at the seam down to the floor, meeting the face's lip at
968 // the seam where both stand at half the step. For a few hours on
969 // 2026-10-02 a ridge stood there instead, the button's valley
970 // rising to the surface and the well's wall falling from it a
971 // whole wall further left — the right side mirrored, which read as
972 // a strip of new surface between the well and the button. The
973 // button is that much wider now (its host lays it out from where
974 // the well's floor ends), so its padding about what it carries is
975 // even and nothing stands between it and the well.
976 //
977 // A field with no well (split left of it — a dropdown trigger, a
978 // button) is all run: the face inset from the outline all round,
979 // its own corners.
980 //
981 // The run ends at p_host.y. Past the field's right end (every form
982 // above) it reaches the outline there; short of it, a well lies to
983 // its right too, mirroring everything said of the left: the face
984 // inset half a wall from that seam with the corners of its LEFT end,
985 // and the seam the well's left wall's inner half. A toggle's run is
986 // half the field and glides between its ends, so mid-glide it has a
987 // well on both sides.
988 let split = rrect_clip.p_host.x;
989 let run_end = rrect_clip.p_host.y;
990 let hw = 0.5 * t;
991 let pr = rrect_clip.p_rect;
992 let fl = pr.x - pr.z;
993 let fr = pr.x + pr.z;
994 let has_well = split > fl + 0.5;
995 let has_well_r = run_end < fr - 0.5;
996 let run_l = select(fl, split, has_well);
997 let run_r = select(fr, run_end, has_well_r);
998 let fx0 = run_l + hw;
999 let fx1 = run_r - hw;
1000 let fy0 = pr.y - pr.w + hw;
1001 let fy1 = pr.y + pr.w - hw;
1002 let face = vec4f(0.5 * (fx0 + fx1), 0.5 * (fy0 + fy1), max(0.5 * (fx1 - fx0), 0.0), max(0.5 * (fy1 - fy0), 0.0));
1003 let rr = rrect_clip.p_radii;
1004 let rtl = max(rr.x - hw, 0.0);
1005 let rtr = max(rr.y - hw, 0.0);
1006 let rbr = max(rr.z - hw, 0.0);
1007 let rbl = max(rr.w - hw, 0.0);
1008 let face_r = vec4f(
1009 select(rtl, rtr, has_well),
1010 select(rtr, rtl, has_well_r),
1011 select(rbr, rbl, has_well_r),
1012 select(rbl, rbr, has_well),
1013 );
1014 // The outline: its outer half everywhere, its inner half over the
1015 // wells alone (`over_well`, antialiased across each seam's pixel).
1016 let over_well = clamp(
1017 1.0 - smoothstep(split - 0.5, split + 0.5, frag.x) + smoothstep(run_end - 0.5, run_end + 0.5, frag.x),
1018 0.0,
1019 1.0,
1020 );
1021 let inner = select(1.0, over_well, u > 0.5);
1022 slope = -cd * carve_slope(u) * inner;
1023 curv = rrect_clip.p_mat.w * sin(u * TAU) * inner;
1024 // The face's lip: half a wall wide, rising to the face.
1025 let gf = rr_sdf_grad(frag, face, face_r);
1026 let df = -gf.z;
1027 if (df >= -hw && df <= 0.0) {
1028 let uf = df / t + 1.0;
1029 sv_seam = gf.xy * (cd * carve_slope(1.0 - uf));
1030 curv_seam = rrect_clip.p_mat.w * sin((1.0 - uf) * TAU);
1031 }
1032 // The seam: the well's right wall, its inner half, faded out at the
1033 // outline (outside the field there is no well to fall into).
1034 if (has_well) {
1035 let us = (split - frag.x) / t + 0.5;
1036 if (us >= 0.5) {
1037 let usc = min(us, 1.0);
1038 let fade = clamp(d / hw, 0.0, 1.0);
1039 sv_seam = sv_seam + vec2f(1.0, 0.0) * (-cd * carve_slope(usc)) * fade;
1040 curv_seam = curv_seam + rrect_clip.p_mat.w * sin(usc * TAU) * fade;
1041 }
1042 }
1043 // The right-hand seam: the right well's LEFT wall, its inner half,
1044 // falling the other way.
1045 if (has_well_r) {
1046 let us = (frag.x - run_end) / t + 0.5;
1047 if (us >= 0.5) {
1048 let usc = min(us, 1.0);
1049 let fade = clamp(d / hw, 0.0, 1.0);
1050 sv_seam = sv_seam + vec2f(-1.0, 0.0) * (-cd * carve_slope(usc)) * fade;
1051 curv_seam = curv_seam + rrect_clip.p_mat.w * sin(usc * TAU) * fade;
1052 }
1053 }
1054 } else if (eff == MODE_RIDGE || eff == MODE_TROUGH) {
1055 // Ridge bump: the carve profile mirrored about the boundary (rising
1056 // outer half, falling inner half), amplitude halved so the wall tilt
1057 // matches a step's despite the doubled profile rate. MODE_TROUGH is the
1058 // same profile inverted — falling outer half, rising inner half — the
1059 // valley a flush inset control leaves. Sharing this branch is the point:
1060 // both get ONE evaluation, so neither can drift into the two-pass
1061 // double-shading the stacked form had.
1062 let w = clamp(select(2.0 * u, 2.0 - 2.0 * u, u > 0.5), 0.0, 1.0);
1063 let up = select(-1.0, 1.0, eff == MODE_RIDGE);
1064 let rising = select(-1.0, 1.0, u <= 0.5) * up;
1065 slope = rising * 0.5 * cd * 2.0 * carve_slope(w);
1066 // Each half-wall is a boss wall: concave fillet at its base, convex
1067 // shoulder toward the crest — and ZERO at the plateaus and crest, so
1068 // flat ground composites to exactly nothing (a constant term here
1069 // tints the whole cover quad). A trough's curvature flips with it: the
1070 // convex shoulders sit at the plateau lips, the concave fillet at the
1071 // floor.
1072 curv = -up * rrect_clip.p_mat.w * sin(w * TAU);
1073 } else {
1074 let dir = select(-1.0, 1.0, eff == MODE_BOSS);
1075 // The profile slope is carve_slope's family: smoothstep-derived
1076 // normally, smootherstep (zero second derivative at the plateaus)
1077 // under a continuous-curvature corner_shape — shading eases in and out
1078 // instead of starting on a line.
1079 slope = dir * cd * carve_slope(u);
1080 // Curvature: the convex shoulder catches ambient light, the concave
1081 // fillet self-occludes — on the outer half for a recess, inner for a
1082 // boss.
1083 curv = -dir * rrect_clip.p_mat.w * sin(u * TAU);
1084 }
1085 let sv = fgd * slope + sv_seam;
1086 let n = normalize(vec3f(sv, 1.0));
1087 let diff = PLATE_AMBIENT + (1.0 - PLATE_AMBIENT) * max(dot(n, l), 0.0);
1088 let spec = roll_spec(sv);
1089 // Fade the carve out across the host plate's perimeter roll (see p_host).
1090 // A field's p_host carries its seam instead, and it fades against nothing.
1091 let hb = rrect_clip.p_host;
1092 let host_d = min(hb.z - abs(frag.x - hb.x), hb.w - abs(frag.y - hb.y));
1093 let att = select(clamp(host_d / t, 0.0, 1.0), 1.0, eff == MODE_FIELD) * wedge;
1094 let v = (diff / flat_shade - 1.0 + curv + curv_seam + spec) * strength * att;
1095 // p_spec_tint.w = 1 marks a tinted carve — the FOCUS treatment. The
1096 // relief is the unfocused carve's, term for term; only its colours
1097 // change: the light composites in the accent instead of white, at
1098 // FOCUS_GAIN, and the shadow in the accent at FOCUS_SHADOW_LUM instead
1099 // of black, at the unfocused alpha — an overlay cannot see the surface
1100 // it darkens, so only a near-black accent is sure to darken it. So the
1101 // ring is the carve's own light and shadow, still reading which walls
1102 // face the lamp. Plates leave w at 0.
1103 let tw = rrect_clip.p_spec_tint.w;
1104 if (v >= 0.0) {
1105 let hl = mix(vec3f(1.0), rrect_clip.p_spec_tint.rgb, tw);
1106 return vec4f(hl, min(v * mix(1.0, FOCUS_GAIN, tw), 1.0));
1107 }
1108 let tint = rrect_clip.p_spec_tint.rgb;
1109 let sh = tint * (FOCUS_SHADOW_LUM * tw / max(dot(tint, LUMA), 0.004));
1110 return vec4f(min(sh, vec3f(1.0)), min(-v, 1.0));
1111 }
1112
1113 struct VertexOutput {
1114 @builtin(position) clip_position: vec4f,
1115 @location(0) color: vec4f,
1116 @location(1) ndc_position: vec2f,
1117 @location(2) clip_circle: vec3f,
1118 }
1119
1120 @vertex
1121 fn vs_main(
1122 @location(0) position: vec2f,
1123 @location(1) color: vec4f,
1124 @location(2) clip_circle: vec3f,
1125 ) -> VertexOutput {
1126 var out: VertexOutput;
1127 out.clip_position = vec4f(position, 0.0, 1.0);
1128 out.color = color;
1129 out.ndc_position = position;
1130 out.clip_circle = clip_circle;
1131 return out;
1132 }
1133
1134 @fragment
1135 fn fs_main(in: VertexOutput) -> @location(0) vec4f {
1136 // Wavy-blob effect (engine shader.wgsl): the -999 sentinel renders a
1137 // rippled, fading disc in NDC space.
1138 if (in.clip_circle.x == -999.0) {
1139 let y = length(vec2f(in.ndc_position.x, in.ndc_position.y));
1140 let x = atan2(in.ndc_position.y, in.ndc_position.x);
1141
1142 // Wavy boundary radius with 7 lobes
1143 let R_theta = 0.60 + 0.06 * sin(7.0 * x);
1144
1145 // Radial density: 1.0 at center, fading out to 0.0 at R_theta
1146 let density = 1.0 - smoothstep(R_theta - 0.25, R_theta, y);
1147
1148 // Sine wave effect driven by the x value (distance around the circle)
1149 let sin_effect = sin(7.0 * x);
1150
1151 // Normalized radius from 0.0 (center) to 1.0 (boundary)
1152 let r_normalized = clamp(y / R_theta, 0.0, 1.0);
1153
1154 let gray = in.color.xyz;
1155
1156 // Scale the ripple amplitude by the normalized radius to fade it out at the center
1157 let alpha = clamp(density * (1.0 - r_normalized * 0.25 * (1.0 - sin_effect)), 0.0, 1.0);
1158
1159 if (y > R_theta + 0.02) {
1160 discard;
1161 }
1162
1163 let final_alpha = alpha * (1.0 - smoothstep(R_theta - 0.02, R_theta + 0.02, y)) * in.color.w;
1164 return vec4f(gray, final_alpha);
1165 }
1166
1167 // Window-corner coverage: ~1px feather along the squircle silhouette in
1168 // place of the old hard circular discard, so the window edge, the 3D scene
1169 // fill, and the plates' tessellated corners all sit on the same curve.
1170 var clip_cov = 1.0 - smoothstep(-0.5, 0.5, window_corner_distance(in.clip_position.xy));
1171 if (clip_cov <= 0.0) {
1172 discard;
1173 }
1174 // Circular clip: ~1px feather folded into the coverage (mirroring the
1175 // rounded-rect clip below) — a clipped edge doubles as the silhouette AA
1176 // for circle prims drawn as cover quads.
1177 if (in.clip_circle.z > 0.0) {
1178 let dx = in.clip_position.x - in.clip_circle.x;
1179 let dy = in.clip_position.y - in.clip_circle.y;
1180 let dist = sqrt(dx * dx + dy * dy);
1181 clip_cov *= 1.0 - smoothstep(in.clip_circle.z - 0.5, in.clip_circle.z + 0.5, dist);
1182 if (clip_cov <= 0.0) {
1183 discard;
1184 }
1185 }
1186 // Rounded-rect clip (per-batch): the round-cornered box through rr_sdf_grad,
1187 // so the clipped silhouette follows the same corner_shape family (rect1.w:
1188 // circular arc at 2, superellipse squircle above) as the tessellated plate
1189 // corners around it, with a ~1px feather folded into the fragment alpha in
1190 // place of the old hard discard — a clipped edge and a drawn plate corner
1191 // share both curve and AA. Fully-outside fragments still discard.
1192 if (rrect_clip.rect1.y > 0.5) {
1193 let r = rrect_clip.rect1.x;
1194 let prect = vec4f(rrect_clip.rect0.xy, rrect_clip.rect0.zw + vec2f(r, r));
1195 let d = rr_sdf_grad(in.clip_position.xy, prect, vec4f(r)).z;
1196 clip_cov *= 1.0 - smoothstep(-0.5, 0.5, d);
1197 if (clip_cov <= 0.0) {
1198 discard;
1199 }
1200 }
1201
1202 // SDF-lit plate batch (mode in the push constants; see plate_shade).
1203 if (i32(round(rrect_clip.rect1.z)) != MODE_NONE) {
1204 let c = plate_shade(in.clip_position.xy, in.color);
1205 return vec4f(c.rgb, c.a * clip_cov);
1206 }
1207
1208 // A raw negative-alpha vertex with no plate block: geometry pushed from
1209 // outside the display list (a legacy host's own quads). No recipe to
1210 // read, so the kernel default and no compression. Everything the
1211 // display list frosts is a plate batch and never lands here.
1212 if (in.color.a < 0.0) {
1213 let c = resolve_blur(in.clip_position.xy, in.color, vec2f(0.0), 0.0, 0.0, LEGACY_STRIDE);
1214 return vec4f(c.rgb, c.a * clip_cov);
1215 }
1216
1217 return vec4f(in.color.rgb, in.color.a * clip_cov);
1218 }
1219
1220 // Blur-behind resolve for a negative-alpha plate color: frosted glass — the
1221 // FULLY blurred backdrop is the base (no clean-backdrop passthrough; mixing
1222 // the clean sample back in at plate opacity left translucent plates barely
1223 // blurred), tinted by the plate color at |alpha| opacity.
1224 //
1225 // `k_in` is the plate's luminance compression and `stride` its kernel's tap
1226 // spacing in physical px (sigma = 2 taps); both come from the plate's own
1227 // push block (MODE_PLATE), or are the no-recipe defaults (droplet, raw
1228 // vertices). A stride of 0 is a CLEAR plate: one clean sample, tinted.
1229 //
1230 // Every sample names its level explicitly: this runs under non-uniform
1231 // control flow (the blur branch), where WebGPU forbids the derivatives an
1232 // implicit LOD takes. The kernel's taps read the level that matches their
1233 // stride; the clean samples (a clear plate, the rim) read level 0.
1234 fn resolve_blur(pos: vec2f, color: vec4f, refract: vec2f, clarity: f32, k_in: f32, stride: f32) -> vec4f {
1235 let tex_size = vec2f(textureDimensions(t_backdrop));
1236
1237 var backdrop_color = vec4f(0.0);
1238 if (stride <= 0.0) {
1239 backdrop_color = textureSampleLevel(t_backdrop, s_backdrop, (pos + refract) / tex_size, 0.0);
1240 } else {
1241 var blurred = vec4f(0.0);
1242 var total_weight = 0.0;
1243 // 7x7 Gaussian kernel at `stride` px (sigma two taps, reach ±3
1244 // taps). The panel default is 5.5 px; a 2.5 px stride was
1245 // technically a blur but read as plain translucency — fine detail
1246 // beneath a frosted menu stayed legible, which is not what frosted
1247 // glass does.
1248 //
1249 // Each tap reads the mip level whose texel is one stride wide, so it
1250 // is the AVERAGE of the stride-sized cell it stands in. At level 0 a
1251 // tap read the texel or two it landed between, and detail thinner
1252 // than the stride — a hairline, a well's edge, a glyph — was picked
1253 // up whole by the taps that hit it and missed by those between:
1254 // seven faint copies a stride apart, horizontal bands under a menu
1255 // over rows. The blur snapshot carries the chain
1256 // (`snapshot_mip_chain`); the scene backdrop has one level, which
1257 // every level clamps to.
1258 let lod = max(log2(stride), 0.0);
1259 for (var x = -3.0; x <= 3.0; x += 1.0) {
1260 for (var y = -3.0; y <= 3.0; y += 1.0) {
1261 let offset = vec2f(x, y) * stride;
1262 let sample_uv = (pos + offset) / tex_size;
1263 let weight = exp(-(x*x + y*y) / (2.0 * 2.0 * 2.0));
1264 blurred += textureSampleLevel(t_backdrop, s_backdrop, sample_uv, lod) * weight;
1265 total_weight += weight;
1266 }
1267 }
1268 backdrop_color = blurred / total_weight;
1269 }
1270
1271 // The rim's clear window onto the backdrop.
1272 //
1273 // Refraction has to sample something with STRUCTURE or it is invisible:
1274 // displacing a field that has already been blurred to sigma ~11px moves
1275 // smooth values around and reads as nothing at all. So the rim takes a
1276 // CLEAN sample, displaced by the roll's tilt, and cross-fades to the
1277 // frosted body — which is also what a real slab does, its thin edge
1278 // scattering over a shorter path than its thick middle (the droplet
1279 // branch already trades on that: "thin edges are clearer water").
1280 //
1281 // One extra tap, not three: per-channel dispersion inside a band this
1282 // narrow is invisible once the body blur is 49 taps, and paying for it
1283 // would triple the most expensive path in this shader to be erased.
1284 if (clarity > 0.001) {
1285 let clean = textureSampleLevel(t_backdrop, s_backdrop, (pos + refract) / tex_size, 0.0);
1286 backdrop_color = mix(backdrop_color, clean, clamp(clarity, 0.0, 1.0));
1287 }
1288
1289 let opacity = -color.a;
1290
1291 // Luminance-range compression, the plate's legibility control.
1292 //
1293 // The blur above destroys the backdrop's spatial DETAIL and preserves its
1294 // mean LUMINANCE — and text contrast is a mean-luminance property, so on
1295 // its own the mix below hands the backdrop's brightness straight through
1296 // at (1 - opacity). At the designer dialog's 0.25 that is 75% of whatever
1297 // is behind it: over the dark viewport a row label runs ~12:1, over
1298 // something bright ~1.2:1, which is not a contrast ratio so much as its
1299 // absence. No amount of extra blur moves either number.
1300 //
1301 // So remap the backdrop's luminance toward the plate's own key, keeping
1302 // its chromaticity. This is not "darken" and not opacity: it is
1303 // SYMMETRIC, pulling a bright backdrop down and a dark one UP, so what it
1304 // removes is the plate's swing through the ink's luminance rather than
1305 // the view through it. Hue, chroma and movement all still read.
1306 // Compression is a LEGIBILITY control and the rim carries no text, so the
1307 // clear window opened there is exempt in proportion to how clear it is.
1308 // Tone-mapping it would pull the refracted view back toward the plate's
1309 // own key — the exact contrast the rim exists to show — and the effect
1310 // measured nearly invisible with the two fighting.
1311 let k = clamp(k_in, 0.0, 1.0) * (1.0 - clamp(clarity, 0.0, 1.0));
1312 let W = vec3f(0.2126, 0.7152, 0.0722);
1313 let bl = dot(backdrop_color.rgb, W);
1314 let key = dot(color.rgb, W);
1315 // `target` is a WGSL reserved word.
1316 let keyed = mix(bl, key, k);
1317 // Scaling by keyed/bl holds chromaticity exactly. The hazard is the
1318 // RATIO: lifting a near-black backdrop toward a bright key multiplies
1319 // its 8-bit chroma by tens — banding, then channels clipping past 1 —
1320 // so the guard cross-fades to the neutral key luminance as the lift
1321 // grows, over ratio 2..8. Keyed to the ratio rather than to the
1322 // backdrop's luminance (the pre-2026-09-20 form: any backdrop under 5%
1323 // linear went neutral whenever k was non-zero at all), it is continuous
1324 // in k: at k = 0 the ratio is 1 and nothing happens, at a hair above 0
1325 // nearly nothing, and a pull DOWN toward a dark key (ratio < 1) never
1326 // touches the hue — the measured case: a navy viewport under a
1327 // #101018 tint kept going grey at k = 0.01. The select keeps k = 0 an
1328 // exact identity (the ratio's 1e-4 floor would otherwise darken true
1329 // black by a hair).
1330 let ratio = keyed / max(bl, 1e-4);
1331 let scaled = backdrop_color.rgb * ratio;
1332 let guard = smoothstep(2.0, 8.0, ratio);
1333 let guarded = mix(scaled, vec3f(keyed), guard);
1334 let compressed = select(guarded, backdrop_color.rgb, k <= 0.0);
1335
1336 return vec4f(mix(compressed, color.rgb, opacity), 1.0);
1337 }