Skip to content

Commit

Permalink
Added: Frustum culling
Browse files Browse the repository at this point in the history
  • Loading branch information
443eb9 committed Feb 29, 2024
1 parent 83b2291 commit f06373b
Show file tree
Hide file tree
Showing 13 changed files with 230 additions and 291 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ bevy = { version = "0.13", default-features = false, features = [
"x11",
"wayland",
] }
thread_local = "1.1.8"
thread_local = "1.1"

[dev-dependencies]
bevy = { version = "0.13", features = [
Expand Down
49 changes: 31 additions & 18 deletions examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
use bevy::{
app::{App, PluginGroup, Startup},
app::{App, PluginGroup, Startup, Update},
core_pipeline::core_2d::Camera2dBundle,
ecs::system::Commands,
ecs::{
query::With,
system::{Commands, Query},
},
math::Vec2,
render::{color::Color, view::{Msaa, NoFrustumCulling}},
render::{
camera::Camera,
color::Color,
view::{Msaa, NoFrustumCulling, VisibleEntities},
},
sprite::{Sprite, SpriteBundle},
transform::components::Transform,
window::{PresentMode, Window, WindowPlugin, WindowResolution},
DefaultPlugins,
};
use bevy_incandescent::{
ecs::{
bundle::{PointLight2dBundle, ShadowCaster2dBundle, ShadowRenderedCameraBundle},
bundle::{PointLight2dBundle, ShadowCaster2dBundle},
light::PointLight2d,
},
IncandescentPlugin,
Expand Down Expand Up @@ -43,16 +50,14 @@ fn main() {
HelpersPlugin { inspector: true },
))
.add_systems(Startup, setup)
.add_systems(Update, debug)
// MSAA is not supported yet
.insert_resource(Msaa::Off)
.run();
}

fn setup(mut commands: Commands) {
commands.spawn((
Camera2dBundle::default(),
ShadowRenderedCameraBundle::default(),
));
commands.spawn(Camera2dBundle::default());

let mut rd = StdRng::seed_from_u64(1);
// let mut rd = StdRng::from_entropy();
Expand All @@ -72,21 +77,23 @@ fn setup(mut commands: Commands) {
),
..Default::default()
},
NoFrustumCulling,
ShadowCaster2dBundle::default(),
));
}

commands.spawn(PointLight2dBundle {
point_light: PointLight2d {
color: Color::rgb(rd.gen(), rd.gen(), rd.gen()),
intensity: 1000.,
range: 200.,
radius: 50.,
commands.spawn((
PointLight2dBundle {
point_light: PointLight2d {
color: Color::rgb(rd.gen(), rd.gen(), rd.gen()),
intensity: 1000.,
range: 200.,
radius: 50.,
},
transform: Transform::from_xyz(50., 25., 0.),
..Default::default()
},
transform: Transform::from_xyz(50., 25., 0.),
..Default::default()
});
NoFrustumCulling,
));

// commands.spawn(PointLight2dBundle {
// point_light: PointLight2d {
Expand All @@ -99,3 +106,9 @@ fn setup(mut commands: Commands) {
// ..Default::default()
// });
}

fn debug(camera: Query<&VisibleEntities, With<PointLight2d>>) {
for camera in camera.iter() {
// println!("{:?}", camera.entities.len());
}
}
21 changes: 7 additions & 14 deletions src/ecs/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,25 @@
use bevy::{
ecs::bundle::Bundle,
render::view::{InheritedVisibility, ViewVisibility, Visibility},
render::{
primitives::Frustum,
view::{InheritedVisibility, ViewVisibility, Visibility, VisibleEntities},
},
transform::components::{GlobalTransform, Transform},
};

use crate::render::DEFAULT_SHADOW_CASTER_LAYER;

use super::light::{PointLight2d, ShadowCaster2d, ShadowCaster2dVisibility, ShadowLayers};

#[derive(Bundle)]
pub struct ShadowRenderedCameraBundle {
pub shadow_layer: ShadowLayers,
}

impl Default for ShadowRenderedCameraBundle {
fn default() -> Self {
Self {
shadow_layer: DEFAULT_SHADOW_CASTER_LAYER,
}
}
}

#[derive(Bundle, Default)]
pub struct PointLight2dBundle {
pub point_light: PointLight2d,
pub transform: Transform,
pub global_transform: GlobalTransform,
pub frustum: Frustum,
pub visible_casters: VisibleEntities,
pub visibility: Visibility,
pub view_visibility: ViewVisibility,
pub inherited_visibility: InheritedVisibility,
}

Expand Down
4 changes: 0 additions & 4 deletions src/ecs/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ pub struct ShadowView2d {
pub attachment: ColorAttachment,
}

#[derive(Component)]
#[cfg_attr(feature = "debug", derive(Reflect))]
pub struct VisibleLight2dEntities(pub Vec<Entity>);

#[derive(Component, Default, Clone, Copy)]
#[cfg_attr(feature = "debug", derive(Reflect))]
pub struct PointLight2d {
Expand Down
8 changes: 6 additions & 2 deletions src/ecs/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use bevy::app::{App, Plugin};

use self::resources::ShadowMap2dConfig;

pub mod bundle;
pub mod camera;
pub mod light;
pub mod resources;

pub struct IncandescentECSPlugin;

impl Plugin for IncandescentECSPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<ShadowMap2dConfig>();

#[cfg(feature = "debug")]
{
use light::*;
app.register_type::<PointLight2d>()
.register_type::<VisibleLight2dEntities>();
app.register_type::<PointLight2d>();
}
}
}
24 changes: 24 additions & 0 deletions src/ecs/resources.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use bevy::{ecs::system::Resource, math::Mat4};

#[derive(Resource, Clone, Copy)]
pub struct ShadowMap2dConfig {
pub near: f32,
pub far: f32,
pub size: u32,
}

impl Default for ShadowMap2dConfig {
fn default() -> Self {
Self {
near: -1000.,
far: 1000.,
size: 512,
}
}
}

impl ShadowMap2dConfig {
pub fn get_proj_mat(&self, scale: f32) -> Mat4 {
Mat4::orthographic_rh(-scale, scale, -scale, scale, self.near, self.far)
}
}
37 changes: 13 additions & 24 deletions src/render/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ use bevy::{
transform::components::GlobalTransform,
};

use crate::ecs::light::{PointLight2d, ShadowCaster2dVisibility, VisibleLight2dEntities};

use super::resource::ShadowMap2dConfig;
use crate::ecs::{
light::{PointLight2d, ShadowCaster2dVisibility},
resources::ShadowMap2dConfig,
};

#[derive(Component, Clone, Copy)]
pub struct ExtractedPointLight2d {
Expand All @@ -32,18 +33,13 @@ pub struct ExtractedPointLight2d {

pub fn extract_point_lights(
mut commands: Commands,
lights_query: Extract<Query<(Entity, &PointLight2d, &GlobalTransform)>>,
caster_query: Extract<Query<(Entity, &ShadowCaster2dVisibility)>>,
shadow_map_config: Res<ShadowMap2dConfig>,
lights_query: Extract<Query<(Entity, &PointLight2d, &GlobalTransform, &VisibleEntities)>>,
shadow_map_config: Extract<Res<ShadowMap2dConfig>>,
) {
let casters = caster_query
.iter()
.filter_map(|(e, v)| if v.0 { Some(e) } else { None })
.collect::<Vec<_>>();
commands.insert_or_spawn_batch(
lights_query
.iter()
.map(|(entity, light, transform)| {
.map(|(entity, light, transform, visible_entities)| {
(
entity,
(
Expand All @@ -55,11 +51,10 @@ pub fn extract_point_lights(
spot_light_angles: None,
},
*transform,
// TODO cull invisible casters
VisibleEntities {
entities: casters.clone(),
},
visible_entities.clone(),
ExtractedView {
// TODO I have no idea why the size should be doubled
// The shadow map will be clipped if the size is not doubled
projection: shadow_map_config.get_proj_mat(light.range * 2.),
transform: *transform,
view_projection: None,
Expand All @@ -75,15 +70,9 @@ pub fn extract_point_lights(
);
}

pub fn extract_shadow_cameras(
pub fn extract_resources(
mut commands: Commands,
main_views: Extract<Query<Entity, With<Camera>>>,
// TODO visibility check
lights_query: Extract<Query<Entity, With<PointLight2d>>>,
shadow_map_config: Extract<Res<ShadowMap2dConfig>>,
) {
for main_view_entity in &main_views {
commands
.get_or_spawn(main_view_entity)
.insert(VisibleLight2dEntities(lights_query.iter().collect()));
}
commands.insert_resource(shadow_map_config.clone());
}
Loading

0 comments on commit f06373b

Please sign in to comment.