Transparency swallows volume scatter bounce
Closed, ResolvedPublic

Description

When a transparent surface penetrates a scattering volume, scatter rays can get stopped at the transparent surface instead of traversing it, regardless of the number of transparent bounces set in the render options.

See the attached file. The 100% transparent plane effectively cuts off volume scattering in the cube. The expected result is that a 100% transparent plane should have no visible influence on volume scattering.

Verified in Blender 2.79, master as of commit 7b29e917118ffdeb39de5c942dd652d40914dbc3 on macOS 10.13 and Windows 10.

I have a potential fix for this coming.

Brecht Van Lommel (brecht) triaged this task as Confirmed priority.Mon, Jan 29, 5:12 PM

This commit is affecting many regression tests, and investigating it more closely I don't think it's correct, so I'll revert it for now to keep the tests passing. After this change it's no longer possible to get just direct volume lighting, it will always do at least 1 indirect volume bounce as well.

The same problem exists for diffuse or glossy bounces, the problem really is with volume emission (and mesh emission) for which we don't do any direct light sampling. Direct light shadow rays will go through the transparent surfaces to reach the emission, but indirect light rays will not.

I'm not sure yet what the right solution is.

I see what you mean.

Just to make sure we're on the same page: Intended behaviour is that when max_volume_bounce is set to 0, we trace one scatter event inside the volume from which we gather emission inside the volume, but not any direct or indirect light? So volume emission will illuminate volume scattering, but not other surfaces (since we don't have next event estimation for volume emission)? And once we get next event estimation for volumes emission, it should then also illuminate surface shaders too?

The intended behavior is that when max_volume_bounce is 0, we gather direct lighting and emission from surfaces and volumes. The latter is also considered to be "direct lighting", so that a mesh light behaves the same as any other light. Using next event estimation or not should not make any difference in the converged render result, but it is different in this case due to an inconsistency with the handling of transparent surfaces.

If you run the regression tests you'll see the difference, but here's an example where you can see how surfaces and volume handle indirect light differently after the fix:

Before FixAfter Fix
Max surface and volume bounces 0
Max surface and volume bounces 1

Currently I'm thinking the fix could be something like this:

  • Move the max bounces test into path_state_next(), setting a state->flag to indicate the path is to be terminated.
  • If that flag is set shader evaluation at the next bounce will remove all closures except for emission and transparency (or not add them in the first place: D2938).
  • The path can then continue for transparency but not other BSDF/BSSRDF types.

Maybe there's a simpler way to do it, I'm not sure.

That sounds like a good approach. I suspect that in general, transparent intersections can lead to incorrect path termination. Note how for example how an environment light with diffuse bounces = 0 will not provide direct illumination through transparency. Volume emission currently also provides direct light to surfaces inside the volume's bounds, but not to surfaces outside of the volume's bounds.

This shouldn't have been closed yet.