89 lines
2.3 KiB
Plaintext
89 lines
2.3 KiB
Plaintext
#import bevy_pbr::mesh_vertex_output MeshVertexOutput
|
|
#import bevy_sprite::mesh2d_view_bindings globals
|
|
|
|
struct DarknessMaterial {
|
|
color: vec4<f32>,
|
|
};
|
|
|
|
struct PointLight {
|
|
position: vec2<f32>,
|
|
radius: f32,
|
|
}
|
|
|
|
struct SpotLight {
|
|
position: vec2<f32>,
|
|
radius: f32,
|
|
rotation: f32,
|
|
angle: f32,
|
|
padding1: u32,
|
|
padding2: u32,
|
|
padding3: u32,
|
|
}
|
|
|
|
@group(1) @binding(0)
|
|
var<uniform> material: DarknessMaterial;
|
|
|
|
@group(1) @binding(1)
|
|
var<uniform> point_light_count: i32;
|
|
|
|
@group(1) @binding(2)
|
|
var<uniform> point_lights: array<PointLight, 64>;
|
|
|
|
@group(1) @binding(3)
|
|
var<uniform> spot_light_count: i32;
|
|
|
|
@group(1) @binding(4)
|
|
var<uniform> spot_lights: array<SpotLight, 64>;
|
|
|
|
@fragment
|
|
fn fragment(
|
|
mesh: MeshVertexOutput,
|
|
) -> @location(0) vec4<f32> {
|
|
let color = material.color;
|
|
let pos = mesh.world_position.xy;
|
|
let t = globals.time;
|
|
let light_edge = 6.0;
|
|
let light_edge_mult = 0.8;
|
|
|
|
var bright_light = 0.0;
|
|
var dim_light = 0.0;
|
|
|
|
for (var i: i32 = 0; i < point_light_count; i++) {
|
|
if (point_lights[i].radius <= 0.0) {
|
|
continue;
|
|
}
|
|
let radius = point_lights[i].radius - (sin(t * 5.0) * 0.5 + 0.5) * 0.2;
|
|
|
|
let dist = distance(pos, point_lights[i].position);
|
|
let edge_treshold = radius * light_edge_mult - light_edge;
|
|
let edge_dist = max(dist - edge_treshold, 0.0);
|
|
bright_light = bright_light + step(dist, edge_treshold);
|
|
bright_light = bright_light + 1.0 / edge_dist;
|
|
dim_light = dim_light + step(dist, radius);
|
|
dim_light = dim_light + 1.0 / max(dist - radius, 0.0);
|
|
}
|
|
|
|
for (var i: i32 = 0; i < spot_light_count; i++) {
|
|
if (spot_lights[i].radius <= 0.0 || spot_lights[i].angle <= 0.0) {
|
|
continue;
|
|
}
|
|
let spot = spot_lights[i];
|
|
let radius = spot.radius - (sin(t * 5.0) * 0.5 + 0.5) * 0.2;
|
|
let diff = pos - spot.position;
|
|
let dist = length(diff);
|
|
let spot_dir = vec2<f32>(cos(spot.rotation), sin(spot.rotation));
|
|
let angle_diff = acos(dot(spot_dir, normalize(diff)));
|
|
|
|
let edge_treshold = radius * light_edge_mult - light_edge;
|
|
let edge_dist = max(dist - edge_treshold, 0.0);
|
|
let angle_mult = step(angle_diff, spot.angle / 2.0);
|
|
bright_light = bright_light + step(dist, edge_treshold) * angle_mult;
|
|
dim_light = dim_light + step(dist, radius) * angle_mult;
|
|
}
|
|
|
|
let edge1 = step(bright_light, 0.75);
|
|
let edge2 = step(dim_light, 0.75) * 0.5 + 0.5;
|
|
|
|
return vec4(color.rgb, color.a * edge1 * (edge2 * 0.5 + 0.5));
|
|
}
|