Skip to content

Fix division-by-zero in null-scattering PDF computation for participating media#535

Open
DeepReinforce wants to merge 1 commit intommp:masterfrom
deepreinforce-ai:fix-division-by-zero-bug
Open

Fix division-by-zero in null-scattering PDF computation for participating media#535
DeepReinforce wants to merge 1 commit intommp:masterfrom
deepreinforce-ai:fix-division-by-zero-bug

Conversation

@DeepReinforce
Copy link
Copy Markdown

Summary

Fix division-by-zero bugs in the null-scattering path of participating media sampling. When the null-scattering PDF (T_maj[0] * sigma_n[0] or T_maj[0] * sigma_maj[0]) evaluates to zero, the original code performs division before checking the zero condition, producing NaN/Inf values that propagate through beta, r_u, r_l, and T_ray, corrupting the entire path contribution and potentially causing rendering artifacts.

This PR moves the zero-check before the division and immediately returns false to terminate the path, avoiding any undefined arithmetic.

Changes

CPU integrators (src/pbrt/cpu/integrators.cpp)

  • VolPathIntegrator::Li (null-scattering callback): Check pdf == 0 before dividing beta, r_u, r_l by pdf. Set beta to zero and return false early.
  • RandomWalk (null-scattering callback): Same fix — check pdf == 0 first, set beta to zero and return false instead of conditionally skipping only the beta update.

Wavefront media sampling (src/pbrt/wavefront/media.cpp)

  • WavefrontPathIntegrator::SampleMediumInteraction (null-scattering callback): Check pr == 0 before dividing beta, r_u, r_l by pr. Set beta to zero and return false early.

Wavefront transmittance (src/pbrt/wavefront/intersect.h)

  • TraceTransmittance (ratio-tracking null-scattering): Add pr == 0 guard before dividing T_ray, r_l, r_u by pr. Set T_ray to zero and return false early.

Motivation

In scenes with participating media, it is possible for the null-scattering probability T_maj * sigma_n (or T_maj * sigma_maj) to evaluate to exactly zero. The original code either:

  1. Divides first, then checks for zero (CPU path, wavefront media), or
  2. Has no zero-check at all (wavefront transmittance).

Both cases lead to NaN/Inf propagation, which can cause visible fireflies, black pixels, or assertion failures depending on the scene configuration and medium parameters.

When the null-scattering PDF evaluates to zero during medium sampling,
the original code performs division before (or without) checking for
zero, producing NaN/Inf that corrupts path throughput and MIS weights.
Move the zero-check before the division in all affected code paths
(VolPathIntegrator::Li, RandomWalk, WavefrontPathIntegrator::
SampleMediumInteraction, and TraceTransmittance) and return false
early to terminate the path cleanly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant