awsm-renderer 0.4.1

awsm-renderer
Documentation
// Bloom effect configuration
const BLOOM_THRESHOLD: f32 = 0.8;
const BLOOM_INTENSITY: f32 = 0.5;
const BLOOM_RADIUS: f32 = 2.0;

fn bloom_threshold(color: vec3<f32>) -> vec3<f32> {
    let brightness = dot(color, vec3<f32>(0.2126, 0.7152, 0.0722));
    let contribution = max(brightness - BLOOM_THRESHOLD, 0.0);
    // Soft knee for smoother threshold transition
    let soft_threshold = BLOOM_THRESHOLD * 0.8;
    let knee = BLOOM_THRESHOLD - soft_threshold;
    let soft = clamp((brightness - soft_threshold) / knee, 0.0, 1.0);
    let factor = contribution / max(brightness, 0.0001) * soft;
    return color * factor;
}

fn gaussian_weight(dist_sq: f32, sigma: f32) -> f32 {
    return exp(-dist_sq / (2.0 * sigma * sigma));
}

// 13-tap blur using a tent/bilinear-friendly pattern
fn blur_sample(
    source_tex: texture_2d<f32>,
    coords: vec2<i32>,
    screen_dims: vec2<i32>
) -> vec3<f32> {
    let sigma = BLOOM_RADIUS;
    let r = i32(ceil(BLOOM_RADIUS));

    var result = vec3<f32>(0.0);
    var total_weight = 0.0;

    // Sample in a plus pattern with varying distances for smooth falloff
    for (var dy = -r; dy <= r; dy = dy + 1) {
        for (var dx = -r; dx <= r; dx = dx + 1) {
            let offset = vec2<i32>(dx, dy);
            let dist_sq = f32(dx * dx + dy * dy);

            // Skip corners beyond radius for circular kernel
            if (dist_sq > BLOOM_RADIUS * BLOOM_RADIUS + 0.5) {
                continue;
            }

            let sample_coords = clamp(coords + offset, vec2<i32>(0), screen_dims - 1);
            let weight = gaussian_weight(dist_sq, sigma);

            result += textureLoad(source_tex, sample_coords, 0).rgb * weight;
            total_weight += weight;
        }
    }

    return result / total_weight;
}

{% if bloom_extract %}
fn apply_bloom(
    color: vec3<f32>,
    coords: vec2<i32>,
    screen_dims: vec2<i32>
) -> vec3<f32> {
    let sigma = BLOOM_RADIUS;
    let r = i32(ceil(BLOOM_RADIUS));

    var bloom_color = vec3<f32>(0.0);
    var total_weight = 0.0;

    for (var dy = -r; dy <= r; dy = dy + 1) {
        for (var dx = -r; dx <= r; dx = dx + 1) {
            let dist_sq = f32(dx * dx + dy * dy);
            if (dist_sq > BLOOM_RADIUS * BLOOM_RADIUS + 0.5) {
                continue;
            }

            let sample_coords = clamp(coords + vec2<i32>(dx, dy), vec2<i32>(0), screen_dims - 1);
            let weight = gaussian_weight(dist_sq, sigma);

            let sample_color = textureLoad(composite_tex, sample_coords, 0).rgb;
            bloom_color += bloom_threshold(sample_color) * weight;
            total_weight += weight;
        }
    }

    return bloom_color / total_weight;
}
{% elif bloom_blend %}
fn apply_bloom(
    color: vec3<f32>,
    coords: vec2<i32>,
    screen_dims: vec2<i32>
) -> vec3<f32> {
    {% if !ping_pong %}
    let blurred = blur_sample(bloom_tex, coords, screen_dims);
    {% else %}
    let blurred = blur_sample(effects_tex, coords, screen_dims);
    {% endif %}

    let original = textureLoad(composite_tex, coords, 0).rgb;
    return original + blurred * BLOOM_INTENSITY;
}
{% else %}
fn apply_bloom(
    color: vec3<f32>,
    coords: vec2<i32>,
    screen_dims: vec2<i32>
) -> vec3<f32> {
    {% if !ping_pong %}
    return blur_sample(bloom_tex, coords, screen_dims);
    {% else %}
    return blur_sample(effects_tex, coords, screen_dims);
    {% endif %}
}
{% endif %}