Page MenuHome

EEVEE fix: Normal mapping making specular artifact
AbandonedPublic

Authored by Mikhail Matrosov (ktdfly) on Dec 18 2020, 3:38 PM.

Details

Summary

Problem

Normal mapping in Eevee creates artifacts both in SSR and cubemap reflections. This is because the reflection vector is below the polygon T78501: EEVEE: Normal mapping making specular artifact

Proposed solution

For cubemaps: flip the reflection vector to above the surface if the ray came from behind the surface. Basically, such a ray propagates without changes. Also I fixed NH-product for BSDF to account for the new reflection value.

For SSR: likewise, flip the reflection vector to above the microsurface, then flip it to be above the actual polygonal geometry to avoid self sampling.

Eevee old, Eevee new, Cycles


Alternative solutions

An alternative would be not to reflect, but to clamp the reflection vector to the surface. It distorts PDF much more then the proposed solution.

Limitations

The situation itself is not physically correct and only comes from a possibility of ray coming from below the surface, so any reasonable solution will be more or less fine.

Diff Detail

Repository
rB Blender

Event Timeline

Mikhail Matrosov (ktdfly) requested review of this revision.Dec 18 2020, 3:38 PM
Mikhail Matrosov (ktdfly) created this revision.
Clément Foucault (fclem) requested changes to this revision.Jan 4 2021, 12:04 PM

The better way would be to do something like cycles does in ensure_valid_reflection(). I would do this in the main pass to avoid computing the geometric normal in the post process pass (and all the issues it brings).

As to where to inject this fix, I think it should be done on all reflections. But maybe do that only before shading using cubemaps (like you did) and in closure_load_ssr_data.

Unfortunately, avoiding the cost of doing ensure_valid_reflection twice means to output the corrected normal from the closure function, but that's quite a lot of change. This might be done in a separate commit.

This revision now requires changes to proceed.Jan 4 2021, 12:04 PM

Note: It is probably better to implement a fix based on D10084: Faster ensure_valid_reflection().

Updated diff to be compatible with the current master

After testing this and experimenting with the code of D10084 I came to the conclusion that it would be preferable to use ensure_valid_reflection.

Using this diff produces too much weird reflections with probes (using -V as reflection vector is quite poor in this regard).

Using D10084 makes bump loose too much detail.

Cycles's ensure_valid_reflectionD10084 's ensure_valid_reflection

There is still self intersection remaining but I think this is a bug in the ray tracing routine which do need to be rewritten.

Also using ensure_valid_reflection to get the correct normal fixes area lighting issues & BSDF evaluation (original issue). Also this makes the testing of correct SSR ray much easier.

So I'll commit P2008 and close the original report.

source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
6–10

This is not going to work for all cases. What if -V is also below geometric normal?

source/blender/draw/engines/eevee/shaders/closure_eval_glossy_lib.glsl
44 ↗(On Diff #34618)

This is not ok to do. Here you assume View vector angle is the same as the sampling_dir angle. But sampling_dir is modified by roughness. Sampling the LTC mat LUT using this is going to produce incorrect results.