Skip to content

Commit e44d659

Browse files
authored
Solari: Misc improvements (#21953)
* Search for a spatial neighbor up to 5 times for ReSTIR instead of just once. * Bump RAY_T_MIN to 0.001. Prevents artifacts and doesn't really cause more self intersections. * Re-calculate world cache cell_size after jittering the query position to prevent creating extra cells at the wrong LOD for a given position. * Prevent the unlikely event of something checksumming to 0, which is reserved for empty cells.
1 parent d597657 commit e44d659

File tree

4 files changed

+29
-20
lines changed

4 files changed

+29
-20
lines changed

crates/bevy_solari/src/realtime/restir_di.wgsl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,19 @@ fn load_temporal_reservoir_inner(temporal_pixel_id: vec2<u32>, depth: f32, world
179179
}
180180

181181
fn load_spatial_reservoir(pixel_id: vec2<u32>, depth: f32, world_position: vec3<f32>, world_normal: vec3<f32>, rng: ptr<function, u32>) -> Reservoir {
182-
let spatial_pixel_id = get_neighbor_pixel_id(pixel_id, rng);
182+
for (var i = 0u; i < 5u; i++) {
183+
let spatial_pixel_id = get_neighbor_pixel_id(pixel_id, rng);
183184

184-
let spatial_depth = textureLoad(depth_buffer, spatial_pixel_id, 0);
185-
let spatial_surface = gpixel_resolve(textureLoad(gbuffer, spatial_pixel_id, 0), spatial_depth, spatial_pixel_id, view.main_pass_viewport.zw, view.world_from_clip);
186-
if pixel_dissimilar(depth, world_position, spatial_surface.world_position, world_normal, spatial_surface.world_normal, view) {
187-
return empty_reservoir();
185+
let spatial_depth = textureLoad(depth_buffer, spatial_pixel_id, 0);
186+
let spatial_surface = gpixel_resolve(textureLoad(gbuffer, spatial_pixel_id, 0), spatial_depth, spatial_pixel_id, view.main_pass_viewport.zw, view.world_from_clip);
187+
if pixel_dissimilar(depth, world_position, spatial_surface.world_position, world_normal, spatial_surface.world_normal, view) {
188+
continue;
189+
}
190+
191+
return load_reservoir_b(spatial_pixel_id);
188192
}
189193

190-
return load_reservoir_b(spatial_pixel_id);
194+
return empty_reservoir();
191195
}
192196

193197
fn get_neighbor_pixel_id(center_pixel_id: vec2<u32>, rng: ptr<function, u32>) -> vec2<u32> {

crates/bevy_solari/src/realtime/restir_gi.wgsl

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -152,21 +152,25 @@ fn load_temporal_reservoir_inner(temporal_pixel_id: vec2<u32>, depth: f32, world
152152
}
153153

154154
fn load_spatial_reservoir(pixel_id: vec2<u32>, depth: f32, world_position: vec3<f32>, world_normal: vec3<f32>, rng: ptr<function, u32>) -> NeighborInfo {
155-
let spatial_pixel_id = get_neighbor_pixel_id(pixel_id, rng);
155+
for (var i = 0u; i < 5u; i++) {
156+
let spatial_pixel_id = get_neighbor_pixel_id(pixel_id, rng);
156157

157-
let spatial_depth = textureLoad(depth_buffer, spatial_pixel_id, 0);
158-
let spatial_surface = gpixel_resolve(textureLoad(gbuffer, spatial_pixel_id, 0), spatial_depth, spatial_pixel_id, view.main_pass_viewport.zw, view.world_from_clip);
159-
let spatial_diffuse_brdf = spatial_surface.material.base_color / PI;
160-
if pixel_dissimilar(depth, world_position, spatial_surface.world_position, world_normal, spatial_surface.world_normal, view) {
161-
return NeighborInfo(empty_reservoir(), spatial_surface.world_position, spatial_surface.world_normal, spatial_diffuse_brdf);
162-
}
158+
let spatial_depth = textureLoad(depth_buffer, spatial_pixel_id, 0);
159+
let spatial_surface = gpixel_resolve(textureLoad(gbuffer, spatial_pixel_id, 0), spatial_depth, spatial_pixel_id, view.main_pass_viewport.zw, view.world_from_clip);
160+
let spatial_diffuse_brdf = spatial_surface.material.base_color / PI;
161+
if pixel_dissimilar(depth, world_position, spatial_surface.world_position, world_normal, spatial_surface.world_normal, view) {
162+
continue;
163+
}
164+
165+
let spatial_pixel_index = spatial_pixel_id.x + spatial_pixel_id.y * u32(view.main_pass_viewport.z);
166+
var spatial_reservoir = gi_reservoirs_b[spatial_pixel_index];
163167

164-
let spatial_pixel_index = spatial_pixel_id.x + spatial_pixel_id.y * u32(view.main_pass_viewport.z);
165-
var spatial_reservoir = gi_reservoirs_b[spatial_pixel_index];
168+
spatial_reservoir.radiance *= trace_point_visibility(world_position, spatial_reservoir.sample_point_world_position);
166169

167-
spatial_reservoir.radiance *= trace_point_visibility(world_position, spatial_reservoir.sample_point_world_position);
170+
return NeighborInfo(spatial_reservoir, spatial_surface.world_position, spatial_surface.world_normal, spatial_diffuse_brdf);
171+
}
168172

169-
return NeighborInfo(spatial_reservoir, spatial_surface.world_position, spatial_surface.world_normal, spatial_diffuse_brdf);
173+
return NeighborInfo(empty_reservoir(), world_position, world_normal, vec3(0.0));
170174
}
171175

172176
fn get_neighbor_pixel_id(center_pixel_id: vec2<u32>, rng: ptr<function, u32>) -> vec2<u32> {

crates/bevy_solari/src/realtime/world_cache_query.wgsl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,13 @@ struct WorldCacheGeometryData {
4747

4848
#ifndef WORLD_CACHE_NON_ATOMIC_LIFE_BUFFER
4949
fn query_world_cache(world_position: vec3<f32>, world_normal: vec3<f32>, view_position: vec3<f32>, cell_lifetime: u32, rng: ptr<function, u32>) -> vec3<f32> {
50-
let cell_size = get_cell_size(world_position, view_position);
50+
var cell_size = get_cell_size(world_position, view_position);
5151

5252
// https://tomclabault.github.io/blog/2025/regir, jitter_world_position_tangent_plane
5353
let TBN = orthonormalize(world_normal);
5454
let offset = (rand_vec2f(rng) * 2.0 - 1.0) * cell_size * 0.5;
5555
let jittered_position = world_position + offset.x * TBN[0] + offset.y * TBN[1];
56+
cell_size = get_cell_size(jittered_position, view_position);
5657

5758
let world_position_quantized = bitcast<vec3<u32>>(quantize_position(jittered_position, cell_size));
5859
let world_normal_quantized = bitcast<vec3<u32>>(quantize_normal(world_normal));
@@ -121,7 +122,7 @@ fn compute_checksum(world_position: vec3<u32>, world_normal: vec3<u32>) -> u32 {
121122
key = iqint_hash(key + world_normal.x);
122123
key = iqint_hash(key + world_normal.y);
123124
key = iqint_hash(key + world_normal.z);
124-
return key;
125+
return max(key, 1u); // 0u is reserved for WORLD_CACHE_EMPTY_CELL
125126
}
126127

127128
fn pcg_hash(input: u32) -> u32 {

crates/bevy_solari/src/scene/raytracing_scene_bindings.wgsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const LIGHT_NOT_PRESENT_THIS_FRAME = 0xFFFFFFFFu;
8383
@group(0) @binding(10) var<storage> directional_lights: array<DirectionalLight>;
8484
@group(0) @binding(11) var<storage> previous_frame_light_id_translations: array<u32>;
8585

86-
const RAY_T_MIN = 0.01f;
86+
const RAY_T_MIN = 0.001f;
8787
const RAY_T_MAX = 100000.0f;
8888

8989
const RAY_NO_CULL = 0xFFu;

0 commit comments

Comments
 (0)