mmp / pbrt-v3

Source code for pbrt, the renderer described in the third edition of "Physically Based Rendering: From Theory To Implementation", by Matt Pharr, Wenzel Jakob, and Greg Humphreys.
http://pbrt.org
BSD 2-Clause "Simplified" License
4.92k stars 1.2k forks source link

volpath cannot reproduce single scattering light path accurately. #69

Closed syoyo closed 8 years ago

syoyo commented 8 years ago

In current volpath loop logic, it cannot reproduce single scattering light path accurately(only one scattering event in the medium).

Please see 7.1 Analytical Single Scattering Solution in "Evaluation of Visual Parameters in Volumetric Path Tracing" for the scene setup: http://www.diva-portal.se/smash/get/diva2:796154/FULLTEXT01.pdf (The scene is one cube([-1, 1]^3) lit by parallel light(0, -1, 0) and seeing it from Z direction)

result-compare (From left to right: PBRT-v3, Mitsuba 0.5 and the analytic solution)

Mitsuba and analytic single scattering solution gives correct result, but PBRT-v3 gives a bit brighter result. (Note that I've changed to use pow(x, 1.0f/2.2f) in PBRT-v3's gamma correction for precise image comparison in LDR image format)

The situation of PBRT's volpath looks like

Thus, theres 2 scattering events in the medium at max even maxdepth is set to 1. This would be the reason why PBRT-v3 result become brighter and cannot produce single scattering light path accurately.

One quick idea to solve the issue is to remove bounce-- line https://github.com/mmp/pbrt-v3/blob/master/src/integrators/volpath.cpp#L99 ,but this may affect another light paths so I'm not sure this is OK or not.

Attached zip is the reproducing scenes in PBRT and Mitsuba, and also analytic solution code in C++. volpath-singlescatter-issue.zip

mmp commented 8 years ago

Nice find! Now fixed.

I'm not closing this out yet, since I did a test with the BDPT integrator (after switching to a narrow perspective view); that gives a result that is ~16% darker than the (now fixed) VolPathIntegrator. So there is an issue to fix there as well. Will start digging into that later today.

mmp commented 8 years ago

An update on BDPT...

The attached file pbrt-singlescatter.pbrt.txt is a repro case for BDPT versus the VolPath integrator; with top of tree, BDPT is ~16% darker (BDPT average radiance value 0.014454 from exravg vs 0.0167834 from VolPath).

I've done some debugging and confirmed that the logic for limiting the path length in BDPT is correct--in other words, for this scene, it only considers paths with (t,s) equal to (1,2) splat path from light, (2,1), one bounce from camera and then direct lighting, and (3,0) path from camera that intersects light source directly. The (3,0) path isn't possible, since it's a distant light source, so only the first two contribute.

If I modify the MISWeight() function to always return a weight of 1.f / (s + t - 1), corresponding to equal weighting for all paths, then BDPT computes an image that matches the VolPathIntegrator. Thus, I believe that the bug is in the MISWeight() method. One theory is that it isn't correctly accounting for the fact that the (3,0) path will never carry any radiance for this scene since the light source is described by a delta distribution.

syoyo commented 8 years ago

Cool! > Fix.

I believe that the bug is in the MISWeight() method.

MIS calculation in nanogi BDPT https://github.com/lighttransport/nanogi/blob/master/include/nanogi/bdpt.hpp may help. @hi2p-perim wrote a robust BDPT&MIS implementation which correctly handles singular component. (https://github.com/hi2p-perim/lightmetrica-v2/blob/master/src/liblightmetrica/renderer/renderer_bdpt.cpp is also worth looking into. Its @hi2p-perim 's newer&robust BDPT implementation)

syoyo commented 8 years ago

Cool! Thanks!