kiss3d 0.45.0

Keep it simple, stupid, 2D and 3D graphics engine for Rust.
Documentation
// Fullscreen tonemap pass: reads the HDR accumulation buffer and applies the
// selected tonemap operator + gamma via the shared `apply_tonemap`, imported from
// the `tonemap_ops` WESL module (which also declares the Tony McMapface LUT at
// group(0) bindings 6 & 7). Upscales from the traced resolution to the framebuffer
// if they differ.

import package::tonemap_ops::apply_tonemap;

struct TonemapUniforms {
    src_width: u32,
    src_height: u32,
    dst_width: u32,
    dst_height: u32,
    exposure: f32,
    // Operator code, matching `post_processing::Tonemap::as_u32`.
    tonemap_op: u32,
    pad0: f32,
    pad1: f32,
};

@group(0) @binding(0) var<storage, read> accum: array<vec4<f32>>;
@group(0) @binding(1) var<uniform> u: TonemapUniforms;

struct VsOut {
    @builtin(position) clip_position: vec4<f32>,
};

@vertex
fn vs_main(@location(0) position: vec2<f32>) -> VsOut {
    var out: VsOut;
    out.clip_position = vec4<f32>(position, 0.0, 1.0);
    return out;
}

@fragment
fn fs_main(@builtin(position) frag: vec4<f32>) -> @location(0) vec4<f32> {
    let dx = u32(frag.x);
    let dy = u32(frag.y);
    if (dx >= u.dst_width || dy >= u.dst_height) {
        return vec4<f32>(0.0, 0.0, 0.0, 1.0);
    }
    // Map the destination pixel back to a source (traced) pixel.
    let sx = min((dx * u.src_width) / u.dst_width, u.src_width - 1u);
    let sy = min((dy * u.src_height) / u.dst_height, u.src_height - 1u);
    let idx = sy * u.src_width + sx;
    let hdr = accum[idx].rgb * u.exposure;
    return vec4<f32>(apply_tonemap(hdr, u.tonemap_op), 1.0);
}