Skip to content

Commit

Permalink
Fixed: Random issues for spot lights.
Browse files Browse the repository at this point in the history
  • Loading branch information
443eb9 committed Mar 12, 2024
1 parent 4c4b143 commit 2267037
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 22 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ bevy = { version = "0.13", default-features = false, features = [
"bevy_sprite",
] }
fast_poisson = "1.0.0"
radsort = "0.1.0"
thread_local = "1.1"

[dev-dependencies]
Expand Down
9 changes: 6 additions & 3 deletions src/render/catalinzz/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ pub fn prepare_lights(
mut commands: Commands,
mut texture_cache: ResMut<TextureCache>,
main_views: Query<Entity, With<ViewTarget>>,
mut point_lights: Query<Entity, With<ExtractedPointLight2d>>,
point_lights: Query<(Entity, &ExtractedPointLight2d)>,
shadow_map_config: Res<ShadowMap2dConfig>,
mut shadow_map_storage: ResMut<ShadowMap2dStorage>,
mut gpu_meta_buffers: ResMut<GpuMetaBuffers>,
Expand All @@ -506,8 +506,11 @@ pub fn prepare_lights(

gpu_meta_buffers.clear();

for (light_index, light_entity) in point_lights.iter_mut().enumerate() {
// TODO support different pcf settings for different lights
let mut point_lights = point_lights.iter().collect::<Vec<_>>();
radsort::sort_by_key(&mut point_lights, |(_, light)| light.id);

for (light_index, (light_entity, _)) in point_lights.into_iter().enumerate() {
// TODO support different settings for different lights
let meta_index = gpu_meta_buffers.push_light_meta(GpuShadowMapMeta {
index: light_index as u32,
size: shadow_map_config.size,
Expand Down
9 changes: 0 additions & 9 deletions src/render/catalinzz/shaders/shadow_2d_main_pass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,6 @@ fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4f {
let attend_color = visibility * visibility * (*light).intensity * light_color.rgb;
color += attend_color;
}

// if length(rel_px_ss) < light_range_ss {
// var visibility = pcf(rel_ss, shadow_map_meta.pcf_samples, pcf_radius_rel, i_light);
// visibility *= 1. - saturate(
// (rel_px_dist - light_radius_ss) / (light_range_ss - light_radius_ss)
// );
// let attend_color = visibility * visibility * (*light).intensity * light_color.rgb;
// color += attend_color;
// }
}

return textureSample(main_tex, main_tex_sampler, in.uv)
Expand Down
22 changes: 16 additions & 6 deletions src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ impl<S: ShaderType> DynamicUniformIndex<S> {

#[derive(Component, Clone, Copy)]
pub struct ExtractedPointLight2d {
pub id: u32,
pub color: Color,
pub intensity: f32,
pub range: f32,
Expand All @@ -106,15 +107,19 @@ pub fn extract_lights(
point_lights_query: Extract<Query<(Entity, &PointLight2d, &GlobalTransform, &VisibleEntities)>>,
spot_lights_query: Extract<Query<(Entity, &SpotLight2d, &GlobalTransform, &VisibleEntities)>>,
) {
let mut id = 0;

commands.insert_or_spawn_batch(
point_lights_query
.iter()
.map(|(entity, light, transform, visible_entities)| {
let transform = GlobalTransform::from_translation(transform.translation());
id += 1;
(
entity,
(
ExtractedPointLight2d {
id: id - 1,
color: light.color,
intensity: light.intensity,
range: light.range,
Expand All @@ -135,15 +140,17 @@ pub fn extract_lights(
.iter()
.map(|(entity, light, transform, visible_entities)| {
let transform = GlobalTransform::from_translation(transform.translation());
id += 1;
(
entity,
(
ExtractedPointLight2d {
id: id - 1,
color: light.color,
intensity: light.intensity,
range: light.range,
radius: light.radius,
spot_light_angles: light.sector.into_angles(),
spot_light_angles: light.sector.into_extent(),
},
transform,
visible_entities.clone(),
Expand All @@ -158,7 +165,7 @@ pub fn extract_lights(
pub fn prepare_lights(
mut commands: Commands,
main_views: Query<(Entity, &ExtractedView, &VisibleEntities), With<ViewTarget>>,
lights_query: Query<(&ExtractedPointLight2d, &GlobalTransform), With<ExtractedPointLight2d>>,
lights_query: Query<(&ExtractedPointLight2d, &GlobalTransform)>,
ambient_light: Res<AmbientLight2d>,
render_device: Res<RenderDevice>,
render_queue: Res<RenderQueue>,
Expand All @@ -183,11 +190,14 @@ pub fn prepare_lights(
main_view.projection * main_view.transform.compute_matrix().inverse()
});

for visible_light in visible_entities.entities.iter().copied() {
let Ok((light, light_transform)) = lights_query.get(visible_light) else {
continue;
};
let mut visible_lights = visible_entities
.entities
.iter()
.filter_map(|e| lights_query.get(*e).ok())
.collect::<Vec<_>>();
radsort::sort_by_key(&mut visible_lights, |(light, _)| light.id);

for (light, light_transform) in &visible_lights {
let position_ws = light_transform.translation().extend(1.);
let screen_size = 2.
/ Vec2::new(
Expand Down
21 changes: 17 additions & 4 deletions src/render/shaders/math.wgsl
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
#define_import_path bevy_incandescent::math

const PI: f32 = 3.14159265358979323846;
const TAU: f32 = 6.28318530717958647692;
const FRAC_PI_2: f32 = 1.57079632679489661923;

// https://www.cnblogs.com/miloyip/archive/2013/04/19/3029852.html
fn is_point_inside_sector(
point: vec2f,
center: vec2f,
radius: f32,
angles: array<f32, 2>,
) -> bool {
if angles[1] >= TAU {
return true;
}

let p0 = point - center;
let sqr_dist = p0.x * p0.x + p0.y * p0.y;
if sqr_dist > radius * radius {
return false;
}
var pol = atan(p0.y / p0.x);
if p0.x < 0.0 {
pol += PI;

let ctr = vec2f(cos(angles[0]), sin(angles[0]));
let cos_ext = cos(angles[1]);
let d = dot(p0, ctr);

if d >= 0. && cos_ext >= 0. {
return d * d > sqr_dist * cos_ext * cos_ext;
} else if d < 0. && cos_ext < 0. {
return d * d < sqr_dist * cos_ext * cos_ext;
} else {
return d >= 0.;
}
return pol > angles[0] && pol < angles[1];
}

0 comments on commit 2267037

Please sign in to comment.