// DVD-style bouncing logo (image texture, e.g. assets/mxl.png) on studio black, // Rec.709, 10-bit Y'CbCr, packed as v210 (4:2:2). // One work-item per 16-byte block = 6 pixels (6 Y + 3 Cb + 3 Cr). // Stateless bounce: logo position is a pure function of the frame tick // (two triangle waves), so no velocity/position state is carried between frames. // // Sub-pixel motion: the logo plane is bilinearly resampled at the fractional // position, so edges glide continuously instead of stepping whole pixels. // The blend is built from mix() chains, which reproduce texel values exactly // in solid regions (mix of equal values is exact in f32). // // Logo plane (binding 2, read-only), one u32 per logo pixel: // logo[0] = logo_w | logo_h << 16 // logo[1 + dy*logo_w + dx] = opaque<<30 | Cr<<20 | Cb<<10 | Y struct Params { width: u32, height: u32, frame: u32, // animation tick (0,1,2,... per generated frame), NOT the raw grain index _pad0: u32, }; @group(0) @binding(0) var out: array; @group(0) @binding(1) var params: Params; @group(0) @binding(2) var logo: array; // 0 -> 1 -> 0 triangle wave; input is elapsed bounce cycles. fn tri01(x: f32) -> f32 { let f = fract(x); return select(2.0 * f, 2.0 - 2.0 * f, f > 0.5); } // Deviation of a logo texel from the background (64/512/512); zero when the // texel is transparent or out of the plane. u32 wraparound in the callers // makes every lower/upper bound case fail the range test, so out-of-bounds // needs no special handling. fn tap(lw: u32, lh: u32, dx: u32, dy: u32) -> vec3 { if (dx < lw && dy < lh) { let s = logo[1u + dy * lw + dx]; if ((s >> 30u) & 1u == 1u) { return vec3(f32(s & 0x3FFu) - 64.0, f32((s >> 10u) & 0x3FFu) - 512.0, f32((s >> 20u) & 0x3FFu) - 512.0); } } return vec3(0.0, 0.0, 0.0); } @compute @workgroup_size(64) fn main(@builtin(global_invocation_id) gid: vec3) { let block = gid.x; let total = (params.width * params.height) / 6u; if (block >= total) { return; } let x = (block * 6u) % params.width; let py = (block * 6u) / params.width; // Logo geometry comes from the plane header. let hdr = logo[0]; let lw = hdr & 0xFFFFu; let lh = hdr >> 16u; // Slow glide: ~8.6 px/frame horizontal, ~6.5 px/frame vertical at 25 fps. // Near-irrational speed ratio (~sqrt(2)) covers the whole frame and // rarely repeats the path, like the DVD logo. let t = f32(params.frame) / 25.0; let lx = tri01(t * 0.061) * max(f32(params.width) - f32(lw), 0.0); let ly = tri01(t * 0.088) * max(f32(params.height) - f32(lh), 0.0); let bx = u32(lx); // integer part of the position let by = u32(ly); let fx = lx - f32(bx); // fractional part, [0,1) let fy = ly - f32(by); var y: array; var cb: array; var cr: array; for (var i = 0u; i < 6u; i++) { // Screen pixel (x+i, py) covers logo-plane footprint [m-f, m+1-f) x // [n-f, n+1-f): texel m-1 gets weight fx, texel m gets 1-fx (same // vertically). Chroma is blended the same way and packed at even // columns, matching v210 4:2:2 co-siting. let m = (x + i) - bx; let n = py - by; let top = mix(tap(lw, lh, m, n - 1u), tap(lw, lh, m - 1u, n - 1u), fx); let bot = mix(tap(lw, lh, m, n), tap(lw, lh, m - 1u, n), fx); let d = mix(bot, top, fy); y[i] = u32(64.0 + d.x + 0.5); cb[i] = u32(512.0 + d.y + 0.5); cr[i] = u32(512.0 + d.z + 0.5); } // v210 word layout, chroma co-sited with luma samples 0/2/4: // w0 = Cb0|Y0<<10|Cr0<<20; w1 = Y1|Cb2<<10|Y2<<20; // w2 = Cr2|Y3<<10|Cb4<<20; w3 = Y4|Cr4<<10|Y5<<20 out[block * 4u + 0u] = (cb[0] & 0x3FFu) | ((y[0] & 0x3FFu) << 10u) | ((cr[0] & 0x3FFu) << 20u); out[block * 4u + 1u] = (y[1] & 0x3FFu) | ((cb[2] & 0x3FFu) << 10u) | ((y[2] & 0x3FFu) << 20u); out[block * 4u + 2u] = (cr[2] & 0x3FFu) | ((y[3] & 0x3FFu) << 10u) | ((cb[4] & 0x3FFu) << 20u); out[block * 4u + 3u] = (y[4] & 0x3FFu) | ((cr[4] & 0x3FFu) << 10u) | ((y[5] & 0x3FFu) << 20u); }