bevy_lit 0.9.1

A lighting 2d library for Bevy
Documentation
#define_import_path bevy_lit::light2d_common

#import bevy_render::view::{
    View,
    frag_coord_to_ndc,
    position_ndc_to_world,
    position_world_to_ndc,
    ndc_to_uv,
    uv_to_ndc,
}
#import bevy_lit::{
    settings_types::Lighting2dSettings,
    view_transformations::{world_to_uv, frag_to_world},
}

@group(0) @binding(0) var<uniform> view: View;
@group(0) @binding(1) var<uniform> settings: Lighting2dSettings;
@group(0) @binding(2) var voronoi_texture: texture_2d<f32>;
@group(0) @binding(3) var voronoi_sampler: sampler;

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) uv: vec2<f32>,
    @location(2) @interpolate(flat) translation_rotation: vec4<f32>,
}

fn attenuation(inner: f32, outer: f32, falloff: f32, diff: f32) -> f32 {
    if diff <= inner {
        return 1.0;
    }

    if diff >= outer {
        return 0.0;
    }

    let s = (diff - inner) / (outer - inner);
    let s2 = s * s;

    return pow(1.0 - s2, 2.0) / (1.0 + falloff * s2);
}

fn get_sdf(pos: vec2<f32>) -> f32 {
    let uv = world_to_uv(vec3(pos, 0.0), view);
    let samp = textureSampleLevel(voronoi_texture, voronoi_sampler, uv, 0.0);

    // Original seed
    if samp.z == 1.0 {
        return 0.0;
    }

    let seed = frag_to_world(samp / settings.scale, view).xy;
    let dist = length(pos - seed);

    // Determine if the pixel is inside or outside the shape
    return select(dist, -dist, samp.w == 1.0);
}

// Implementation follows the demo in this article
// https://www.rykap.com/2020/09/23/distance-fields
fn raymarch(ray_origin: vec2<f32>, ray_target: vec2<f32>) -> f32 {
    let config = settings.raymarch;
    let max_steps = config.max_steps;
    let sharpness = config.sharpness;
    let jitter = config.jitter;

    let ray_direction = normalize(ray_target - ray_origin);
    let stop_at = distance(ray_origin, ray_target);

    var ray_progress = 0.0;
    var light_contrib = 1.0;

    for (var i = 0u; i < max_steps; i++) {
        // ray found target
        if ray_progress > stop_at {
            return light_contrib;
        }

        let sdf = get_sdf(ray_origin + ray_progress * ray_direction);

        // ray found occluder
        if sdf <= 0.0 {
            break;
        }

        light_contrib = min(light_contrib, sdf / ray_progress * sharpness);
        ray_progress += sdf * (1.0 - jitter) + jitter * fract(sdf * 43758.5453);
    }

    return 0.0;
}