Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

too many point lights behave strangely #3915

Closed
robtfm opened this issue Feb 11, 2022 · 0 comments
Closed

too many point lights behave strangely #3915

robtfm opened this issue Feb 11, 2022 · 0 comments
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior

Comments

@robtfm
Copy link
Contributor

robtfm commented Feb 11, 2022

Bevy version

main

Operating system & version

Windows 10

What you did

Create a scene with more than 256 point lights.

What you expected to happen

Rational degradation of the lights in the scene.

What actually happened

Odd behaviour as some clusters get more light than expected, and some get less / none.

Additional information

Example code to see the issue (most noticeable after ~10 seconds when the CLUSTER_COUNT_MASK limit is exceeded for the middle cluster):

use bevy::{prelude::*, diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, window::{WindowMode, PresentMode}};

fn main() {
    App::new()
        .insert_resource(WindowDescriptor{
            width: 1280.0,
            height: 720.0,
            mode: WindowMode::Windowed,
            present_mode: PresentMode::Immediate,
            ..Default::default()
        })
        .add_plugins(DefaultPlugins)
        .add_plugin(FrameTimeDiagnosticsPlugin)
        .add_plugin(LogDiagnosticsPlugin::default())
        .add_startup_system(setup)
        .add_system(move_camera)
        .run()
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // some quad
    commands.spawn_bundle(PbrBundle{
        mesh: meshes.add(shape::Quad{size: Vec2::splat(100.0), flip: false}.into()),
        material: materials.add(Color::WHITE.into()),
        transform: Transform::from_translation(Vec3::new(0.0, 0.0, -5.0)),
        ..Default::default()
    });

    // some bright offscreen lights
    for x in 0..25 {
        for y in 0..10 {
            commands.spawn_bundle(PointLightBundle {
                point_light: PointLight {
                    color: Color::RED,
                    intensity: 10.0,
                    range: f32::sqrt(10.0 * 10.0 / (4.0 * std::f32::consts::PI)),
                    ..Default::default()
                },
                transform: Transform::from_translation(Vec3::new(20.0 + 10.0 * x as f32, y as f32 * 10.0 - 50.0, -4.9)),
                ..Default::default()
            });
        }
    }

    // grid of lights
    for x in 1..=18 {
        for y in 1..=18 {
            commands.spawn_bundle(PointLightBundle {
                point_light: PointLight {
                    color: Color::BLUE,
                    intensity: x as f32 * y as f32 * 0.01,
                    range: f32::sqrt(x as f32 * y as f32 * 0.01 * 10.0 / (4.0 * std::f32::consts::PI)),
                    ..Default::default()
                },
                transform: Transform::from_translation(Vec3::new(x as f32 * 0.2 - 2.0, y as f32 * 0.2 - 2.0, -4.9)),
                ..Default::default()
            });
        }
    }

    //camera
    commands.spawn_bundle(PerspectiveCameraBundle::new_3d());

    //action
}

fn move_camera(
    mut q: Query<&mut Transform, With<Camera>>,
    time: Res<Time>,
) {
    for mut t in q.iter_mut() {
        t.translation.z += time.delta_seconds();
    }
}

lights_issue_1
lights_issue_2

@robtfm robtfm added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Feb 11, 2022
@IceSentry IceSentry added A-Rendering Drawing game state to the screen C-Usability A simple quality-of-life change that makes Bevy easier to use and removed S-Needs-Triage This issue needs to be labelled labels Feb 11, 2022
@alice-i-cecile alice-i-cecile removed the C-Usability A simple quality-of-life change that makes Bevy easier to use label Feb 11, 2022
@bors bors bot closed this as completed in 3f6068d Mar 1, 2022
kurtkuehnert pushed a commit to kurtkuehnert/bevy that referenced this issue Mar 6, 2022
# Objective

fix bevyengine#3915 

## Solution

the issues are caused by
- lights are assigned to clusters before being filtered down to MAX_POINT_LIGHTS, leading to cluster counts potentially being too high
- after fixing the above, packing the count into 8 bits still causes overflow with exactly 256 lights affecting a cluster

to fix:

```assign_lights_to_clusters```
- limit extracted lights to MAX_POINT_LIGHTS, selecting based on shadow-caster & intensity (if required)
- warn if MAX_POINT_LIGHT count is exceeded

```prepare_lights```
- limit the lights assigned to a cluster to CLUSTER_COUNT_MASK (which is 1 less than MAX_POINT_LIGHTS) to avoid overflowing into the offset bits

notes:
- a better solution to the overflow may be to use more than 8 bits for cluster_count (the comment states only 14 of the remaining 24 bits are used for the offset). this would touch more of the code base but i'm happy to try if it has some benefit.
- intensity is only one way to select lights. it may be worth allowing user configuration of the light filtering, but i can't see a clean way to do that
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants