11use crate :: {
2- light:: { AmbientLight , PointLight , PointLightUniform } ,
2+ light:: {
3+ AmbientLight , DirectionalLight , DirectionalLightUniform , PointLight , PointLightUniform ,
4+ } ,
35 render_graph:: uniform,
46} ;
57use bevy_core:: { AsBytes , Byteable } ;
@@ -21,12 +23,14 @@ use bevy_transform::prelude::*;
2123pub struct LightsNode {
2224 command_queue : CommandQueue ,
2325 max_point_lights : usize ,
26+ max_dir_lights : usize ,
2427}
2528
2629impl LightsNode {
27- pub fn new ( max_lights : usize ) -> Self {
30+ pub fn new ( max_point_lights : usize , max_dir_lights : usize ) -> Self {
2831 LightsNode {
29- max_point_lights : max_lights,
32+ max_point_lights,
33+ max_dir_lights,
3034 command_queue : CommandQueue :: default ( ) ,
3135 }
3236 }
@@ -48,6 +52,8 @@ impl Node for LightsNode {
4852#[ derive( Debug , Clone , Copy ) ]
4953struct LightCount {
5054 // storing as a `[u32; 4]` for memory alignement
55+ // Index 0 is for point lights,
56+ // Index 1 is for directional lights
5157 pub num_lights : [ u32 ; 4 ] ,
5258}
5359
@@ -59,6 +65,7 @@ impl SystemNode for LightsNode {
5965 config. 0 = Some ( LightsNodeSystemState {
6066 command_queue : self . command_queue . clone ( ) ,
6167 max_point_lights : self . max_point_lights ,
68+ max_dir_lights : self . max_dir_lights ,
6269 light_buffer : None ,
6370 staging_buffer : None ,
6471 } )
@@ -74,6 +81,7 @@ pub struct LightsNodeSystemState {
7481 staging_buffer : Option < BufferId > ,
7582 command_queue : CommandQueue ,
7683 max_point_lights : usize ,
84+ max_dir_lights : usize ,
7785}
7886
7987pub fn lights_node_system (
@@ -83,7 +91,8 @@ pub fn lights_node_system(
8391 // TODO: this write on RenderResourceBindings will prevent this system from running in parallel
8492 // with other systems that do the same
8593 mut render_resource_bindings : ResMut < RenderResourceBindings > ,
86- query : Query < ( & PointLight , & GlobalTransform ) > ,
94+ point_lights : Query < ( & PointLight , & GlobalTransform ) > ,
95+ dir_lights : Query < & DirectionalLight > ,
8796) {
8897 let state = & mut state;
8998 let render_resource_context = & * * render_resource_context;
@@ -92,16 +101,31 @@ pub fn lights_node_system(
92101 let ambient_light: [ f32 ; 4 ] =
93102 ( ambient_light_resource. color * ambient_light_resource. brightness ) . into ( ) ;
94103 let ambient_light_size = std:: mem:: size_of :: < [ f32 ; 4 ] > ( ) ;
95- let point_light_count = query. iter ( ) . len ( ) . min ( state. max_point_lights ) ;
96- let size = std:: mem:: size_of :: < PointLightUniform > ( ) ;
104+
105+ let point_light_count = point_lights. iter ( ) . len ( ) . min ( state. max_point_lights ) ;
106+ let point_light_size = std:: mem:: size_of :: < PointLightUniform > ( ) ;
107+ let point_light_array_size = point_light_size * point_light_count;
108+ let point_light_array_max_size = point_light_size * state. max_point_lights ;
109+
110+ let dir_light_count = dir_lights. iter ( ) . len ( ) . min ( state. max_dir_lights ) ;
111+ let dir_light_size = std:: mem:: size_of :: < DirectionalLightUniform > ( ) ;
112+ let dir_light_array_size = dir_light_size * dir_light_count;
113+ let dir_light_array_max_size = dir_light_size * state. max_dir_lights ;
114+
97115 let light_count_size = ambient_light_size + std:: mem:: size_of :: < LightCount > ( ) ;
98- let point_light_array_size = size * point_light_count;
99- let point_light_array_max_size = size * state. max_point_lights ;
100- let current_point_light_uniform_size = light_count_size + point_light_array_size;
101- let max_light_uniform_size = light_count_size + point_light_array_max_size;
116+
117+ let point_light_uniform_start = light_count_size;
118+ let point_light_uniform_end = light_count_size + point_light_array_size;
119+
120+ let dir_light_uniform_start = light_count_size + point_light_array_max_size;
121+ let dir_light_uniform_end =
122+ light_count_size + point_light_array_max_size + dir_light_array_size;
123+
124+ let max_light_uniform_size =
125+ light_count_size + point_light_array_max_size + dir_light_array_max_size;
102126
103127 if let Some ( staging_buffer) = state. staging_buffer {
104- if point_light_count == 0 {
128+ if point_light_count == 0 && dir_light_count == 0 {
105129 return ;
106130 }
107131
@@ -133,23 +157,33 @@ pub fn lights_node_system(
133157 let staging_buffer = state. staging_buffer . unwrap ( ) ;
134158 render_resource_context. write_mapped_buffer (
135159 staging_buffer,
136- 0 ..current_point_light_uniform_size as u64 ,
160+ 0 ..max_light_uniform_size as u64 ,
137161 & mut |data, _renderer| {
138162 // ambient light
139163 data[ 0 ..ambient_light_size] . copy_from_slice ( ambient_light. as_bytes ( ) ) ;
140164
141165 // light count
142- data[ ambient_light_size..light_count_size]
143- . copy_from_slice ( [ point_light_count as u32 , 0 , 0 , 0 ] . as_bytes ( ) ) ;
166+ data[ ambient_light_size..light_count_size] . copy_from_slice (
167+ [ point_light_count as u32 , dir_light_count as u32 , 0 , 0 ] . as_bytes ( ) ,
168+ ) ;
144169
145- // light array
146- for ( ( point_light, global_transform) , slot) in query. iter ( ) . zip (
147- data[ light_count_size..current_point_light_uniform_size] . chunks_exact_mut ( size) ,
170+ // point light array
171+ for ( ( point_light, global_transform) , slot) in point_lights. iter ( ) . zip (
172+ data[ point_light_uniform_start..point_light_uniform_end]
173+ . chunks_exact_mut ( point_light_size) ,
148174 ) {
149175 slot. copy_from_slice (
150- PointLightUniform :: from ( & point_light, & global_transform) . as_bytes ( ) ,
176+ PointLightUniform :: new ( & point_light, & global_transform) . as_bytes ( ) ,
151177 ) ;
152178 }
179+
180+ // directional light array
181+ for ( dir_light, slot) in dir_lights. iter ( ) . zip (
182+ data[ dir_light_uniform_start..dir_light_uniform_end]
183+ . chunks_exact_mut ( dir_light_size) ,
184+ ) {
185+ slot. copy_from_slice ( DirectionalLightUniform :: new ( & dir_light) . as_bytes ( ) ) ;
186+ }
153187 } ,
154188 ) ;
155189 render_resource_context. unmap_buffer ( staging_buffer) ;
0 commit comments