Skip to main content

HYPERSLICE_KERNEL_WGSL

Constant HYPERSLICE_KERNEL_WGSL 

Source
pub const HYPERSLICE_KERNEL_WGSL: &str = "\nfn sky(rd: vec3<f32>, below: vec3<f32>, above: vec3<f32>) -> vec3<f32> {\n    return mix(below, above, (rd.y + 1.0) * 0.5);\n}\n\n// Box-filtered checker: Quilez, \"Filtering the checkerboard pattern\" (2013).\nfn ground_color(\n    p: vec3<f32>,\n    footprint: vec2<f32>,\n    dark: vec3<f32>,\n    light: vec3<f32>,\n    checker_fade: f32,\n) -> vec3<f32> {\n    let w = footprint + vec2<f32>(1.0e-3);\n    let i = 2.0 * (abs(fract((p.xz - 0.5 * w) * 0.5) - 0.5) - abs(fract((p.xz + 0.5 * w) * 0.5) - 0.5)) / w;\n    let alt = 0.5 - 0.5 * i.x * i.y;\n    return mix(mix(dark, light, alt), 0.5 * (dark + light), checker_fade);\n}\nfn loam_projective_depth(image: vec3<f32>, near: f32) -> f32 {\n    return near / max(-image.z, 1e-20);\n}\n\nconst NO_BODY: u32 = 0xffffffffu;\n\nconst BODY_KIND_SPHERE: u32 = 0u;\nconst BODY_KIND_POLYTOPE: u32 = 1u;\n\nconst SHAPE_PENTATOPE: u32 = 0u;\nconst SHAPE_TESSERACT: u32 = 1u;\nconst SHAPE_16CELL: u32 = 2u;\nconst SHAPE_24CELL: u32 = 3u;\nconst SHAPE_120CELL: u32 = 4u;\nconst SHAPE_600CELL: u32 = 5u;\nconst SHAPE_3SPHERE: u32 = 6u;\nconst SHAPE_DUOCYLINDER: u32 = 7u;\nconst SHAPE_CLIFFORD_TORUS: u32 = 8u;\nconst SHAPE_SPHERINDER: u32 = 9u;\nconst BODY_KIND_INVALID: u32 = 255u;\n\nstruct BodyUniform {\n    position: vec4<f32>,\n    kind: f32,\n    radius_or_shape: f32,\n    polytope_size: f32,\n    _pad0: f32,\n    color: vec3<f32>,\n    _pad1: f32,\n    // Two vec4 so the std140 stride matches Rust\'s `[f32; 8]`; order [s, xy, xz, xw, yz, yw, zw, xyzw].\n    rotor_lo: vec4<f32>,\n    rotor_hi: vec4<f32>,\n};\n\nstruct Uniforms {\n    camera_pos: vec3<f32>,\n    camera_forward: vec3<f32>,\n    camera_right: vec3<f32>,\n    camera_up: vec3<f32>,\n    fov_y_tan: f32,\n    resolution: vec2<f32>,\n    time: f32,\n    tick: f32,\n    w_slice: f32,\n    body_count: f32,\n    viewport_origin: vec2<f32>,\n    params: vec4<f32>,\n    near: f32,\n    body_offset: f32,\n    sky_below: vec3<f32>,\n    sky_above: vec3<f32>,\n};\n\n@group(0) @binding(0) var<uniform> u: Uniforms;\n@group(0) @binding(1) var<storage, read> bodies: array<BodyUniform>;\n\nfn body_at(index: u32) -> BodyUniform {\n    return bodies[u32(u.body_offset + 0.5) + index];\n}\n\nfn body_sphere_sdf_4d(p4: vec4<f32>, b: BodyUniform) -> f32 {\n    return length(p4 - b.position) - b.radius_or_shape;\n}\n\nfn rotor4_inverse_apply(rotor_lo: vec4<f32>, rotor_hi: vec4<f32>, v: vec4<f32>) -> vec4<f32> {\n    let rs  = rotor_lo.x;\n    let rxy = -rotor_lo.y;\n    let rxz = -rotor_lo.z;\n    let rxw = -rotor_lo.w;\n    let ryz = -rotor_hi.x;\n    let ryw = -rotor_hi.y;\n    let rzw = -rotor_hi.z;\n    let r_i = rotor_hi.w;\n\n    let vx = v.x; let vy = v.y; let vz = v.z; let vw = v.w;\n\n    let p1 = rs * vx - rxy * vy - rxz * vz - rxw * vw;\n    let p2 = rs * vy + rxy * vx - ryz * vz - ryw * vw;\n    let p3 = rs * vz + rxz * vx + ryz * vy - rzw * vw;\n    let p4 = rs * vw + rxw * vx + ryw * vy + rzw * vz;\n\n    let t123 = -rxy * vz + rxz * vy - ryz * vx + r_i * vw;\n    let t124 = -rxy * vw + rxw * vy - ryw * vx - r_i * vz;\n    let t134 = -rxz * vw + rxw * vz - rzw * vx + r_i * vy;\n    let t234 = -ryz * vw + ryw * vz - rzw * vy - r_i * vx;\n\n    let q1 = rs * p1 - rxy * p2 - rxz * p3 - rxw * p4\n           - ryz * t123 - ryw * t124 - rzw * t134 + r_i * t234;\n    let q2 = rs * p2 + rxy * p1 - ryz * p3 - ryw * p4\n           + rxz * t123 + rxw * t124 - rzw * t234 - r_i * t134;\n    let q3 = rs * p3 + rxz * p1 + ryz * p2 - rzw * p4\n           - rxy * t123 + rxw * t134 + ryw * t234 + r_i * t124;\n    let q4 = rs * p4 + rxw * p1 + ryw * p2 + rzw * p3\n           - rxy * t124 - rxz * t134 - ryz * t234 - r_i * t123;\n\n    return vec4<f32>(q1, q2, q3, q4);\n}\n\nfn pentatope_sdf_local(p: vec4<f32>) -> f32 {\n    let t  = 0.55901699437;  // sqrt(5) / 4\n    let n0 = vec4<f32>(0.0, 0.0, 0.0, -1.0);\n    let n1 = vec4<f32>(-t, -t, -t, 0.25);\n    let n2 = vec4<f32>(-t,  t,  t, 0.25);\n    let n3 = vec4<f32>( t, -t,  t, 0.25);\n    let n4 = vec4<f32>( t,  t, -t, 0.25);\n    let r = 0.25;\n    var d: f32 = dot(n0, p) - r;\n    d = max(d, dot(n1, p) - r);\n    d = max(d, dot(n2, p) - r);\n    d = max(d, dot(n3, p) - r);\n    d = max(d, dot(n4, p) - r);\n    return d;\n}\n\nfn tesseract_sdf_local(p: vec4<f32>) -> f32 {\n    let q = abs(p) - vec4<f32>(0.5, 0.5, 0.5, 0.5);\n    let outside = length(max(q, vec4<f32>(0.0, 0.0, 0.0, 0.0)));\n    let inside = min(max(max(q.x, q.y), max(q.z, q.w)), 0.0);\n    return outside + inside;\n}\n\nfn cell16_sdf_local(p: vec4<f32>) -> f32 {\n    let q = abs(p);\n    return (q.x + q.y + q.z + q.w - 1.0) * 0.5;\n}\n\nfn cell24_sdf_local(p: vec4<f32>) -> f32 {\n    let inv_sqrt2: f32 = 0.70710678;\n    let sqrt2:     f32 = 1.41421356;\n    let q = abs(p);\n    let tess  = max(max(q.x, q.y), max(q.z, q.w)) - inv_sqrt2;\n    let cross = (q.x + q.y + q.z + q.w - sqrt2) * 0.5;\n    return max(tess, cross);\n}\n\nfn sphere3_sdf_local(p: vec4<f32>) -> f32 {\n    return length(p) - 1.0;\n}\n\nfn duocylinder_sdf_local(p: vec4<f32>) -> f32 {\n    let r = 0.7071068;\n    let dxy = length(p.xy) - r;\n    let dzw = length(p.zw) - r;\n    let outside = length(vec2<f32>(max(dxy, 0.0), max(dzw, 0.0)));\n    let inside = min(max(dxy, dzw), 0.0);\n    return outside + inside;\n}\n\nfn clifford_torus_sdf_local(p: vec4<f32>) -> f32 {\n    let r1 = 0.5;\n    let r2 = 0.5;\n    let tube = 0.2;\n    let q1 = length(p.xy) - r1;\n    let q2 = length(p.zw) - r2;\n    return length(vec2<f32>(q1, q2)) - tube;\n}\n\nfn spherinder_sdf_local(p: vec4<f32>) -> f32 {\n    let r = 0.7071068;\n    let h = 0.7071068;\n    let dxyz = length(p.xyz) - r;\n    let dw = abs(p.w) - h;\n    let outside = length(vec2<f32>(max(dxyz, 0.0), max(dw, 0.0)));\n    let inside = min(max(dxyz, dw), 0.0);\n    return outside + inside;\n}\n\n// Outside 1.5\u{d7} the circumradius the ball SDF is a Lipschitz-1 lower bound; skips the rotor inverse.\nfn body_polytope_sdf_4d(p4: vec4<f32>, b: BodyUniform) -> f32 {\n    let size = max(b.polytope_size, 1.0e-6);\n    let world_v = p4 - b.position;\n    let world_dist2 = dot(world_v, world_v);\n    let bound = size * 1.5;\n    if (world_dist2 > bound * bound) {\n        return sqrt(world_dist2) - size;\n    }\n    let local_v = rotor4_inverse_apply(b.rotor_lo, b.rotor_hi, world_v);\n    let unit_p = local_v / size;\n    let shape = u32(b.radius_or_shape + 0.5);\n    var d: f32 = 1.0e9;\n    if (shape == SHAPE_PENTATOPE) {\n        d = pentatope_sdf_local(unit_p);\n    } else if (shape == SHAPE_TESSERACT) {\n        d = tesseract_sdf_local(unit_p);\n    } else if (shape == SHAPE_16CELL) {\n        d = cell16_sdf_local(unit_p);\n    } else if (shape == SHAPE_24CELL) {\n        d = cell24_sdf_local(unit_p);\n    } else if (shape == SHAPE_120CELL) {\n        d = cell120_sdf_local(unit_p);\n    } else if (shape == SHAPE_600CELL) {\n        d = cell600_sdf_local(unit_p);\n    } else if (shape == SHAPE_3SPHERE) {\n        d = sphere3_sdf_local(unit_p);\n    } else if (shape == SHAPE_DUOCYLINDER) {\n        d = duocylinder_sdf_local(unit_p);\n    } else if (shape == SHAPE_CLIFFORD_TORUS) {\n        d = clifford_torus_sdf_local(unit_p);\n    } else if (shape == SHAPE_SPHERINDER) {\n        d = spherinder_sdf_local(unit_p);\n    }\n    return d * size;\n}\n\nfn loam_dynamic_bodies_sdf(p3: vec3<f32>) -> f32 {\n    let p4 = vec4<f32>(p3, u.w_slice);\n    let body_count = u32(u.body_count + 0.5);\n    var sdf: f32 = 1.0e9;\n    for (var i: u32 = 0u; i < body_count; i = i + 1u) {\n        let b = body_at(i);\n        let kind = u32(b.kind + 0.5);\n        if (kind == BODY_KIND_SPHERE) {\n            sdf = min(sdf, body_sphere_sdf_4d(p4, b));\n        } else if (kind == BODY_KIND_POLYTOPE) {\n            sdf = min(sdf, body_polytope_sdf_4d(p4, b));\n        }\n    }\n    return sdf;\n}\n\nfn loam_body_sdf_at(p3: vec3<f32>, body_idx: u32) -> f32 {\n    if (body_idx >= u32(u.body_count + 0.5)) { return 1.0e9; }\n    let p4 = vec4<f32>(p3, u.w_slice);\n    let b = body_at(body_idx);\n    let kind = u32(b.kind + 0.5);\n    if (kind == BODY_KIND_SPHERE) {\n        return body_sphere_sdf_4d(p4, b);\n    } else if (kind == BODY_KIND_POLYTOPE) {\n        return body_polytope_sdf_4d(p4, b);\n    }\n    return 1.0e9;\n}\n\nstruct HitInfo {\n    dist: f32,\n    body_idx: u32,\n};\n\nfn loam_total_sdf(p3: vec3<f32>) -> HitInfo {\n    let scene_d = loam_scene_sdf(p3);\n\n    let p4 = vec4<f32>(p3, u.w_slice);\n    let body_count = u32(u.body_count + 0.5);\n    var dyn_d: f32 = 1.0e9;\n    var dyn_idx: u32 = NO_BODY;\n    for (var i: u32 = 0u; i < body_count; i = i + 1u) {\n        let b = body_at(i);\n        let kind = u32(b.kind + 0.5);\n        var d: f32 = 1.0e9;\n        if (kind == BODY_KIND_SPHERE) {\n            d = body_sphere_sdf_4d(p4, b);\n        } else if (kind == BODY_KIND_POLYTOPE) {\n            d = body_polytope_sdf_4d(p4, b);\n        }\n        if (d < dyn_d) {\n            dyn_d = d;\n            dyn_idx = i;\n        }\n    }\n\n    if (scene_d <= dyn_d) {\n        return HitInfo(scene_d, NO_BODY);\n    }\n    return HitInfo(dyn_d, dyn_idx);\n}\n\n@vertex\nfn vs_fullscreen(@builtin(vertex_index) vid: u32) -> @builtin(position) vec4<f32> {\n    let uv = vec2<f32>(f32((vid << 1u) & 2u), f32(vid & 2u));\n    return vec4<f32>(uv * 2.0 - 1.0, 0.0, 1.0);\n}\n\nfn estimate_normal(p: vec3<f32>, body_idx: u32) -> vec3<f32> {\n    let h = 0.001;\n    if (body_idx == NO_BODY) {\n        let dx = loam_scene_sdf(p + vec3<f32>(h, 0.0, 0.0))\n               - loam_scene_sdf(p - vec3<f32>(h, 0.0, 0.0));\n        let dy = loam_scene_sdf(p + vec3<f32>(0.0, h, 0.0))\n               - loam_scene_sdf(p - vec3<f32>(0.0, h, 0.0));\n        let dz = loam_scene_sdf(p + vec3<f32>(0.0, 0.0, h))\n               - loam_scene_sdf(p - vec3<f32>(0.0, 0.0, h));\n        return normalize(vec3<f32>(dx, dy, dz));\n    }\n    let dx = loam_body_sdf_at(p + vec3<f32>(h, 0.0, 0.0), body_idx)\n           - loam_body_sdf_at(p - vec3<f32>(h, 0.0, 0.0), body_idx);\n    let dy = loam_body_sdf_at(p + vec3<f32>(0.0, h, 0.0), body_idx)\n           - loam_body_sdf_at(p - vec3<f32>(0.0, h, 0.0), body_idx);\n    let dz = loam_body_sdf_at(p + vec3<f32>(0.0, 0.0, h), body_idx)\n           - loam_body_sdf_at(p - vec3<f32>(0.0, 0.0, h), body_idx);\n    return normalize(vec3<f32>(dx, dy, dz));\n}\n\nstruct Shaded {\n    color: vec4<f32>,\n    depth: f32,\n};\n\nstruct Fragment {\n    @location(0) color: vec4<f32>,\n    @builtin(frag_depth) depth: f32,\n};\n\nfn shade(frag_pos: vec4<f32>) -> Shaded {\n    let uv = ((frag_pos.xy - u.viewport_origin) / u.resolution) * 2.0 - vec2<f32>(1.0, 1.0);\n    let aspect = u.resolution.x / u.resolution.y;\n    let ndc = vec2<f32>(uv.x * aspect, -uv.y);\n    let rd = normalize(\n        u.camera_forward\n        + u.camera_right * (ndc.x * u.fov_y_tan)\n        + u.camera_up    * (ndc.y * u.fov_y_tan)\n    );\n    let ro = u.camera_pos;\n\n    var t: f32 = 0.0;\n    let scene_max_t = loam_scene_max_t(ro, rd);\n    let max_t = min(60.0, scene_max_t + 1.0);\n    var hit = false;\n    var hit_idx: u32 = NO_BODY;\n    // Every composed SDF is a 1-Lipschitz lower bound, so the full step cannot tunnel.\n    let hit_eps = 0.001;\n    let min_step = 0.0001;\n    for (var i: i32 = 0; i < 384; i = i + 1) {\n        let p = ro + rd * t;\n        let h = loam_total_sdf(p);\n        if (h.dist < hit_eps) {\n            hit = true;\n            hit_idx = h.body_idx;\n            break;\n        }\n        t = t + max(h.dist, min_step);\n        if (t > max_t) { break; }\n    }\n\n    if (!hit) {\n        discard;\n        return Shaded(vec4<f32>(0.0, 0.0, 0.0, 0.0), 0.0);\n    }\n\n    let p_hit = ro + rd * t;\n    if (hit_idx == NO_BODY) {\n        if (loam_scene_at(p_hit).kind == LOAM_PRIM_HALFSPACE4D) {\n            discard;\n            return Shaded(vec4<f32>(0.0, 0.0, 0.0, 0.0), 0.0);\n        }\n    }\n    let n = estimate_normal(p_hit, hit_idx);\n    let light_dir = normalize(vec3<f32>(0.5, 0.85, 0.3));\n    let lambert = max(dot(n, light_dir), 0.0);\n    let ambient = 0.20;\n    var base = vec3<f32>(0.65, 0.65, 0.72);\n    if (hit_idx != NO_BODY) {\n        base = body_at(hit_idx).color;\n    }\n    let lit = base * (ambient + lambert * 0.85);\n    let fog = 1.0 - exp(-t * 0.05);\n    let final_color = mix(lit, sky(rd, u.sky_below, u.sky_above), fog * 0.5);\n    let image = vec3<f32>(0.0, 0.0, -t * dot(rd, u.camera_forward));\n    return Shaded(vec4<f32>(final_color, 1.0), loam_projective_depth(image, u.near));\n}\n\n@fragment\nfn fs_main(@builtin(position) frag_pos: vec4<f32>) -> @location(0) vec4<f32> {\n    return shade(frag_pos).color;\n}\n\n@fragment\nfn fs_depth(@builtin(position) frag_pos: vec4<f32>) -> Fragment {\n    let shaded = shade(frag_pos);\n    return Fragment(shaded.color, shaded.depth);\n}\n";
Expand description

Prefixed with crate::sky_ground::SKY_GROUND_WGSL and the shared loam_projective_depth; the user’s Scene4 emit supplies loam_scene_sdf.