mmp / pbrt-v4

Source code to pbrt, the ray tracer described in the forthcoming 4th edition of the "Physically Based Rendering: From Theory to Implementation" book.
https://pbrt.org
Apache License 2.0
2.83k stars 440 forks source link

NaNs being produced in SampleMediumInteraction #172

Closed shadeops closed 3 years ago

shadeops commented 3 years ago

Summary

Howdy

I've noticed some NaNs being produced in the WavefrontPathIntegrator::SampleMediumInteraction. It is fairly reproducible (with enough samples) in the scene described below.

[ tid 3457192 @     0.000s util/image.h:424 ] ERROR NaN at pixel 201,99 comp 0
[ tid 3457192 @     0.000s util/image.h:424 ] ERROR NaN at pixel 201,99 comp 1
[ tid 3457192 @     0.000s util/image.h:424 ] ERROR NaN at pixel 201,99 comp 2

Amateur Analysis

Tracking a sample that led to a NaN it seemed to originate from -

https://github.com/mmp/pbrt-v4/blob/130757d3c89b0b953902c5c9fd3db30091d9184f/src/pbrt/wavefront/media.cpp#L95-L97

uniPathPDF.Average() is 0.0 due to sigma_n being 0 in a null scattering event from https://github.com/mmp/pbrt-v4/blob/130757d3c89b0b953902c5c9fd3db30091d9184f/src/pbrt/wavefront/media.cpp#L137-L143

The events leading up to this were -

Medium event T_maj 0.694691 0.694691 0.694691 0.694691 sigma_a 0.250000 0.250000 0.250000 0.250000 sigma_s 10.000000 10.000000 10.000000 10.000000

Medium scattering probabilities: 0.024390 0.975610 0.000000 (not quite 0.0)

With a uMode very very close to 1.0

Example Scene

Film "rgb"
    "string filename" [ "NaNs.exr" ]
    "integer yresolution" [ 720 ]
    "integer xresolution" [ 1280 ]
PixelFilter "gaussian"
    "float xradius" [ 2 ]
    "float yradius" [ 2 ]
Sampler "zsobol"
    "integer pixelsamples" [ 4096 ]
Integrator "volpath"
    "integer maxdepth" [ 5 ]
Accelerator "bvh"
Transform [ 1 0 0 0 0 1 0 0 0 0 -1 0 0 0 5.450332 1  ]
Camera "perspective"
    "float screenwindow" [ -1 1 -0.5625 0.5625 ]
    "float fov" [ 45.000042 ]

WorldBegin

AttributeBegin
    Transform [ 1 0 0 0 0 0.70710677 -0.70710677 0 0 0.70710677 0.70710677 0 0 0 0 1  ]
    Scale 1 1 -1
    Scale 1 -1 1
    LightSource "distant"
        "float scale" [ 1 ]
AttributeEnd

AttributeBegin
    ConcatTransform [ 3 0 0 0 0 3 0 0 0 0 1.5 0 0 0 0 1  ]
    MakeNamedMedium "/obj/box/vol"
        "rgb sigma_s" [ 10 10 10 ]
        "point3 p1" [ 1 1 1 ]
        "point3 p0" [ -1 -1 -1 ]
        "rgb sigma_a" [ 0.25 0.25 0.25 ]
        "integer nz" [ 2 ]
        "rgb Le" [ 1 1 1 ]
        "integer ny" [ 4 ]
        "integer nx" [ 4 ]
        "float density" [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
                          1 1 1 1 1 1 ]
        "string type" [ "uniformgrid" ]

    Material "interface"
    MediumInterface "/obj/box/vol" ""
    Shape "trianglemesh"
        "point3 P" [ 1 -1 1 -1 -1 1 1 1 1 -1 1 1 -1 -1 -1 1 -1 -1 -1 1 -1 1 1 
                     -1 ]
        "integer indices" [ 0 3 1 0 2 3 4 7 5 4 6 7 6 2 7 6 3 2 5 1 4 5 0 1 5 
                            2 0 5 7 2 1 6 4 1 3 6 ]
AttributeEnd
shadeops commented 3 years ago

Changing

 if (w.depth < maxDepth && mp.Le) 
     L += T_hat * mp.Le * mp.sigma_a / 
          (sigma_maj[0] * uniPathPDF.Average()); 

to

// also check uniPathPDF
 if (w.depth < maxDepth && mp.Le && uniPathPDF) 
     L += T_hat * mp.Le * mp.sigma_a / 
          (sigma_maj[0] * uniPathPDF.Average()); 

This seems like a blunt fix, but not sure if this is appropriate.

mmp commented 3 years ago

Thanks for chasing this down! (To my shame, I had occasionally seen similar NaNs but never chased down the root cause.) I've pushed a fix that takes care of this as well as some similar sketchy cases.