Search Unity

#### Standard Pipeline: Reducing specular halo in UnityStandardBRDF.cginc ####

Discussion in 'Shaders' started by Quatum1000, Jan 7, 2021.

  1. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Hi everyone,

    I like to reduce the specular halo in the standard render pipeline. I tried to search in the CGIncludes\UnityStandardBRDF.cginc but was not found any value in

    ~ SmithJointGGXVisibilityTerm (nl, nv, roughness);
    ~ GGXTerm (nh, roughness);


    to reduce the smooth halo. I tried also to change the previous values NL NV, but no chance.


    Here is an example what I like to archive.
    Currently:
    1.jpg
    2.jpg

    I think the specular light would be calculated in real-time based on roughness and is not ploted through any cube or texture. Does anyone know where this specular light is calculated ?

    Thanks a lot...
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    That "specular halo" is the GGX specular lobe shape. If you don't want it, and you're manually modifying the built in shader files already, find the
    #define UNITY_BRDF_GGX 1
    in UnityStandardConfig.cginc and set that to 0. Or if you have a custom shader, add this to your shader:
    Code (csharp):
    1. #ifdef UNITY_BRDF_GGX
    2. #undef UNITY_BRDF_GGX
    3. #endif
    4. #define UNITY_BRDF_GGX 0
    That should make that shader use the original blinn-phong lobe, which is much sharper.
     
    Quatum1000 likes this.
  3. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Thanks a lot.

    I currently use the ggxTern and ndfBlin like this: (and some other small changes)

    Code (CSharp):
    1. #if UNITY_BRDF_GGX
    2.     // GGX with roughtness to 0 would mean no specular at all, using max(roughness, 0.002) here to match HDrenderloop roughtness remapping.
    3.     roughness = max(roughness, 0.002);
    4.     float V = SmithJointGGXVisibilityTerm(nl, nv, roughness);
    5.     float D;
    6.     if(smoothness > 0.95) {
    7.         D = NDFBlinnPhongNormalizedTerm(nh, PerceptualRoughnessToSpecPower(perceptualRoughness)) * 0.01;
    8.     } else {
    9.         D = GGXTerm(nh, roughness);
    10.     }
    11. #else
    12. ....
    13.  
    Gives me in my opinion better more overall shiny results. (left side shpere reflections)
    0,.jpg

    + Is there any possibility to optimize the content of the if statement
    + or the GGXTerm.

    I thought about to lerping the result of D:
    Code (CSharp):
    1.    float D = GGXTerm(nh, roughness);
    2.     if(smoothness > 0.95) {
    3.       D = lerp (-2,1,D);
    4.      }
    But the result does not looks well.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Not really, no. Those two functions are quite different, so most likely you're always going to be calculating both going that route.
     
    Quatum1000 likes this.