bugfix(frustra of point lights were not recalculated when a camera changes) (#18519)

# Objective

- Fixes https://github.com/bevyengine/bevy/issues/11682

## Solution

- https://github.com/bevyengine/bevy/pull/4086 introduced an
optimization to not do redundant calculations, but did not take into
account changes to the resource `global_lights`. I believe that my patch
includes the optimization benefit but adds the required nuance to fix
said bug.

## Testing

The example originally given by
[@kirillsurkov](https://github.com/kirillsurkov) and then updated by me
to bevy 15.3 here:
https://github.com/bevyengine/bevy/issues/11682#issuecomment-2746287416
will not have shadows without this patch:

```rust
use bevy::prelude::*;

#[derive(Resource)]
struct State {
    x: f32,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, update)
        .insert_resource(State { x: -40.0 })
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    commands.spawn((
        Mesh3d(meshes.add(Circle::new(4.0))),
        MeshMaterial3d(materials.add(Color::WHITE)),
    ));
    commands.spawn((
        Mesh3d(meshes.add(Cuboid::new(1.0, 1.0, 1.0))),
        MeshMaterial3d(materials.add(Color::linear_rgb(0.0, 1.0, 0.0))),
    ));
    commands.spawn((
        PointLight {
            shadows_enabled: true,
            ..default()
        },
        Transform::from_xyz(4.0, 8.0, 4.0),
    ));
    commands.spawn(Camera3d::default());
}

fn update(mut state: ResMut<State>, mut camera: Query<&mut Transform, With<Camera3d>>) {
    let mut camera = camera.single_mut().unwrap();

    let t = Vec3::new(state.x, 0.0, 10.0);
    camera.translation = t;
    camera.look_at(t - Vec3::Z, Vec3::Y);

    state.x = 0.0;
}
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
This commit is contained in:
HugoPeters1024 2025-03-25 05:48:49 +01:00 committed by GitHub
parent 6a981aaa6f
commit a58a8bde2b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -563,9 +563,13 @@ pub fn update_directional_light_frusta(
// NOTE: Run this after assign_lights_to_clusters!
pub fn update_point_light_frusta(
global_lights: Res<GlobalVisibleClusterableObjects>,
mut views: Query<
(Entity, &GlobalTransform, &PointLight, &mut CubemapFrusta),
Or<(Changed<GlobalTransform>, Changed<PointLight>)>,
mut views: Query<(Entity, &GlobalTransform, &PointLight, &mut CubemapFrusta)>,
changed_lights: Query<
Entity,
(
With<PointLight>,
Or<(Changed<GlobalTransform>, Changed<PointLight>)>,
),
>,
) {
let view_rotations = CUBE_MAP_FACES
@ -574,6 +578,12 @@ pub fn update_point_light_frusta(
.collect::<Vec<_>>();
for (entity, transform, point_light, mut cubemap_frusta) in &mut views {
// If this light hasn't changed, and neither has the set of global_lights,
// then we can skip this calculation.
if !global_lights.is_changed() && !changed_lights.contains(entity) {
continue;
}
// The frusta are used for culling meshes to the light for shadow mapping
// so if shadow mapping is disabled for this light, then the frusta are
// not needed.