66#import bevy_render :: maths :: PI
77#import bevy_render :: view :: View
88#import bevy_solari :: brdf :: evaluate_diffuse_brdf
9- #import bevy_solari :: gbuffer_utils :: {gpixel_resolve , pixel_dissimilar }
9+ #import bevy_solari :: gbuffer_utils :: {gpixel_resolve , pixel_dissimilar , permute_pixel }
1010#import bevy_solari :: sampling :: {sample_random_light , trace_point_visibility }
1111#import bevy_solari :: scene_bindings :: {trace_ray , resolve_ray_hit_full , RAY_T_MIN , RAY_T_MAX }
1212#import bevy_solari :: world_cache :: query_world_cache
@@ -67,7 +67,9 @@ fn spatial_and_shade(@builtin(global_invocation_id) global_id: vec3<u32>) {
6767 let spatial = load_spatial_reservoir (global_id . xy , depth , surface . world_position , surface . world_normal , & rng );
6868 let merge_result = merge_reservoirs (input_reservoir , surface . world_position , surface . world_normal , surface . material . base_color / PI ,
6969 spatial . reservoir , spatial . world_position , spatial . world_normal , spatial . diffuse_brdf , & rng );
70- let combined_reservoir = merge_result . merged_reservoir ;
70+ var combined_reservoir = merge_result . merged_reservoir ;
71+
72+ combined_reservoir . radiance *= trace_point_visibility (surface . world_position , combined_reservoir . sample_point_world_position );
7173
7274 gi_reservoirs_a [pixel_index ] = combined_reservoir ;
7375
@@ -76,10 +78,6 @@ fn spatial_and_shade(@builtin(global_invocation_id) global_id: vec3<u32>) {
7678 var pixel_color = textureLoad (view_output , global_id . xy );
7779 pixel_color += vec4 (merge_result . selected_sample_radiance * combined_reservoir . unbiased_contribution_weight * view . exposure * brdf , 0 .0 );
7880 textureStore (view_output , global_id . xy , pixel_color );
79-
80- #ifdef VISUALIZE_WORLD_CACHE
81- textureStore (view_output , global_id . xy , vec4 (query_world_cache (surface . world_position , surface . world_normal , view . world_position ) * view . exposure , 1 .0 ));
82- #endif
8381}
8482
8583fn generate_initial_reservoir (world_position : vec3 <f32 >, world_normal : vec3 <f32 >, rng : ptr <function , u32 >) -> Reservoir {
@@ -107,7 +105,7 @@ fn generate_initial_reservoir(world_position: vec3<f32>, world_normal: vec3<f32>
107105 reservoir . radiance = direct_lighting . radiance ;
108106 reservoir . unbiased_contribution_weight = direct_lighting . inverse_pdf * uniform_hemisphere_inverse_pdf ();
109107#else
110- reservoir . radiance = query_world_cache (sample_point . world_position , sample_point . geometric_world_normal , view . world_position );
108+ reservoir . radiance = query_world_cache (sample_point . world_position , sample_point . geometric_world_normal , view . world_position , rng );
111109 reservoir . unbiased_contribution_weight = uniform_hemisphere_inverse_pdf ();
112110#endif
113111
@@ -120,43 +118,28 @@ fn generate_initial_reservoir(world_position: vec3<f32>, world_normal: vec3<f32>
120118fn load_temporal_reservoir (pixel_id : vec2 <u32 >, depth : f32 , world_position : vec3 <f32 >, world_normal : vec3 <f32 >) -> NeighborInfo {
121119 let motion_vector = textureLoad (motion_vectors , pixel_id , 0 ). xy ;
122120 let temporal_pixel_id_float = round (vec2 <f32 >(pixel_id ) - (motion_vector * view . main_pass_viewport . zw ));
121+ let temporal_pixel_id = permute_pixel (vec2 <u32 >(temporal_pixel_id_float ), constants . frame_index , view . viewport . zw );
123122
124123 // Check if the current pixel was off screen during the previous frame (current pixel is newly visible),
125124 // or if all temporal history should assumed to be invalid
126125 if any (temporal_pixel_id_float < vec2 (0 .0 )) || any (temporal_pixel_id_float >= view . main_pass_viewport . zw ) || bool (constants . reset ) {
127126 return NeighborInfo (empty_reservoir (), vec3 (0 .0 ), vec3 (0 .0 ), vec3 (0 .0 ));
128127 }
129128
130- let temporal_pixel_id_base = vec2 <u32 >(round (temporal_pixel_id_float ));
131- for (var i = 0u ; i < 4u ; i ++ ) {
132- let temporal_pixel_id = permute_pixel (temporal_pixel_id_base , i );
133-
134- // Check if the pixel features have changed heavily between the current and previous frame
135- let temporal_depth = textureLoad (previous_depth_buffer , temporal_pixel_id , 0 );
136- let temporal_surface = gpixel_resolve (textureLoad (previous_gbuffer , temporal_pixel_id , 0 ), temporal_depth , temporal_pixel_id , view . main_pass_viewport . zw , previous_view . world_from_clip );
137- let temporal_diffuse_brdf = temporal_surface . material . base_color / PI ;
138- if pixel_dissimilar (depth , world_position , temporal_surface . world_position , world_normal , temporal_surface . world_normal , view ) {
139- continue ;
140- }
141-
142- let temporal_pixel_index = temporal_pixel_id . x + temporal_pixel_id . y * u32 (view . main_pass_viewport . z );
143- var temporal_reservoir = gi_reservoirs_a [temporal_pixel_index ];
144-
145- temporal_reservoir . confidence_weight = min (temporal_reservoir . confidence_weight , CONFIDENCE_WEIGHT_CAP );
146-
147- return NeighborInfo (temporal_reservoir , temporal_surface . world_position , temporal_surface . world_normal , temporal_diffuse_brdf );
129+ // Check if the pixel features have changed heavily between the current and previous frame
130+ let temporal_depth = textureLoad (previous_depth_buffer , temporal_pixel_id , 0 );
131+ let temporal_surface = gpixel_resolve (textureLoad (previous_gbuffer , temporal_pixel_id , 0 ), temporal_depth , temporal_pixel_id , view . main_pass_viewport . zw , previous_view . world_from_clip );
132+ let temporal_diffuse_brdf = temporal_surface . material . base_color / PI ;
133+ if pixel_dissimilar (depth , world_position , temporal_surface . world_position , world_normal , temporal_surface . world_normal , view ) {
134+ return NeighborInfo (empty_reservoir (), vec3 (0 .0 ), vec3 (0 .0 ), vec3 (0 .0 ));
148135 }
149136
150- return NeighborInfo ( empty_reservoir (), vec3 ( 0 .0 ), vec3 ( 0 .0 ), vec3 ( 0 .0 ) );
151- }
137+ let temporal_pixel_index = temporal_pixel_id . x + temporal_pixel_id . y * u32 ( view . main_pass_viewport . z );
138+ var temporal_reservoir = gi_reservoirs_a [ temporal_pixel_index ];
152139
153- fn permute_pixel (pixel_id : vec2 <u32 >, i : u32 ) -> vec2 <u32 > {
154- let r = constants . frame_index + i ;
155- let offset = vec2 (r & 3u , (r >> 2u ) & 3u );
156- var shifted_pixel_id = pixel_id + offset ;
157- shifted_pixel_id ^= vec2 (3u );
158- shifted_pixel_id -= offset ;
159- return min (shifted_pixel_id , vec2 <u32 >(view . main_pass_viewport . zw - 1 .0 ));
140+ temporal_reservoir . confidence_weight = min (temporal_reservoir . confidence_weight , CONFIDENCE_WEIGHT_CAP );
141+
142+ return NeighborInfo (temporal_reservoir , temporal_surface . world_position , temporal_surface . world_normal , temporal_diffuse_brdf );
160143}
161144
162145fn load_spatial_reservoir (pixel_id : vec2 <u32 >, depth : f32 , world_position : vec3 <f32 >, world_normal : vec3 <f32 >, rng : ptr <function , u32 >) -> NeighborInfo {
@@ -170,9 +153,7 @@ fn load_spatial_reservoir(pixel_id: vec2<u32>, depth: f32, world_position: vec3<
170153 }
171154
172155 let spatial_pixel_index = spatial_pixel_id . x + spatial_pixel_id . y * u32 (view . main_pass_viewport . z );
173- var spatial_reservoir = gi_reservoirs_b [spatial_pixel_index ];
174-
175- spatial_reservoir . radiance *= trace_point_visibility (world_position , spatial_reservoir . sample_point_world_position );
156+ let spatial_reservoir = gi_reservoirs_b [spatial_pixel_index ];
176157
177158 return NeighborInfo (spatial_reservoir , spatial_surface . world_position , spatial_surface . world_normal , spatial_diffuse_brdf );
178159}
@@ -252,27 +233,19 @@ fn merge_reservoirs(
252233 rng : ptr <function , u32 >,
253234) -> ReservoirMergeResult {
254235 // Radiances for resampling
255- let canonical_sample_radiance =
256- canonical_reservoir . radiance *
257- saturate (dot (normalize (canonical_reservoir . sample_point_world_position - canonical_world_position ), canonical_world_normal ));
258- let other_sample_radiance =
259- other_reservoir . radiance *
260- saturate (dot (normalize (other_reservoir . sample_point_world_position - canonical_world_position ), canonical_world_normal ));
236+ let canonical_sample_radiance = canonical_reservoir . radiance * saturate (dot (normalize (canonical_reservoir . sample_point_world_position - canonical_world_position ), canonical_world_normal ));
237+ let other_sample_radiance = other_reservoir . radiance * saturate (dot (normalize (other_reservoir . sample_point_world_position - canonical_world_position ), canonical_world_normal ));
261238
262239 // Target functions for resampling and MIS
263240 let canonical_target_function_canonical_sample = luminance (canonical_sample_radiance * canonical_diffuse_brdf );
264241 let canonical_target_function_other_sample = luminance (other_sample_radiance * canonical_diffuse_brdf );
265242
266243 // Extra target functions for MIS
267244 let other_target_function_canonical_sample = luminance (
268- canonical_reservoir . radiance *
269- saturate (dot (normalize (canonical_reservoir . sample_point_world_position - other_world_position ), other_world_normal )) *
270- other_diffuse_brdf
245+ canonical_reservoir . radiance * saturate (dot (normalize (canonical_reservoir . sample_point_world_position - other_world_position ), other_world_normal )) * other_diffuse_brdf
271246 );
272247 let other_target_function_other_sample = luminance (
273- other_reservoir . radiance *
274- saturate (dot (normalize (other_reservoir . sample_point_world_position - other_world_position ), other_world_normal )) *
275- other_diffuse_brdf
248+ other_reservoir . radiance * saturate (dot (normalize (other_reservoir . sample_point_world_position - other_world_position ), other_world_normal )) * other_diffuse_brdf
276249 );
277250
278251 // Jacobians for resampling and MIS
@@ -299,19 +272,14 @@ fn merge_reservoirs(
299272 canonical_reservoir . confidence_weight * canonical_target_function_canonical_sample ,
300273 other_reservoir . confidence_weight * other_target_function_canonical_sample * other_target_function_canonical_sample_jacobian ,
301274 );
302- let canonical_sample_resampling_weight = canonical_sample_mis_weight *
303- canonical_target_function_canonical_sample *
304- canonical_reservoir . unbiased_contribution_weight ;
275+ let canonical_sample_resampling_weight = canonical_sample_mis_weight * canonical_target_function_canonical_sample * canonical_reservoir . unbiased_contribution_weight ;
305276
306277 // Resampling weight for other sample
307278 let other_sample_mis_weight = balance_heuristic (
308279 other_reservoir . confidence_weight * other_target_function_other_sample ,
309280 canonical_reservoir . confidence_weight * canonical_target_function_other_sample * canonical_target_function_other_sample_jacobian ,
310281 );
311- let other_sample_resampling_weight = other_sample_mis_weight *
312- canonical_target_function_other_sample *
313- other_reservoir . unbiased_contribution_weight *
314- canonical_target_function_other_sample_jacobian ;
282+ let other_sample_resampling_weight = other_sample_mis_weight * canonical_target_function_other_sample * other_reservoir . unbiased_contribution_weight * canonical_target_function_other_sample_jacobian ;
315283
316284 // Perform resampling
317285 var combined_reservoir = empty_reservoir ();
0 commit comments