Closed gamer9xxx closed 4 months ago
Hey,
In your code, for NEE, you are evaluating the BSDF but are not taking into account the light pdf and instead using the BSDF pdf (without MIS) which isn't quite right.
You can have a look at the light sampling and BSDF sampling code from the simple path tracer example from PBRTv4:
Light Sampling: https://github.com/mmp/pbrt-v4/blob/39e01e61f8de07b99859df04b271a02a53d9aeb2/src/pbrt/cpu/integrators.cpp#L441
BSDF Sampling: https://github.com/mmp/pbrt-v4/blob/39e01e61f8de07b99859df04b271a02a53d9aeb2/src/pbrt/cpu/integrators.cpp#L453
Documentation: https://www.pbr-book.org/4ed/Light_Transport_I_Surface_Reflection/A_Simple_Path_Tracer
Here are some examples from this project (16 spp):
Only light sampling (essentially similar to your unit test):
Only BSDF sampling:
MIS:
Another example with light sampling only and a directional light (zero area and pdf = 1). The sphere on the top left is a smooth white metal with 0.001 roughness. Here only the highlight is visible and the remaining surface has no contribution which is the expected output from the BSDF evaluation for the light:
Hi, I see, thanks for the explanation, you are correct!
I couldn't get my head around the fact that BSDF.eval / BSDF.pdf returns full contribution regardless of the direction, but that's still valid because BSDF.sample never returns such direction and in case we get samples from other domain such as NEE.sample, we must apply proper MIS to get the correct contribution, so it actually all works as expected.
Thanks for the examples, esp. the last example with pdf = 1 was an interesting exercise! And big thanks for this great library!
For the perfectly smooth materials,
DisneyEval
returns a full light contribution, even for angles that are far from the perfect reflection.DisneySample
never generates such samples, so usually this is not a problem, but once the samples are generated any other way (e.g. NEE), this results in a wrong contribution. To better demonstrate what I mean, I wrote a simple unit test, where thedebug_color.b
should be always 0, yet it evaluates to the same full light contribution as a perfect reflection.