Search Unity

Unity Doesn't Pass The Furnace Test

Discussion in 'Shaders' started by Deleted User, Mar 4, 2021.

  1. Deleted User

    Deleted User

    Guest

    The way unity renders its materials always felt off to me as everything had something like a glow around it, like it was brighter at the edges than it should be. Now, after researching this I know why: the PBR materials don't adhere to conservation of energy. Doing a simple furnace test shows this:
    upload_2021-3-5_1-29-27.png

    As you can see, in a solid grey background, the edges of the material are brighter than they should be as if it created energy out of thin air! The correct result should have been a solid grey sphere indistinguishable from the background. After fiddling around with light settings and looking into the builtin shader code, the problem lies with unity forgetting to multiply the indirect diffuse with the fresnel term.

    So, the problem I'm having is that I cannot for the life of me find in which built-in shader file unity is applying the indirect diffuse term. It's not in Internal-DeferredShading nor in Internal-DiffuseReflections, and those are the only two built-in shaders you can replace in the Preferences/Graphics window that is related to this. Please help, this issue is seriously bugging me.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    If you're not using the deferred rendering path, then no, neither of those two shaders are being used. You'd want to replace the Standard shader that's being used by the material applied to the object. Or switch to the deferred rendering path so you can override those files.

    The main issue is real time engines all use approximations for their fresnel component, plus multiple forward scattering still isn't super well researched in the real time rendering world. Unity's new state of the art HDRP doesn't pass the furnace test. Unreal Engine 4 doesn't pass the furnace test (though is better than Unity). The only real time renderer I know of that passes the furnace test is Filament.
     
    nan_nz and God-at-play like this.
  3. Deleted User

    Deleted User

    Guest

    Thanks for the snap reply.

    I am using deferred rendering path and have overidden the files. However, those two files have nothing to do with the environment lighting being applied. Internal-DeferredShading seemed only concerned with direct lighting and Internal-DeferredReflections with only specular reflections. I can set both to return 0 and the envirnoment lighting is still there. I think maybe using command buffers to edit the emissive buffer where the environment lighting is placed would be a solution.

    Thanks again.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    That bright edge is a specular reflection...
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Did some quick tests and I'm actually a little surprised by how close Unity is to actually passing the furnace test.

    At 0% metallic, 0% smoothness, it's really close.

    At 100% metallic, 100% smoothness, it's perfect, but that's not hard since it's just reflecting a cubemap of the box at that point. If that was wrong I'd be a little scared.

    At 0% metallic, 100% smoothness, it's too bright like you're seeing. Unity uses Disney Diffuse for their diffuse model, which is known to not be energy conserving. EA did a talk on that where they presented a minor modification to the Disney Diffuse model to try to make it closer to energy conserving. See page 10 here:
    https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
    You'd need to modify the DisneyDiffuse function deep in the UnityStandardBRDF.cginc file to make that better, as then the combination of the specular and diffuse are closer to adding up to 1.0. It still won't be 100% perfect though.

    100% metallic, 0% smoothness, this is too dark. This is the multiple scattering issue I mentioned above. A lot of high end offline path tracers didn't get this right until fairly recently, so it's not surprising that many real time renderers aren't yet either. The fix there is a bit harder, as again it's a relatively recent thing that's been getting attention. Filament fixed it by prebaking the expensive calculations required into a look up texture. Unreal does the same, though AFAIK they haven't updated their LUT to include multiple scattering yet.
    https://google.github.io/filament/Filament.md.html
    Unity's doesn't use look up tables, so they have to use approximations, and thus far I haven't seen any that handle multiple scattering on rough metallic surfaces well.
     
    God-at-play likes this.