indicatrix 0.9.0

A physically-based spectral gemstone renderer that turns GemCAD-style cutting instructions into rendered output.
Documentation
fn wt_white_balance(xyz: vec3<f32>) -> vec3<f32> {
    let lms = vec3<f32>(
        fma(0.8951, xyz.x, fma(0.2664, xyz.y, -0.1614 * xyz.z)),
        fma(-0.7502, xyz.x, fma(1.7135, xyz.y, 0.0367 * xyz.z)),
        fma(0.0389, xyz.x, fma(-0.0685, xyz.y, 1.0296 * xyz.z))) * wt.white_balance.xyz;
    return vec3<f32>(
        fma(0.986993, lms.x, fma(-0.147054, lms.y, 0.159963 * lms.z)),
        fma(0.432305, lms.x, fma(0.518360, lms.y, 0.049291 * lms.z)),
        fma(-0.008529, lms.x, fma(0.040043, lms.y, 0.968487 * lms.z)));
}
fn wt_tap(pixel: u32, tap: u32) -> vec3<f32> {
    let width = wt_dims.z;
    let jitter = wt.aa[tap % wt.counts.z].xy;
    let aspect = wt_camera.width / wt_camera.height;
    let u = ((f32(pixel % width) + jitter.x) / wt_camera.width - 0.5) * 2.0 * aspect * wt_camera.fov_tan;
    let v = (0.5 - (f32(pixel / width) + jitter.y) / wt_camera.height) * 2.0 * wt_camera.fov_tan;
    let dir = normalize(wt_camera.forward + wt_camera.right * u + wt_camera.up * v);
    var rgb = vec3<f32>(0.0);
    for (var c: u32 = 0u; c < wt.counts.w; c = c + 1u) {
        rgb = rgb + wt.masks[c].xyz * wt_chain(wt_camera.origin, dir, wt.indices[c], -dir);
    }
    // Preserve the CPU column-matrix summation order; Bradford explicitly fuses.
    var xyz = (wt.rgb_to_xyz[0].xyz * rgb.x + wt.rgb_to_xyz[1].xyz * rgb.y) + wt.rgb_to_xyz[2].xyz * rgb.z;
    if (wt.modes.w != 0u) { xyz = wt_white_balance(xyz); }
    return max(xyz, vec3<f32>(0.0));
}
@compute @workgroup_size(64)
fn whitted_main(@builtin(global_invocation_id) id: vec3<u32>) {
    if (id.x >= wt.range.y) { return; }
    let pixel = wt.range.x + id.x;
    var sum = vec3<f32>(0.0);
    for (var s: u32 = 0u; s < wt.range.w; s = s + 1u) {
        let xyz = wt_tap(pixel, wt.range.z + s);
        // Finite-sample filtering matches add_finite_sample, including the count.
        if (all(abs(xyz) <= vec3<f32>(3.402823466e38))) { sum = sum + xyz; }
    }
    out_xyz[id.x * 3u] = sum.x;
    out_xyz[id.x * 3u + 1u] = sum.y;
    out_xyz[id.x * 3u + 2u] = sum.z;
}