@@ -5,6 +5,7 @@ use bevy_render::{
55 camera:: Camera ,
66 color:: Color ,
77 mesh:: Mesh ,
8+ primitives:: { CascadesFrusta , CubemapFrusta , Frustum } ,
89 render_asset:: RenderAssets ,
910 render_graph:: { Node , NodeRunError , RenderGraphContext } ,
1011 render_phase:: * ,
@@ -48,6 +49,7 @@ pub struct ExtractedDirectionalLight {
4849 shadow_normal_bias : f32 ,
4950 cascade_shadow_config : CascadeShadowConfig ,
5051 cascades : EntityHashMap < Entity , Vec < Cascade > > ,
52+ frusta : EntityHashMap < Entity , Vec < Frustum > > ,
5153 render_layers : RenderLayers ,
5254}
5355
@@ -296,6 +298,7 @@ pub fn extract_lights(
296298 & CubemapVisibleEntities ,
297299 & GlobalTransform ,
298300 & ViewVisibility ,
301+ & CubemapFrusta ,
299302 ) > ,
300303 > ,
301304 spot_lights : Extract <
@@ -304,6 +307,7 @@ pub fn extract_lights(
304307 & VisibleEntities ,
305308 & GlobalTransform ,
306309 & ViewVisibility ,
310+ & Frustum ,
307311 ) > ,
308312 > ,
309313 directional_lights : Extract <
@@ -314,6 +318,7 @@ pub fn extract_lights(
314318 & CascadesVisibleEntities ,
315319 & Cascades ,
316320 & CascadeShadowConfig ,
321+ & CascadesFrusta ,
317322 & GlobalTransform ,
318323 & ViewVisibility ,
319324 Option < & RenderLayers > ,
@@ -343,7 +348,7 @@ pub fn extract_lights(
343348
344349 let mut point_lights_values = Vec :: with_capacity ( * previous_point_lights_len) ;
345350 for entity in global_point_lights. iter ( ) . copied ( ) {
346- let Ok ( ( point_light, cubemap_visible_entities, transform, view_visibility) ) =
351+ let Ok ( ( point_light, cubemap_visible_entities, transform, view_visibility, frusta ) ) =
347352 point_lights. get ( entity)
348353 else {
349354 continue ;
@@ -373,15 +378,19 @@ pub fn extract_lights(
373378 } ;
374379 point_lights_values. push ( (
375380 entity,
376- ( extracted_point_light, render_cubemap_visible_entities) ,
381+ (
382+ extracted_point_light,
383+ render_cubemap_visible_entities,
384+ ( * frusta) . clone ( ) ,
385+ ) ,
377386 ) ) ;
378387 }
379388 * previous_point_lights_len = point_lights_values. len ( ) ;
380389 commands. insert_or_spawn_batch ( point_lights_values) ;
381390
382391 let mut spot_lights_values = Vec :: with_capacity ( * previous_spot_lights_len) ;
383392 for entity in global_point_lights. iter ( ) . copied ( ) {
384- if let Ok ( ( spot_light, visible_entities, transform, view_visibility) ) =
393+ if let Ok ( ( spot_light, visible_entities, transform, view_visibility, frustum ) ) =
385394 spot_lights. get ( entity)
386395 {
387396 if !view_visibility. get ( ) {
@@ -417,6 +426,7 @@ pub fn extract_lights(
417426 spot_light_angles : Some ( ( spot_light. inner_angle , spot_light. outer_angle ) ) ,
418427 } ,
419428 render_visible_entities,
429+ * frustum,
420430 ) ,
421431 ) ) ;
422432 }
@@ -430,6 +440,7 @@ pub fn extract_lights(
430440 visible_entities,
431441 cascades,
432442 cascade_config,
443+ frusta,
433444 transform,
434445 view_visibility,
435446 maybe_layers,
@@ -452,6 +463,7 @@ pub fn extract_lights(
452463 shadow_normal_bias : directional_light. shadow_normal_bias * std:: f32:: consts:: SQRT_2 ,
453464 cascade_shadow_config : cascade_config. clone ( ) ,
454465 cascades : cascades. cascades . clone ( ) ,
466+ frusta : frusta. frusta . clone ( ) ,
455467 render_layers : maybe_layers. copied ( ) . unwrap_or_default ( ) ,
456468 } ,
457469 render_visible_entities,
@@ -656,7 +668,11 @@ pub fn prepare_lights(
656668 directional_light_shadow_map : Res < DirectionalLightShadowMap > ,
657669 mut max_directional_lights_warning_emitted : Local < bool > ,
658670 mut max_cascades_per_light_warning_emitted : Local < bool > ,
659- point_lights : Query < ( Entity , & ExtractedPointLight ) > ,
671+ point_lights : Query < (
672+ Entity ,
673+ & ExtractedPointLight ,
674+ AnyOf < ( & CubemapFrusta , & Frustum ) > ,
675+ ) > ,
660676 directional_lights : Query < ( Entity , & ExtractedDirectionalLight ) > ,
661677) {
662678 let views_iter = views. iter ( ) ;
@@ -733,7 +749,7 @@ pub fn prepare_lights(
733749
734750 let spot_light_shadow_maps_count = point_lights
735751 . iter ( )
736- . filter ( |( _, light) | light. shadows_enabled && light. spot_light_angles . is_some ( ) )
752+ . filter ( |( _, light, _ ) | light. shadows_enabled && light. spot_light_angles . is_some ( ) )
737753 . count ( )
738754 . min ( max_texture_array_layers - directional_shadow_enabled_count * MAX_CASCADES_PER_LIGHT ) ;
739755
@@ -742,7 +758,7 @@ pub fn prepare_lights(
742758 // - then those with shadows enabled first, so that the index can be used to render at most `point_light_shadow_maps_count`
743759 // point light shadows and `spot_light_shadow_maps_count` spot light shadow maps,
744760 // - then by entity as a stable key to ensure that a consistent set of lights are chosen if the light count limit is exceeded.
745- point_lights. sort_by ( |( entity_1, light_1) , ( entity_2, light_2) | {
761+ point_lights. sort_by ( |( entity_1, light_1, _ ) , ( entity_2, light_2, _ ) | {
746762 point_light_order (
747763 (
748764 entity_1,
@@ -775,7 +791,7 @@ pub fn prepare_lights(
775791 }
776792
777793 let mut gpu_point_lights = Vec :: new ( ) ;
778- for ( index, & ( entity, light) ) in point_lights. iter ( ) . enumerate ( ) {
794+ for ( index, & ( entity, light, _ ) ) in point_lights. iter ( ) . enumerate ( ) {
779795 let mut flags = PointLightFlags :: NONE ;
780796
781797 // Lights are sorted, shadow enabled lights are first
@@ -952,11 +968,11 @@ pub fn prepare_lights(
952968 } ;
953969
954970 // TODO: this should select lights based on relevance to the view instead of the first ones that show up in a query
955- for & ( light_entity, light) in point_lights
971+ for & ( light_entity, light, ( point_light_frusta , _ ) ) in point_lights
956972 . iter ( )
957973 // Lights are sorted, shadow enabled lights are first
958974 . take ( point_light_shadow_maps_count)
959- . filter ( |( _, light) | light. shadows_enabled )
975+ . filter ( |( _, light, _ ) | light. shadows_enabled )
960976 {
961977 let light_index = * global_light_meta
962978 . entity_to_index
@@ -967,7 +983,11 @@ pub fn prepare_lights(
967983 // and ignore rotation because we want the shadow map projections to align with the axes
968984 let view_translation = GlobalTransform :: from_translation ( light. transform . translation ( ) ) ;
969985
970- for ( face_index, view_rotation) in cube_face_rotations. iter ( ) . enumerate ( ) {
986+ for ( face_index, ( view_rotation, frustum) ) in cube_face_rotations
987+ . iter ( )
988+ . zip ( & point_light_frusta. unwrap ( ) . frusta )
989+ . enumerate ( )
990+ {
971991 let depth_texture_view =
972992 point_light_depth_texture
973993 . texture
@@ -1005,6 +1025,7 @@ pub fn prepare_lights(
10051025 hdr : false ,
10061026 color_grading : Default :: default ( ) ,
10071027 } ,
1028+ * frustum,
10081029 RenderPhase :: < Shadow > :: default ( ) ,
10091030 LightEntity :: Point {
10101031 light_entity,
@@ -1017,7 +1038,7 @@ pub fn prepare_lights(
10171038 }
10181039
10191040 // spot lights
1020- for ( light_index, & ( light_entity, light) ) in point_lights
1041+ for ( light_index, & ( light_entity, light, ( _ , spot_light_frustum ) ) ) in point_lights
10211042 . iter ( )
10221043 . skip ( point_light_count)
10231044 . take ( spot_light_shadow_maps_count)
@@ -1063,6 +1084,7 @@ pub fn prepare_lights(
10631084 hdr : false ,
10641085 color_grading : Default :: default ( ) ,
10651086 } ,
1087+ * spot_light_frustum. unwrap ( ) ,
10661088 RenderPhase :: < Shadow > :: default ( ) ,
10671089 LightEntity :: Spot { light_entity } ,
10681090 ) )
@@ -1078,12 +1100,20 @@ pub fn prepare_lights(
10781100 . enumerate ( )
10791101 . take ( directional_shadow_enabled_count)
10801102 {
1081- for ( cascade_index , ( cascade , bound ) ) in light
1103+ let cascades = light
10821104 . cascades
10831105 . get ( & entity)
10841106 . unwrap ( )
10851107 . iter ( )
1086- . take ( MAX_CASCADES_PER_LIGHT )
1108+ . take ( MAX_CASCADES_PER_LIGHT ) ;
1109+ let frusta = light
1110+ . frusta
1111+ . get ( & entity)
1112+ . unwrap ( )
1113+ . iter ( )
1114+ . take ( MAX_CASCADES_PER_LIGHT ) ;
1115+ for ( cascade_index, ( ( cascade, frusta) , bound) ) in cascades
1116+ . zip ( frusta)
10871117 . zip ( & light. cascade_shadow_config . bounds )
10881118 . enumerate ( )
10891119 {
@@ -1129,6 +1159,7 @@ pub fn prepare_lights(
11291159 hdr : false ,
11301160 color_grading : Default :: default ( ) ,
11311161 } ,
1162+ * frusta,
11321163 RenderPhase :: < Shadow > :: default ( ) ,
11331164 LightEntity :: Directional {
11341165 light_entity,
0 commit comments