Skip to main content

WGSL

Constant WGSL 

Source
pub const WGSL: &str = "struct Post {\n    size: vec2<u32>,\n    frame: u32,\n    seed: u32,\n    p0: vec4<f32>,\n    p1: vec4<f32>,\n    p2: vec4<f32>,\n    p3: vec4<f32>,\n    region: vec4<u32>,\n    extent: vec4<u32>,\n}\n\n@group(0) @binding(0) var<uniform> post: Post;\n@group(0) @binding(1) var src_tex: texture_2d<f32>;\n@group(0) @binding(2) var dst_tex: texture_storage_2d<rgba16float, write>;\n@group(0) @binding(3) var linear_sampler: sampler;\n\nvar<private> edge: f32;\n\nfn hash(x: u32, y: u32, seed: u32) -> u32 {\n    var h = x * 0x8da6b343u ^ y * 0xd8163841u ^ seed * 0xcb1ab31fu;\n    h = h ^ (h >> 15u);\n    h = h * 0x2c1b3c6du;\n    h = h ^ (h >> 12u);\n    return h;\n}\n\nfn encode(c: f32) -> f32 {\n    let v = max(c, 0.0);\n    if (v <= 0.0031308) { return v * 12.92; }\n    return 1.055 * pow(v, 1.0 / 2.4) - 0.055;\n}\n\nfn bump(yn: f32, t: f32, turn: f32, start: f32, speed: f32, width: f32, gain: f32) -> f32 {\n    let spun = f32(post.seed & 0xffffu) * turn + start;\n    let travel = spun - floor(spun) - post.p0.w * speed * t;\n    let centre = (travel - floor(travel)) * (1.0 + 2.0 * width) - width;\n    let d = max(1.0 - abs(yn - centre) / width, 0.0);\n    return d * d * gain;\n}\n\nfn band(yn: f32, t: f32) -> f32 {\n    let a = bump(yn, t, 0.61803399, 0.0, 0.21, 0.05, 0.9);\n    let b = bump(yn, t, 0.41421356, 0.37, 0.34, 0.022, 1.0);\n    let c = bump(yn, t, 0.73205081, 0.71, 0.13, 0.09, 0.6);\n    return max(a, max(b, c));\n}\n\nfn at(x: f32, v: f32, inv: f32) -> vec4<f32> {\n    return textureSampleLevel(src_tex, linear_sampler, vec2<f32>(min(x, edge) * inv, v), 0.0);\n}\n\n@compute @workgroup_size(8, 8)\nfn main(@builtin(global_invocation_id) id: vec3<u32>) {\n    let dim = min(textureDimensions(dst_tex), post.size);\n    if (id.x >= dim.x || id.y >= dim.y) { return; }\n    let full = textureDimensions(src_tex);\n    let span = min(full, post.extent.xy);\n    let fw = f32(span.x);\n    let inv = 1.0 / f32(full.x);\n    edge = select(1e30, fw - 0.5, span.x < full.x);\n    let row = id.y;\n    let lead = post.p0.w;\n    let mixed = post.seed ^ (post.frame * 0x9e3779b9u);\n    let t = f32(post.frame) / 60.0;\n    let yn = (f32(row) + 0.5) / f32(span.y);\n    let v = (f32(row) + 0.5) / f32(full.y);\n    let envelope = band(yn, t);\n    let bands = post.p3.x;\n    let rh = hash(row, 17u, mixed);\n    let shove = lead * bands * fw * (\n        post.p3.y * envelope\n        + 0.0003 * envelope * (f32(rh >> 16u) / 32768.0 - 1.0)\n    );\n    let x = f32(id.x) + 0.5 + shove + post.p1.z;\n    let d = post.p1.w * fw;\n    let sr = lead * post.p0.x * fw;\n    let sb = lead * post.p0.y * fw;\n    let here = at(x, v, inv);\n    var left = at(x + sr, v, inv);\n    var right = at(x - sb, v, inv);\n    if (d > 0.0) {\n        left = 0.5 * (at(x + sr - d, v, inv) + at(x + sr + d, v, inv));\n        right = 0.5 * (at(x - sb - d, v, inv) + at(x - sb + d, v, inv));\n    }\n    var mixed_rgb = vec3<f32>(\n        0.41 * here.r + 0.59 * left.r,\n        0.92 * here.g + 0.06 * left.g + 0.02 * right.g,\n        0.45 * here.b + 0.08 * left.b + 0.47 * right.b,\n    );\n    let w1 = post.p1.x;\n    let w2 = post.p1.y;\n    if (w1 > 0.0 || w2 > 0.0) {\n        let e1 = at(x + lead * 0.007 * fw, v, inv).rgb;\n        let e2 = at(x + lead * 0.016 * fw, v, inv).rgb;\n        mixed_rgb = mixed_rgb * (1.0 - w1 - w2) + w1 * e1 + w2 * e2;\n    }\n    let split = sqrt(max(mixed_rgb, vec3<f32>(0.0)));\n    let lift = post.p2.x;\n    var luma = lift + (1.0 - lift) * dot(split, vec3<f32>(0.299, 0.587, 0.114));\n    var chroma = vec2<f32>(\n        dot(split, vec3<f32>(0.596, -0.274, -0.322)),\n        dot(split, vec3<f32>(0.211, -0.523, 0.312)),\n    ) * post.p2.y;\n    if (envelope > 0.0) {\n        let n = f32(hash(id.x / max(span.x / 960u, 1u), row, mixed ^ 0x51u) >> 8u) / 16777216.0;\n        let lo = 1.0 - 0.12 * envelope;\n        let u = clamp((n - lo) / (1.0 - lo), 0.0, 1.0);\n        luma = luma + bands * envelope * 0.1 * u * u * (3.0 - 2.0 * u);\n    }\n    let grain = post.p2.z;\n    let h = hash(id.x, row, mixed ^ 7u);\n    let n = f32(h & 0x3ffu) / 1024.0 + f32((h >> 10u) & 0x3ffu) / 1024.0 - 1.0;\n    let period = max(2.0, round(f32(span.y) / 540.0));\n    let scan = 1.0 - post.p2.w * (0.5 + 0.5 * cos(6.2831853 * f32(row) / period));\n    luma = (luma + n * grain) * scan;\n    chroma = chroma + (vec2<f32>(f32((h >> 20u) & 0x3fu), f32(h >> 26u)) / 64.0 - vec2<f32>(0.5)) * grain * 0.6;\n    let g = clamp(vec3<f32>(\n        luma + 0.9561707 * chroma.x + 0.6214326 * chroma.y,\n        luma - 0.2726886 * chroma.x - 0.6468132 * chroma.y,\n        luma - 1.1037441 * chroma.x + 1.7006231 * chroma.y,\n    ), vec3<f32>(0.0), vec3<f32>(1.0));\n    let linear = g * g;\n    if (post.p3.z > 0.5) {\n        textureStore(dst_tex, vec2<u32>(id.xy), vec4<f32>(encode(linear.r), encode(linear.g), encode(linear.b), here.a));\n    } else {\n        textureStore(dst_tex, vec2<u32>(id.xy), vec4<f32>(linear, here.a));\n    }\n}\n";