kiss3d 0.44.0

Keep it simple, stupid, 2D and 3D graphics engine for Rust.
Documentation
import package::common::fullscreen_uv_from_clip;
// Contrast Adaptive Sharpening (AMD FidelityFX CAS), simplified single-pass
// (no scaling). Runs as a post-processing effect on the tonemapped LDR image:
// it sharpens detail while adapting the strength to local contrast so flat areas
// and already-sharp edges are left mostly untouched. Pairs well after FXAA/TAA.

struct CasUniforms {
    // 1 / render-target size, in UV units per texel.
    inv_resolution: vec2<f32>,
    // Sharpening strength in [0, 1].
    sharpness: f32,
    _pad: f32,
};

@group(0) @binding(0) var t_color: texture_2d<f32>;
@group(0) @binding(1) var s_color: sampler;
@group(0) @binding(2) var<uniform> u: CasUniforms;

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

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

fn tap(uv: vec2<f32>, off: vec2<f32>) -> vec3<f32> {
    return textureSample(t_color, s_color, uv + off * u.inv_resolution).rgb;
}

@fragment
fn fs_main(in: VsOut) -> @location(0) vec4<f32> {
    let uv = in.uv;
    // 3x3 neighborhood:  a b c / d e f / g h i
    let a = tap(uv, vec2<f32>(-1.0, -1.0));
    let b = tap(uv, vec2<f32>(0.0, -1.0));
    let c = tap(uv, vec2<f32>(1.0, -1.0));
    let d = tap(uv, vec2<f32>(-1.0, 0.0));
    let e = tap(uv, vec2<f32>(0.0, 0.0));
    let f = tap(uv, vec2<f32>(1.0, 0.0));
    let g = tap(uv, vec2<f32>(-1.0, 1.0));
    let h = tap(uv, vec2<f32>(0.0, 1.0));
    let i = tap(uv, vec2<f32>(1.0, 1.0));

    // Soft min/max of the cross, then extended to the full 3x3 (CAS).
    var mn = min(min(min(d, e), min(f, b)), h);
    let mn2 = min(mn, min(min(a, c), min(g, i)));
    mn = mn + mn2;

    var mx = max(max(max(d, e), max(f, b)), h);
    let mx2 = max(mx, max(max(a, c), max(g, i)));
    mx = mx + mx2;

    let rcp_mx = 1.0 / max(mx, vec3<f32>(1e-4));
    var amp = clamp(min(mn, vec3<f32>(2.0) - mx) * rcp_mx, vec3<f32>(0.0), vec3<f32>(1.0));
    amp = sqrt(amp);

    // Sharpening weight: peak between -1/8 (soft) and -1/5 (sharp).
    let peak = -1.0 / mix(8.0, 5.0, clamp(u.sharpness, 0.0, 1.0));
    let w = amp * peak;
    let rcp_w = 1.0 / (1.0 + 4.0 * w);

    let out_rgb = (b * w + d * w + f * w + h * w + e) * rcp_w;
    return vec4<f32>(max(out_rgb, vec3<f32>(0.0)), 1.0);
}