Skip to content

Commit

Permalink
Cascaded shadow maps.
Browse files Browse the repository at this point in the history
Co-authored-by: Robert Swain <robert.swain@gmail.com>

Implements cascaded shadow maps for directional lights, which produces
better quality shadows without needing excessively large shadow maps.
  • Loading branch information
danchia committed Dec 30, 2022
1 parent a5d70b8 commit fa11b18
Show file tree
Hide file tree
Showing 21 changed files with 616 additions and 261 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_core_pipeline/src/core_2d/camera_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Camera2dBundle {
let transform = Transform::from_xyz(0.0, 0.0, far - 0.1);
let view_projection =
projection.get_projection_matrix() * transform.compute_matrix().inverse();
let frustum = Frustum::from_view_projection(
let frustum = Frustum::from_view_projection_custom_far(
&view_projection,
&transform.translation,
&transform.back(),
Expand Down
24 changes: 19 additions & 5 deletions crates/bevy_pbr/src/bundle.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use crate::{DirectionalLight, Material, PointLight, SpotLight, StandardMaterial};
use crate::{
CascadeShadowConfig, Cascades, DirectionalLight, Material, PointLight, SpotLight,
StandardMaterial,
};
use bevy_asset::Handle;
use bevy_ecs::{bundle::Bundle, component::Component, reflect::ReflectComponent};
use bevy_ecs::{bundle::Bundle, component::Component, prelude::Entity, reflect::ReflectComponent};
use bevy_reflect::Reflect;
use bevy_render::{
mesh::Mesh,
primitives::{CubemapFrusta, Frustum},
primitives::{CascadesFrusta, CubemapFrusta, Frustum},
view::{ComputedVisibility, Visibility, VisibleEntities},
};
use bevy_transform::components::{GlobalTransform, Transform};
use bevy_utils::HashMap;

/// A component bundle for PBR entities with a [`Mesh`] and a [`StandardMaterial`].
pub type PbrBundle = MaterialMeshBundle<StandardMaterial>;
Expand Down Expand Up @@ -63,6 +67,14 @@ impl CubemapVisibleEntities {
}
}

#[derive(Component, Clone, Debug, Default, Reflect)]
#[reflect(Component)]
pub struct CascadesVisibleEntities {
/// The visible entities for each cascade frustrum, for each view.
#[reflect(ignore)]
pub entities: HashMap<Entity, Vec<VisibleEntities>>,
}

/// A component bundle for [`PointLight`] entities.
#[derive(Debug, Bundle, Default)]
pub struct PointLightBundle {
Expand Down Expand Up @@ -95,8 +107,10 @@ pub struct SpotLightBundle {
#[derive(Debug, Bundle, Default)]
pub struct DirectionalLightBundle {
pub directional_light: DirectionalLight,
pub frustum: Frustum,
pub visible_entities: VisibleEntities,
pub frusta: CascadesFrusta,
pub cascades: Cascades,
pub cascade_shadow_config: CascadeShadowConfig,
pub visible_entities: CascadesVisibleEntities,
pub transform: Transform,
pub global_transform: GlobalTransform,
/// Enables or disables the light
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_pbr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,20 @@ impl Plugin for PbrPlugin {
.after(CameraUpdateSystem)
.after(ModifiesWindows),
)
.add_system_to_stage(
CoreStage::PostUpdate,
update_directional_light_cascades
.label(SimulationLightSystems::UpdateDirectionalLightCascades)
.after(TransformSystem::TransformPropagate),
)
.add_system_to_stage(
CoreStage::PostUpdate,
update_directional_light_frusta
.label(SimulationLightSystems::UpdateLightFrusta)
// This must run after CheckVisibility because it relies on ComputedVisibility::is_visible()
.after(VisibilitySystems::CheckVisibility)
.after(TransformSystem::TransformPropagate)
.after(SimulationLightSystems::UpdateDirectionalLightCascades)
// We assume that no entity will be both a directional light and a spot light,
// so these systems will run indepdently of one another.
// FIXME: Add an archetype invariant for this /~https://github.com/bevyengine/bevy/issues/1481.
Expand Down
Loading

0 comments on commit fa11b18

Please sign in to comment.