cvkg-render-gpu 0.1.7

Cyberpunk Viking Knowledge Graph (CVKG) - High-fidelity agentic UI framework
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
// =============================================================================
// CYBERPUNK VIKING BERZERKER SHADER
// Obsidian Glassmorphism · Neon Cyan Illumination · Magenta Shatter Physics
// -----------------------------------------------------------------------------
// SwiftUI-inspired architecture: declarative uniform structs, modular fn blocks,
// composable visual layers, and a single themeable ColorTheme binding.
// Compatible with wgpu / Bevy / any WebGPU-based Rust renderer.
// =============================================================================


// -----------------------------------------------------------------------------
// SECTION 1 — THEME UNIFORMS
// Bind group 0, binding 0: update at runtime to retheme everything.
// SwiftUI analogy: @Environment(.colorScheme) / @Binding var theme: Theme
// -----------------------------------------------------------------------------
struct ColorTheme {
    // Core palette — vec4<f32> = (R, G, B, intensity_multiplier)
    primary_neon:    vec4<f32>,  // default: cyan    (0.0, 1.0, 0.95, 1.2)
    shatter_neon:    vec4<f32>,  // default: magenta (1.0, 0.0, 0.75, 1.5)
    glass_base:      vec4<f32>,  // default: obsidian black (0.04, 0.04, 0.06, 0.82)
    glass_edge:      vec4<f32>,  // default: dark cyan rim  (0.0, 0.45, 0.55, 0.6)
    rune_glow:       vec4<f32>,  // default: pale ice  (0.75, 0.98, 1.0, 0.9)
    ember_core:      vec4<f32>,  // default: berzerker blood (0.95, 0.12, 0.12, 1.0)
    background_deep: vec4<f32>,  // default: void black (0.01, 0.01, 0.03, 1.0)
    // Scalar controls
    glass_blur_strength:  f32,   // 0.0–1.0, default 0.6
    shatter_edge_width:   f32,   // pixels, default 1.8
    neon_bloom_radius:    f32,   // 0.0–0.05, default 0.022
    rune_opacity:         f32,   // 0.0–1.0, default 0.55
    // Padding to ensure 16-byte alignment for GPU uniforms
    _pad0: f32,
    _pad1: f32,
    _pad2: f32,
    _pad3: f32,
};

@group(0) @binding(0)
var<uniform> theme: ColorTheme;


// -----------------------------------------------------------------------------
// SECTION 2 — SCENE UNIFORMS
// Bind group 0, binding 1: time, resolution, interaction inputs.
// SwiftUI analogy: @State / @Published scene state driving view updates.
// -----------------------------------------------------------------------------
struct SceneUniforms {
    view:            mat4x4<f32>,
    proj:            mat4x4<f32>,
    time:            f32,   // seconds elapsed
    delta_time:      f32,   // frame delta for physics
    resolution:      vec2<f32>,
    mouse:           vec2<f32>,   // normalized 0..1
    mouse_velocity:  vec2<f32>,   // for shatter impulse
    shatter_origin:  vec2<f32>,   // epicenter of last shatter event
    shatter_time:    f32,         // timestamp of last shatter (for animation)
    shatter_force:   f32,         // 0.0–1.0 impact magnitude
    berzerker_rage:  f32,
    scroll_offset:   f32,
    _pad:            vec2<f32>,
};

@group(0) @binding(1)
var<uniform> scene: SceneUniforms;


// SECTION 3 — VERTEX STAGE
// Receives vertex data from the SurtrRenderer's vertex buffer.
// -----------------------------------------------------------------------------
struct VertexInput {
    @location(0) position: vec3<f32>,
    @location(1) normal:   vec3<f32>,
    @location(2) uv:       vec2<f32>,
    @location(3) color:    vec4<f32>,
    @location(4) mode:     u32,
    @location(5) radius:   f32,
    @location(6) slice:    vec3<f32>,
    @location(7) logical:  vec2<f32>,
    @location(8) size:     vec2<f32>,
    @location(9) screen:   vec2<f32>,
    @location(10) clip:    vec4<f32>,
};

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) uv:          vec2<f32>,
    @location(1) color:       vec4<f32>,
    @location(2) @interpolate(flat) mode: u32,
    @location(3) radius:      f32,
    @location(4) slice:       vec3<f32>,
    @location(5) logical:     vec2<f32>,
    @location(6) size:        vec2<f32>,
    @location(7) screen:      vec2<f32>,
    @location(8) normal:      vec3<f32>,
    @location(9) clip:        vec4<f32>,
};

@vertex
fn vs_main(in: VertexInput) -> VertexOutput {
    var out: VertexOutput;
    
    // Check if we are in 2D mode (mode < 100) or 3D mode
    if in.mode < 100u {
        // 2D UI Path: Convert pixel coordinates to NDC
        let ndc_x = (in.position.x / scene.resolution.x) * 2.0 - 1.0;
        let ndc_y = 1.0 - (in.position.y / scene.resolution.y) * 2.0;
        out.clip_position = vec4<f32>(ndc_x, ndc_y, 0.0, 1.0);
    } else {
        // 3D/Visualization Path: Use MVP matrices
        out.clip_position = scene.proj * scene.view * vec4<f32>(in.position, 1.0);
    }
    
    out.uv = in.uv;
    out.color = in.color;
    out.mode = in.mode;
    out.radius = in.radius;
    out.slice = in.slice;
    out.logical = in.logical;
    out.size = in.size;
    out.screen = in.screen;
    out.normal = in.normal;
    out.clip = in.clip;
    
    return out;
}


// =============================================================================
// SECTION 4 — MATH & UTILITY LIBRARY
// Pure functions — no side effects, fully composable.
// SwiftUI analogy: ViewModifier / extension on View
// =============================================================================

// --- 2D rotation matrix (standard CCW)
fn rot2(angle: f32) -> mat2x2<f32> {
    let s = sin(angle);
    let c = cos(angle);
    return mat2x2<f32>(c, s, -s, c);
}

// --- Hash / noise primitives (GPU-friendly, no texture dependency)
fn hash11(p: f32) -> f32 {
    var x = fract(p * 0.1031);
    x *= x + 33.33;
    x *= x + x;
    return fract(x);
}

// --- Heatmap Palette
fn heatmap_palette(t: f32) -> vec3<f32> {
    let low = vec3<f32>(0.0, 0.05, 0.2);
    let mid = theme.primary_neon.rgb;
    let high = theme.shatter_neon.rgb;
    return mix(mix(low, mid, smoothstep(0.0, 0.5, t)), high, smoothstep(0.5, 1.0, t));
}

fn hash21(p: vec2<f32>) -> f32 {
    var p3 = fract(vec3<f32>(p.xyx) * 0.1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

fn hash22(p: vec2<f32>) -> vec2<f32> {
    var p3 = fract(vec3<f32>(p.xyx) * vec3<f32>(0.1031, 0.1030, 0.0973));
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.xx + p3.yz) * p3.zy);
}

// --- Value noise 2D (smooth)
fn vnoise(p: vec2<f32>) -> f32 {
    let i = floor(p);
    let f = fract(p);
    let u = f * f * (3.0 - 2.0 * f);
    return mix(
        mix(hash21(i + vec2<f32>(0.0, 0.0)), hash21(i + vec2<f32>(1.0, 0.0)), u.x),
        mix(hash21(i + vec2<f32>(0.0, 1.0)), hash21(i + vec2<f32>(1.0, 1.0)), u.x),
        u.y
    );
}

// --- Fractal Brownian Motion (fBm) — 5 octaves
fn fbm(p: vec2<f32>) -> f32 {
    var val  = 0.0;
    var amp  = 0.5;
    var freq = 1.0;
    var pp   = p;
    for (var i = 0; i < 5; i++) {
        val += amp * vnoise(pp * freq);
        freq *= 2.1;
        amp  *= 0.5;
        pp = pp * rot2(0.37);
    }
    return val;
}

// --- Signed distance: line segment (for rune strokes)
fn sd_segment(p: vec2<f32>, a: vec2<f32>, b: vec2<f32>) -> f32 {
    let pa = p - a;
    let ba = b - a;
    let h  = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
    return length(pa - ba * h);
}

// --- Signed distance: box
fn sd_box(p: vec2<f32>, b: vec2<f32>) -> f32 {
    let d = abs(p) - b;
    return length(max(d, vec2<f32>(0.0))) + min(max(d.x, d.y), 0.0);
}

// --- Equilateral Triangle SDF
fn sd_triangle(p: vec2<f32>, r: f32) -> f32 {
    let k = sqrt(3.0);
    var pp = p;
    pp.x = abs(pp.x) - r;
    pp.y = pp.y + r / k;
    if (pp.x + k * pp.y > 0.0) {
        pp = vec2<f32>(pp.x - k * pp.y, -k * pp.x - pp.y) / 2.0;
    }
    pp.x -= clamp(pp.x, -2.0 * r, 0.0);
    return -length(pp) * sign(pp.y);
}

// --- Ellipse SDF (Approximate)
fn sd_ellipse(p: vec2<f32>, r: vec2<f32>) -> f32 {
    let k0 = length(p / r);
    let k1 = length(p / (r * r));
    return k0 * (k0 - 1.0) / k1;
}

// --- Rounded Rectangle SDF
fn sd_round_rect(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32 {
    let d = abs(p) - b;
    return length(max(d, vec2<f32>(0.0))) + min(max(d.x, d.y), 0.0) - r;
}

// --- Smooth minimum (organic blending)
fn smin(a: f32, b: f32, k: f32) -> f32 {
    let h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
    return mix(b, a, h) - k * h * (1.0 - h);
}

// --- Neon glow falloff: sharp core + soft bloom
fn neon_glow(dist: f32, width: f32, bloom: f32) -> f32 {
    let core  = smoothstep(width, 0.0, dist);
    let glow  = exp(-dist * dist / (bloom * bloom));
    return core + glow * 0.6;
}

// --- Chromatic aberration offset
fn chrom_aberr(uv: vec2<f32>, offset: f32) -> vec2<f32> {
    return uv + normalize(uv - vec2<f32>(0.5)) * offset;
}

// ── 3D SDF Library ──────────────────────────────────────────────────────────
fn sd_sphere(p: vec3<f32>, s: f32) -> f32 {
    return length(p) - s;
}

fn sd_box_3d(p: vec3<f32>, b: vec3<f32>) -> f32 {
    let q = abs(p) - b;
    return length(max(q, vec3<f32>(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0);
}

fn scene_sdf(p: vec3<f32>) -> f32 {
    let s1 = sd_sphere(p - vec3<f32>(0.0, 0.2 * sin(scene.time), 0.0), 0.4);
    let b1 = sd_box_3d(p - vec3<f32>(0.6, 0.0, 0.0), vec3<f32>(0.2, 0.2, 0.2));
    return smin(s1, b1, 0.1);
}

fn ray_march(ro: vec3<f32>, rd: vec3<f32>) -> f32 {
    var t = 0.0;
    for (var i = 0; i < 64; i++) {
        let d = scene_sdf(ro + rd * t);
        if d < 0.001 { return t; }
        if t > 20.0  { break; }
        t += d;
    }
    return -1.0;
}

fn calc_normal(p: vec3<f32>) -> vec3<f32> {
    let e = vec2<f32>(0.001, 0.0);
    return normalize(vec3<f32>(
        scene_sdf(p + e.xyy) - scene_sdf(p - e.xyy),
        scene_sdf(p + e.yxy) - scene_sdf(p - e.yxy),
        scene_sdf(p + e.yyx) - scene_sdf(p - e.yyx),
    ));
}

// -----------------------------------------------------------------------------
// SECTION 5 — FRAGMENT STAGE
// -----------------------------------------------------------------------------
@group(1) @binding(0) var t_diffuse: texture_2d<f32>;
@group(1) @binding(1) var s_diffuse: sampler;

@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
    // Mode 0: Primitive / Panel
    // Mode 1: Neon Line / Gungnir
    // Mode 2: Texture Map
    // Mode 3: Rounded Rect Panel
    // Mode 4: Ellipse
    // Mode 5: Shatter Shard
    // Mode 6: Text Atlas
    // Mode 7: Bifrost Glassmorphism
    // Mode 8: Mjolnir Shatter Grid
    // Mode 9: Lightning Bolt
    // Mode 10: Runes
    // Mode 11: Mjolnir Fluid
    // Mode 12: Heatmap
    // Mode 13: 3D Surface
    // Mode 14: Ray Marched Reflections
    // Mode 15: Linear Gradient
    // Mode 16: Radial Gradient
    // Mode 17: Stroked Rounded Rect
    // Mode 18: Drop Shadow
    // Mode 19: Dashed Border
    var color = in.color;
    let fw = length(vec2(dpdx(in.logical.x), dpdy(in.logical.y)));
    
    // ── Global Clipping (SDF-based) ──────────────────────────────────────────
    let clip_pos = in.clip.xy;
    let clip_size = in.clip.zw;
    let clip_d = sd_box(in.position.xy - (clip_pos + clip_size * 0.5), clip_size * 0.5);
    let clip_alpha = 1.0 - smoothstep(-fw, fw, clip_d);
    color.a *= clip_alpha;
    if color.a <= 0.0 { discard; }
    
    if in.mode == 3u {
        // Mode 3: Rounded Rect Panel
        let half_size = in.size * 0.5;
        let d = sd_round_rect(in.logical - half_size, half_size - in.radius, in.radius);
        let alpha = 1.0 - smoothstep(-fw, fw, d);
        color.a *= alpha;
        if color.a <= 0.0 { discard; }
    } else if in.mode == 4u {
        // Mode 4: Ellipse
        let d = length((in.uv - 0.5) * 2.0) - 1.0;
        let alpha = 1.0 - smoothstep(-fw, fw, d);
        color.a *= alpha;
        if color.a <= 0.0 { discard; }
    } else if in.mode == 5u {
        // Shatter Shard SDF
        let p = (in.uv - 0.5) * 2.0;
        let d = sd_triangle(p, 0.01);
        let alpha = 1.0 - smoothstep(-fw, fw, d);
        if alpha <= 0.0 { discard; }
        // Add neon edge
        let edge = smoothstep(0.01, 0.0, abs(d));
        color = mix(color, theme.shatter_neon, edge);
    } else if in.mode == 7u {
        // Mode 7: Bifrost (Advanced Glassmorphism)
        let uv_dist = sd_box(in.uv - 0.5, vec2<f32>(0.495));
        
        // Refraction & Chromatic Aberration
        let refraction = 0.005 * (1.0 - smoothstep(0.0, 0.1, abs(uv_dist)));
        let r = textureSample(t_diffuse, s_diffuse, in.uv + vec2<f32>(refraction, 0.0)).r;
        let g = textureSample(t_diffuse, s_diffuse, in.uv).g;
        let b = textureSample(t_diffuse, s_diffuse, in.uv - vec2<f32>(refraction, 0.0)).b;
        let blur_color = vec4<f32>(r, g, b, 1.0);
        
        // Frosted Grain Noise
        let grain = hash21(in.position.xy + scene.time) * 0.04;
        let base = mix(blur_color, theme.glass_base, theme.glass_base.a) + grain;
        
        // Edge Highlight & Specular
        let edge_mask = smoothstep(-0.01, 0.0, uv_dist);
        var final_color = mix(base, theme.glass_edge, (1.0 - edge_mask) * theme.glass_edge.a);
        
        // Specular Light Catch
        let light_dir = normalize(vec2<f32>(1.0, -1.0));
        let normal = normalize(vec2<f32>(dpdx(uv_dist), dpdy(uv_dist)));
        let spec = pow(max(dot(normal, light_dir), 0.0), 16.0) * 0.2;
        final_color += spec * theme.primary_neon;
        
        color = final_color;
    } else if in.mode == 8u || in.mode == 11u {
        // Mode 8/11: Mjolnir Shatter
        var p = (in.uv - 0.5) * 2.0;
        if in.mode == 11u {
            p += fbm(p * 5.0 + vec2<f32>(scene.time, scene.time * 0.7)) * 0.2;
        }
        let d = sd_triangle(p, 0.05);
        let alpha = 1.0 - smoothstep(-fw, fw, d);
        if alpha <= 0.0 { discard; }
        color.a *= alpha;
        color = mix(color, theme.shatter_neon, smoothstep(0.05, 0.0, abs(d)));
    } else if in.mode == 9u {
        // Mode 9: Gungnir Bolt (Lightning Glow)
        let d = length((in.uv - 0.5) * vec2<f32>(1.0, 4.0));
        let glow = neon_glow(d, 0.01, 0.2);
        color = theme.primary_neon * glow;
    } else if in.mode == 10u {
        // Mode 10: Runes (SDF Strokes)
        let p = (in.uv - 0.5) * 2.0;
        let d1 = sd_segment(p, vec2<f32>(-0.5, -0.8), vec2<f32>(0.5, 0.8));
        let d2 = sd_segment(p, vec2<f32>(0.5, -0.8), vec2<f32>(-0.5, 0.8));
        let d = min(d1, d2);
        let glow = neon_glow(d, 0.02, 0.15);
        color = theme.rune_glow * glow * theme.rune_opacity;
    } else if in.mode == 12u {
        // Mode 12: Heatmap
        let val = textureSample(t_diffuse, s_diffuse, in.uv).r;
        color = vec4<f32>(heatmap_palette(val), in.color.a);
    } else if in.mode == 13u {
        // Mode 13: 3D Surface
        // Simple diffuse lighting
        let light_dir = normalize(vec3<f32>(0.5, 0.5, 1.0));
        let diff = max(dot(in.normal, light_dir), 0.2);
        color = vec4<f32>(in.color.rgb * diff, in.color.a);
    } else if in.mode == 14u {
        // Mode 14: Ray Marched Reflections
        let ro = vec3<f32>(in.uv.x - 0.5, in.uv.y - 0.5, -2.0);
        let rd = normalize(vec3<f32>(in.uv.x - 0.5, in.uv.y - 0.5, 1.0));
        let t = ray_march(ro, rd);
        if t > 0.0 {
            let p = ro + rd * t;
            let n = calc_normal(p);
            let light_dir = normalize(vec3<f32>(1.0, 1.0, -1.0));
            let diff = max(dot(n, light_dir), 0.2);
            let ref_rd = reflect(rd, n);
            let ref_t = ray_march(p + n * 0.01, ref_rd);
            var reflection_color = vec3<f32>(0.05, 0.05, 0.1);
            if ref_t > 0.0 {
                reflection_color = mix(theme.primary_neon.rgb, theme.shatter_neon.rgb, 0.5);
            }
            let final_rgb = mix(in.color.rgb * diff, reflection_color, 0.3);
            color = vec4<f32>(final_rgb, 1.0);
        } else {
             discard;
        }
    } else if in.mode == 15u {
        // Mode 15: Linear Gradient (Animated)
        let angle = in.slice.x + scene.time * 0.5;
        let dir = vec2<f32>(cos(angle), sin(angle));
        let t = dot(in.uv - 0.5, dir) + 0.5;
        color = mix(in.color, theme.primary_neon, clamp(t, 0.0, 1.0));
    } else if in.mode == 16u {
        // Mode 16: Radial Gradient
        let t = length(in.uv - 0.5) * 2.0;
        color = mix(in.color, theme.primary_neon, clamp(t, 0.0, 1.0));
    } else if in.mode == 17u {
        // Mode 17: Stroked Rounded Rect
        let half_size = in.size * 0.5;
        let d = sd_round_rect(in.logical - half_size, half_size - in.radius, in.radius);
        let thickness = max(in.slice.x, 1.0);
        let d_stroke = abs(d + thickness * 0.5) - thickness * 0.5;
        let alpha = 1.0 - smoothstep(-fw, fw, d_stroke);
        color.a *= alpha;
        if color.a <= 0.0 { discard; }
    } else if in.mode == 18u {
        // Mode 18: Drop Shadow
        let half_size = in.size * 0.5;
        let d = sd_round_rect(in.logical - half_size, half_size - in.radius, in.radius);
        let blur = max(in.slice.x, 1.0);
        let shadow = 1.0 - smoothstep(-blur, blur, d - in.slice.y);
        color = vec4<f32>(in.color.rgb, in.color.a * shadow);
        if color.a <= 0.0 { discard; }
    } else if in.mode == 19u {
        // Mode 19: Dashed Border
        let half_size = in.size * 0.5;
        let d = sd_round_rect(in.logical - half_size, half_size - in.radius, in.radius);
        let thickness = max(in.slice.x, 1.0);
        let dash = max(in.slice.y, 1.0);
        let gap = max(in.slice.z, 1.0);
        let perimeter = (in.uv.x + in.uv.y) * max(in.size.x, in.size.y);
        let pattern = (perimeter + scene.time * 20.0) % (dash + gap);
        var alpha = 1.0 - smoothstep(-fw, fw, abs(d + thickness * 0.5) - thickness * 0.5);
        if pattern > dash { alpha = 0.0; }
        color.a *= alpha;
        if color.a <= 0.0 { discard; }
    } else if in.mode == 20u {
        // Mode 20: 9-Slice / Patch Scaling
        // slice = [left, top, right], radius = bottom (normalized 0..1 of texture)
        let l = in.slice.x;
        let t = in.slice.y;
        let r = in.slice.z;
        let b = in.radius;
        
        var uv = in.uv;
        // X-axis remapping
        if uv.x < l {
            uv.x = uv.x * (0.33 / l);
        } else if uv.x > (1.0 - r) {
            uv.x = 0.66 + (uv.x - (1.0 - r)) * (0.34 / r);
        } else {
            uv.x = 0.33 + (uv.x - l) / (1.0 - l - r) * 0.33;
        }
        // Y-axis remapping
        if uv.y < t {
            uv.y = uv.y * (0.33 / t);
        } else if uv.y > (1.0 - b) {
            uv.y = 0.66 + (uv.y - (1.0 - b)) * (0.34 / b);
        } else {
            uv.y = 0.33 + (uv.y - t) / (1.0 - t - b) * 0.33;
        }
        
        color *= textureSample(t_diffuse, s_diffuse, uv);
    } else if in.mode == 21u {
        // Mode 21: Stroked Ellipse
        let d = sd_ellipse((in.uv - 0.5) * 2.0, vec2<f32>(1.0));
        let thickness = max(in.slice.x, 0.01);
        let d_stroke = abs(d + thickness * 0.5) - thickness * 0.5;
        let alpha = 1.0 - smoothstep(-fw, fw, d_stroke);
        color.a *= alpha;
        if color.a <= 0.0 { discard; }
    } else if in.mode == 2u || in.mode == 6u {
        // Texture or Text Atlas
        let tex_color = textureSample(t_diffuse, s_diffuse, in.uv);
        if in.mode == 6u {
            // Text uses alpha from atlas and color from vertex
            color.a *= tex_color.r; 
        } else {
            color *= tex_color;
        }
    }
    
    // Global Berserker Rage influence
    let rage = scene.berzerker_rage;
    if rage > 0.1 {
        let n = fbm(in.logical * 10.0 + vec2<f32>(scene.time, scene.time * 0.7));
        color = mix(color, theme.ember_core, n * rage * 0.5);
    }
    
    return color;
}