Skip to content

Commit c9ca149

Browse files
committed
[path_tracing] cleanup
1 parent b95b5dc commit c9ca149

15 files changed

Lines changed: 89 additions & 430 deletions

data/shaders/light_composition.hlsl

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,16 +157,11 @@ void main_cs(uint3 thread_id : SV_DispatchThreadID)
157157
// upsample (depth + normal aware) to avoid bleeding across edges
158158
// also multiply by surface.occlusion to recover contact shadows that
159159
// restir's spatial reuse and denoiser smear away at small scales
160-
// debug mode writes a heatmap into the gi slot, the remodulator is skipped there so
161-
// the viridis colors are not tinted by surface albedo
162160
if (is_restir_pt_enabled())
163161
{
164162
float depth_dst_lin = linearize_depth(surface.depth);
165-
light_gi = sample_gi_bilateral(surface.uv, depth_dst_lin, surface.normal);
166-
if (uint(buffer_frame.restir_pt_debug_mode) == 0u)
167-
{
168-
light_gi *= restir_albedo_demodulator(surface.albedo);
169-
}
163+
light_gi = sample_gi_bilateral(surface.uv, depth_dst_lin, surface.normal);
164+
light_gi *= restir_albedo_demodulator(surface.albedo);
170165
light_gi *= surface.occlusion;
171166
}
172167
}

data/shaders/light_image_based.hlsl

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,23 +99,17 @@ void main_cs(uint3 thread_id : SV_DispatchThreadID)
9999
float3 diffuse_ibl = diffuse_skysphere * diffuse_occlusion * diffuse_energy * surface.albedo.rgb;
100100
float3 specular_ibl = specular_skysphere * specular_energy * specular_occlusion;
101101

102-
// ray traced reflections owns specular indirect across the full roughness range when enabled
103-
if (is_ray_traced_reflections_enabled())
102+
// restir path tracing owns the full brdf at the primary, so it produces both diffuse and
103+
// specular indirect, when restir is on we drop both ibl terms to avoid double counting
104+
// otherwise rt reflections (when enabled) owns specular and the cubemap diffuse handles ao
105+
if (is_restir_pt_enabled())
104106
{
107+
diffuse_ibl *= 0.0f;
105108
specular_ibl *= 0.0f;
106109
}
107-
108-
// restir path tracing owns diffuse indirect always, and the specular indirect lobe for
109-
// moderate to high roughness surfaces (paper-faithful full brdf at the primary), zeroing
110-
// specular_ibl in that range avoids double counting when rt reflections is off, near mirror
111-
// surfaces still receive specular_ibl as the fallback when rt reflections is unavailable
112-
if (is_restir_pt_enabled())
110+
else if (is_ray_traced_reflections_enabled())
113111
{
114-
diffuse_ibl *= 0.0f;
115-
if (surface.roughness >= 0.2f)
116-
{
117-
specular_ibl *= 0.0f;
118-
}
112+
specular_ibl *= 0.0f;
119113
}
120114

121115
// transparents take full ibl, fresnel inside the split sum already governs the reflection split

data/shaders/restir_pt.hlsl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2424
#include "restir_reservoir.hlsl"
2525
//==============================
2626

27-
// upper bounds on the per pixel ris pool sizes, the actual counts come from cvars
28-
// r.restir_pt_initial_candidates -> brdf stream (cap below)
29-
// r.restir_pt_light_candidates -> nee stream (cap below)
30-
// caps are sized so the unrolled loop pressure is bounded but the user can tune for quality
27+
// upper bounds on the per pixel ris pool sizes, the live counts come from get_restir_*
28+
// helpers in restir_reservoir.hlsl which return paper-faithful hardcoded values (1 brdf
29+
// candidate, 8 nee candidates), the caps below only bound the unrolled loop size
3130
static const uint INITIAL_CANDIDATE_SAMPLES_MAX = 8;
3231
static const uint LIGHT_RIS_CANDIDATE_SAMPLES_MAX = 64;
3332
static const float MIN_COS_AT_PRIMARY = 1e-3f;
@@ -594,8 +593,8 @@ void trace_rc_suffix(
594593
}
595594

596595
// gathers the rc vertex's nee + emission contribution (with rc bsdf baked in at src view dir,
597-
// view-dep bias bounded by RESTIR_RC_MIN_ROUGHNESS gate on rc reuse) and the suffix radiance
598-
// past rc (with rc bsdf factored out into rc_outgoing_dir for paper-faithful shift evaluation)
596+
// view-dep bias bounded by the get_restir_rc_min_roughness floor on rc reuse) and the suffix
597+
// radiance past rc (with rc bsdf factored out into rc_outgoing_dir for paper-faithful shifts)
599598
void accumulate_subpath_at_rc(
600599
PathPayload rc,
601600
float3 rc_view_dir,
@@ -846,10 +845,18 @@ PathSample trace_path_from_primary(
846845
L_nee = max(L_nee, 0.0f);
847846
L_post = max(L_post, 0.0f);
848847

849-
// no source side firefly clamp here, the lin 2022 estimator is unbiased and the energy
850-
// bound is provided by the m cap, the per sample W clamp, and the variance aware denoiser
851-
// downstream, scaling the suffix luminance was a downward bias on bright reflections that
852-
// also fought the denoiser's variance estimate
848+
// soft luminance clamp, the W clamp + m cap bound the unbiased estimator energy but not
849+
// single sample variance, when a glossy rc lands on a bright emitter the rc bsdf baked
850+
// into rc_L_nee can spike to thousands of nits and a stable spatial neighbor will then
851+
// stamp that pulse across many pixels (boiling), the soft scale preserves chromaticity so
852+
// the residual downward bias is uniform across channels and the denoiser absorbs the rest
853+
{
854+
float lum_nee = luminance(L_nee);
855+
float lum_post = luminance(L_post);
856+
const float firefly_ceiling = 250.0f;
857+
if (lum_nee > firefly_ceiling) L_nee *= firefly_ceiling / lum_nee;
858+
if (lum_post > firefly_ceiling) L_post *= firefly_ceiling / lum_post;
859+
}
853860

854861
s.rc_L_nee = L_nee;
855862
s.rc_L_post = L_post;

data/shaders/restir_pt_debug.hlsl

Lines changed: 0 additions & 170 deletions
This file was deleted.

data/shaders/restir_pt_denoise_temporal.hlsl

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -295,16 +295,27 @@ void main_cs(uint3 dispatch_id : SV_DispatchThreadID)
295295
history_weight = saturate(min(history_weight, 0.992f));
296296
}
297297

298+
// small 3x3 mean+variance pre blur (schied 2017 §4.2) so isolated bright fireflies do not
299+
// pin the variance estimate to a single pixel, this stabilizes the spatial filter weights
300+
// and gives the firefly clamp below a reliable spatial sigma even when history is young
301+
float3 mean_color, sigma_color, min_color, max_color;
302+
compute_local_statistics(pixel, resolution, mean_color, sigma_color, min_color, max_color);
303+
float spatial_sigma_luma = dot(sigma_color, luminance_weights);
304+
float spatial_var_3x3 = spatial_sigma_luma * spatial_sigma_luma;
305+
298306
// pre-ema firefly soft clamp, lin 2022 §6.4 / production svgf trick
299307
// if the current sample's luma is way above the history band, soft-rescale it down before
300308
// it poisons the moment update, otherwise a single hot pixel can pin the variance estimate
301-
// for many frames and force the spatial filter to over-blur the neighborhood, the gate is
302-
// applied only once temporal accumulation is established (n_eff > 4) so the bootstrap
303-
// window stays unbiased
304-
if (history_ok && history_moments.z > 4.0f)
309+
// for many frames and force the spatial filter to over-blur the neighborhood, the gate
310+
// fires as soon as we have a temporal partner so disocclusion fireflies do not boil for
311+
// 4 frames before the clamp kicks in, the band widens via spatial sigma when history is
312+
// young so the clamp does not over-bias on freshly accumulating pixels
313+
if (history_ok)
305314
{
306315
float history_sigma = sqrt(max(history_moments.y - history_moments.x * history_moments.x, 0.0f));
307-
float clamp_high = history_moments.x + 8.0f * max(history_sigma, 0.05f);
316+
float band_sigma = max(history_sigma, spatial_sigma_luma);
317+
float band_widen = lerp(16.0f, 6.0f, saturate(history_moments.z / 4.0f));
318+
float clamp_high = history_moments.x + band_widen * max(band_sigma, 0.05f);
308319
if (current_luma > clamp_high && current_luma > 1e-3f)
309320
{
310321
float scale = clamp_high / current_luma;
@@ -335,12 +346,6 @@ void main_cs(uint3 dispatch_id : SV_DispatchThreadID)
335346
variance_estimate = max(temporal_var, spatial_var * boost);
336347
}
337348

338-
// small 3x3 mean+variance pre blur (schied 2017 §4.2) so isolated bright fireflies do not
339-
// pin the variance estimate to a single pixel, this stabilizes the spatial filter weights
340-
float3 mean_color, sigma_color, min_color, max_color;
341-
compute_local_statistics(pixel, resolution, mean_color, sigma_color, min_color, max_color);
342-
float spatial_sigma_luma = dot(sigma_color, luminance_weights);
343-
float spatial_var_3x3 = spatial_sigma_luma * spatial_sigma_luma;
344349
variance_estimate = max(variance_estimate, spatial_var_3x3 * 0.25f);
345350

346351
// variance gated history clamp keeps chromatic stability even when the temporal accumulator

data/shaders/restir_pt_temporal.hlsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,9 @@ void main_cs(uint3 dispatch_id : SV_DispatchThreadID)
302302
// lin 2022 §6.4 sample validation: every N frames a fixed subset of pixels re-traces the
303303
// chosen sample's primary->rc visibility ray, if rc is no longer reachable from the current
304304
// primary (light moved, geometry changed, occluder appeared) the reservoir is reset so we
305-
// do not drag a stale path across many frames, the period is in cb_frame.restir_pt_validation_period
306-
// and a value of 0 disables the pass, the pixel hash cycles deterministically with frame
307-
// index so the cost is amortized to ~1/N pixels per frame
305+
// do not drag a stale path across many frames, the period comes from get_restir_validation_period
306+
// (hardcoded to 8 frames) and the pixel hash cycles deterministically with frame index so
307+
// the cost is amortized to ~1/N pixels per frame
308308
uint validation_period = get_restir_validation_period();
309309
if (validation_period > 0u && combined.M > 0.0f && combined.W > 0.0f)
310310
{

0 commit comments

Comments
 (0)