moonlit/assets/shaders/darkness.wgsl

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));
}