bevy_fast_light 0.10.0

Simple 2D lighting for Bevy focused on performance over features.
Documentation
#import bevy_sprite::{mesh2d_vertex_output::VertexOutput, mesh2d_view_bindings::view}
#import bevy_render::view::frag_coord_to_uv

@group(2) @binding(0)
var occluder_texture: texture_2d<f32>;
@group(2) @binding(1)
var occluder_sampler: sampler;
@group(2) @binding(2)
var<uniform> light_color: vec4<f32>;

const HALF_UV = vec2<f32>(0.5);
const INV_RADIUS_SQ = 1. / (0.5 * 0.5);

@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
    // NOTE: This is not technically correct, but since the output texture is always at viewport resolution this works.
    let viewport_uv = frag_coord_to_uv(in.position.xy, view.viewport);
    let occluder_color = textureSample(occluder_texture, occluder_sampler, viewport_uv);
    let sprite_depth = occluder_color.r;
    let is_occluder = occluder_color.g > 0.5;
    let occluder_depth = occluder_color.b;
    // NOTE: Checking if sprite_depth is 0 is necessary for occluders on z-level 0 if no sprites are rendered.
    let is_occluded = is_occluder && (sprite_depth == 0. || occluder_depth > sprite_depth);

    let dist = in.uv - HALF_UV;
    let length_sq = dot(dist, dist);
    let falloff = smoothstep(1., 0., length_sq * INV_RADIUS_SQ);
    let attenuation = falloff * falloff;

    return light_color * attenuation * select(1., 0., is_occluded);
}