Skip to main content

PROBE_WGSL

Constant PROBE_WGSL 

Source
pub const PROBE_WGSL: &str = "struct ProbeGridInfo {\n    min_spacing: vec4f,\n    dims: vec4u,\n    fallback: vec4f,\n}\n@group(3) @binding(0) var<storage, read> probe_words: array<u32>;\n@group(3) @binding(1) var<uniform> probe_grid: ProbeGridInfo;\n\nfn probe_axis(index: u32) -> vec3f {\n    switch index {\n        case 0u: { return vec3f(1.0, 0.0, 0.0); }\n        case 1u: { return vec3f(-1.0, 0.0, 0.0); }\n        case 2u: { return vec3f(0.0, 1.0, 0.0); }\n        case 3u: { return vec3f(0.0, -1.0, 0.0); }\n        case 4u: { return vec3f(0.0, 0.0, 1.0); }\n        default: { return vec3f(0.0, 0.0, -1.0); }\n    }\n}\n\nfn probe_index(xyz: vec3u) -> u32 {\n    return (xyz.z * probe_grid.dims.y + xyz.y) * probe_grid.dims.x + xyz.x;\n}\n\nfn sample_probe_grid(position: vec3f, normal: vec3f) -> vec3f {\n    let normal_length = length(normal);\n    if (normal_length < 0.000001 || normal_length != normal_length || normal_length > 1e20 || any(position != position) || any(abs(position) > vec3f(1e20))) { return probe_grid.fallback.xyz; }\n    let n = normal / normal_length;\n    let point = position + n * 0.006;\n    let last = vec3f(probe_grid.dims.xyz - vec3u(1u));\n    let surface = (position - probe_grid.min_spacing.xyz) / probe_grid.min_spacing.w;\n    let shifted = (point - probe_grid.min_spacing.xyz) / probe_grid.min_spacing.w;\n    let surface_out = any(surface < vec3f(0.0)) || any(surface > last);\n    let shifted_out = any(shifted < vec3f(0.0)) || any(shifted > last);\n    if (surface_out && shifted_out) { return probe_grid.fallback.xyz; }\n    let coord = clamp(shifted, vec3f(0.0), last);\n    let base = min(vec3u(floor(coord)), max(probe_grid.dims.xyz, vec3u(2u)) - vec3u(2u));\n    var t = clamp(coord - vec3f(base), vec3f(0.0), vec3f(1.0));\n    for (var axis = 0u; axis < 3u; axis++) {\n        if (probe_grid.dims[axis] == 1u) { t[axis] = 0.0; }\n    }\n    var color = vec3f(0.0);\n    var total = 0.0;\n    for (var corner = 0u; corner < 8u; corner++) {\n        var xyz = base;\n        var weight = 1.0;\n        for (var axis = 0u; axis < 3u; axis++) {\n            let high = (corner & (1u << axis)) != 0u;\n            if (high && probe_grid.dims[axis] > 1u) { xyz[axis] += 1u; }\n            weight *= select(1.0 - t[axis], t[axis], high);\n        }\n        if (weight == 0.0) { continue; }\n        let version_two = probe_grid.dims.w == 2u;\n        let offset = probe_index(xyz) * select(15u, 20u, version_two);\n        var center = probe_grid.min_spacing.xyz + vec3f(xyz) * probe_grid.min_spacing.w;\n        if (version_two) {\n            let last = probe_words[offset + 19u];\n            if (((last >> 16u) & 1u) == 0u) { continue; }\n            let xy = unpack2x16float(probe_words[offset + 18u]);\n            center += vec3f(xy, unpack2x16float(last).x) * probe_grid.min_spacing.w;\n        }\n        let toward_probe = center - position + n * 0.0001;\n        let facing = clamp((dot(toward_probe / max(length(toward_probe), 0.000001), n) + 1.0) * 0.5, 0.0, 1.0);\n        weight *= facing * facing * facing;\n        if (weight == 0.0) { continue; }\n        let toward_point = point - center;\n        let distance = length(toward_point);\n        let direction = toward_point / max(distance, 0.000001);\n        var irradiance = vec3f(0.0);\n        var visibility = 0.0;\n        var mean = 0.0;\n        var second = 0.0;\n        for (var lobe = 0u; lobe < 6u; lobe++) {\n            let directional = max(dot(n, probe_axis(lobe)), 0.0);\n            let nw = directional * directional;\n            let rg = unpack2x16float(probe_words[offset + lobe * 2u]);\n            let b = unpack2x16float(probe_words[offset + lobe * 2u + 1u]).x;\n            let pair = unpack2x16float(probe_words[offset + 12u + lobe / 2u]);\n            irradiance += vec3f(rg, b) * nw;\n            let ray_weight = max(dot(direction, probe_axis(lobe)), 0.0);\n            if (version_two) {\n                let squared = unpack2x16float(probe_words[offset + 15u + lobe / 2u]);\n                mean += ray_weight * ray_weight * select(pair.x, pair.y, lobe % 2u == 1u) * probe_grid.min_spacing.w;\n                second += ray_weight * ray_weight * select(squared.x, squared.y, lobe % 2u == 1u) * probe_grid.min_spacing.w * probe_grid.min_spacing.w;\n            } else {\n                let reach = select(pair.x, pair.y, lobe % 2u == 1u) + probe_grid.min_spacing.w * 0.25;\n                visibility += ray_weight * ray_weight * clamp((reach - distance) / probe_grid.min_spacing.w, 0.0, 1.0);\n            }\n        }\n        if (version_two) {\n            let variance = max(second - mean * mean, probe_grid.min_spacing.w * probe_grid.min_spacing.w * 0.01);\n            let delta = max(distance - mean - probe_grid.min_spacing.w * 0.1, 0.0);\n            let chance = variance / (variance + delta * delta);\n            weight *= chance * chance;\n        } else {\n            weight *= select(1.0, visibility, distance > 0.000001);\n        }\n        color += irradiance * weight;\n        total += weight;\n    }\n    if (total <= 0.000001) { return probe_grid.fallback.xyz; }\n    return color / total;\n}\n";