Skip to content

Commit c3a4682

Browse files
committed
Cascaded shadow maps. (#7064)
Co-authored-by: Robert Swain <[email protected]> # Objective Implements cascaded shadow maps for directional lights, which produces better quality shadows without needing excessively large shadow maps. Fixes #3629 Before ![image](https://user-images.githubusercontent.com/1222141/210061203-bbd965a4-8d11-4cec-9a88-67fc59d0819f.png) After ![image](https://user-images.githubusercontent.com/1222141/210061334-2ff15334-e6d7-4a31-9314-f34a7805cac6.png) ## Solution Rather than rendering a single shadow map for directional light, the view frustum is divided into a series of cascades, each of which gets its own shadow map. The correct cascade is then sampled for shadow determination. --- ## Changelog Directional lights now use cascaded shadow maps for improved shadow quality. ## Migration Guide You no longer have to manually specify a `shadow_projection` for a directional light, and these settings should be removed. If customization of how cascaded shadow maps work is desired, modify the `CascadeShadowConfig` component instead.
1 parent f27e9b2 commit c3a4682

File tree

23 files changed

+672
-284
lines changed

23 files changed

+672
-284
lines changed

crates/bevy_core_pipeline/src/core_2d/camera_2d.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl Camera2dBundle {
6161
let transform = Transform::from_xyz(0.0, 0.0, far - 0.1);
6262
let view_projection =
6363
projection.get_projection_matrix() * transform.compute_matrix().inverse();
64-
let frustum = Frustum::from_view_projection(
64+
let frustum = Frustum::from_view_projection_custom_far(
6565
&view_projection,
6666
&transform.translation,
6767
&transform.back(),

crates/bevy_pbr/src/bundle.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
1-
use crate::{DirectionalLight, Material, PointLight, SpotLight, StandardMaterial};
1+
use crate::{
2+
CascadeShadowConfig, Cascades, DirectionalLight, Material, PointLight, SpotLight,
3+
StandardMaterial,
4+
};
25
use bevy_asset::Handle;
3-
use bevy_ecs::{bundle::Bundle, component::Component, reflect::ReflectComponent};
6+
use bevy_ecs::{bundle::Bundle, component::Component, prelude::Entity, reflect::ReflectComponent};
47
use bevy_reflect::Reflect;
58
use bevy_render::{
69
mesh::Mesh,
7-
primitives::{CubemapFrusta, Frustum},
10+
primitives::{CascadesFrusta, CubemapFrusta, Frustum},
811
view::{ComputedVisibility, Visibility, VisibleEntities},
912
};
1013
use bevy_transform::components::{GlobalTransform, Transform};
14+
use bevy_utils::HashMap;
1115

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

70+
#[derive(Component, Clone, Debug, Default, Reflect)]
71+
#[reflect(Component)]
72+
pub struct CascadesVisibleEntities {
73+
/// Map of view entity to the visible entities for each cascade frustum.
74+
#[reflect(ignore)]
75+
pub entities: HashMap<Entity, Vec<VisibleEntities>>,
76+
}
77+
6678
/// A component bundle for [`PointLight`] entities.
6779
#[derive(Debug, Bundle, Default)]
6880
pub struct PointLightBundle {
@@ -95,8 +107,10 @@ pub struct SpotLightBundle {
95107
#[derive(Debug, Bundle, Default)]
96108
pub struct DirectionalLightBundle {
97109
pub directional_light: DirectionalLight,
98-
pub frustum: Frustum,
99-
pub visible_entities: VisibleEntities,
110+
pub frusta: CascadesFrusta,
111+
pub cascades: Cascades,
112+
pub cascade_shadow_config: CascadeShadowConfig,
113+
pub visible_entities: CascadesVisibleEntities,
100114
pub transform: Transform,
101115
pub global_transform: GlobalTransform,
102116
/// Enables or disables the light

crates/bevy_pbr/src/lib.rs

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,17 +145,20 @@ impl Plugin for PbrPlugin {
145145
Shader::from_wgsl
146146
);
147147

148-
app.register_type::<CubemapVisibleEntities>()
149-
.register_type::<DirectionalLight>()
150-
.register_type::<PointLight>()
151-
.register_type::<SpotLight>()
152-
.register_asset_reflect::<StandardMaterial>()
148+
app.register_asset_reflect::<StandardMaterial>()
153149
.register_type::<AmbientLight>()
154-
.register_type::<DirectionalLightShadowMap>()
150+
.register_type::<CascadeShadowConfig>()
151+
.register_type::<Cascades>()
152+
.register_type::<CascadesVisibleEntities>()
155153
.register_type::<ClusterConfig>()
156-
.register_type::<ClusterZConfig>()
157154
.register_type::<ClusterFarZMode>()
155+
.register_type::<ClusterZConfig>()
156+
.register_type::<CubemapVisibleEntities>()
157+
.register_type::<DirectionalLight>()
158+
.register_type::<DirectionalLightShadowMap>()
159+
.register_type::<PointLight>()
158160
.register_type::<PointLightShadowMap>()
161+
.register_type::<SpotLight>()
159162
.add_plugin(MeshRenderPlugin)
160163
.add_plugin(MaterialPlugin::<StandardMaterial> {
161164
prepass_enabled: self.prepass_enabled,
@@ -183,13 +186,20 @@ impl Plugin for PbrPlugin {
183186
.after(CameraUpdateSystem)
184187
.after(ModifiesWindows),
185188
)
189+
.add_system_to_stage(
190+
CoreStage::PostUpdate,
191+
update_directional_light_cascades
192+
.label(SimulationLightSystems::UpdateDirectionalLightCascades)
193+
.after(TransformSystem::TransformPropagate),
194+
)
186195
.add_system_to_stage(
187196
CoreStage::PostUpdate,
188197
update_directional_light_frusta
189198
.label(SimulationLightSystems::UpdateLightFrusta)
190199
// This must run after CheckVisibility because it relies on ComputedVisibility::is_visible()
191200
.after(VisibilitySystems::CheckVisibility)
192201
.after(TransformSystem::TransformPropagate)
202+
.after(SimulationLightSystems::UpdateDirectionalLightCascades)
193203
// We assume that no entity will be both a directional light and a spot light,
194204
// so these systems will run independently of one another.
195205
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.

0 commit comments

Comments
 (0)