Search Unity

Standard Shader custom ambient

Discussion in 'Shaders' started by Andrzej-Skibinski, Oct 28, 2015.

  1. Andrzej-Skibinski

    Andrzej-Skibinski

    Joined:
    Apr 16, 2014
    Posts:
    13
    Hey all

    We're working on a projects that combines exterior and interior model. We use dynamic lighting (from UniStorm) with real-time interior lights. In Unity4 we had a special shader written for all interior materials, that used custom lighting model (basicly #pragma Surface surf CustomAmbient noambient).
    Problem is we moved to Unity5 and now use Standard shaders (with reflection probes, nice looks that it brings, etc), but we cannot re-create the old custom ambient for those shaders. This means all interior materials take on animated ambient color from the whole scene, and it looks rather poor.

    Anyone tried to replace ambient color in Standard shader in Unity5?

    Thanks in advance
    Andrzej Skibiński
    Lead Graphic Designer
    Sito Poland
     
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    We're working with architectural interiors and exteriors and I'm in the process of implementing our own set of shaders to replace the Unity 5 Standard shaders to better fit our needs. In this case it's of course very easy to use a different ambient color by just setting it in a global vector and using it in your own shader. I'm actually trying to use the ambient from Unity itself in my shaders, which seems to lead to random intensity changes. (I'm using unity_AmbientSky as ambient.)

    By using the right define, you might be able to replace the ambient from the Unity 5 Standard shader, but it is tricky. It's a fairly complex combination of includes. The Standard shader leans mostly on UnityStandardCore.cginc, which takes in the GI using UNITY_BRDF_GI in the forwardBase and deferred passes. This is located and defined in UnityPBSLighting.cginc.

    So you could just redefine that between the includes of UnityPBSLighting.cginc and UnityStandardCore.cginc and add your own. (Easy, right ;-) )

    In a copy of the Standard shader in the forwardBase and deferred passes right before:
    Code (csharp):
    1. #include "UnityStandardCore.cginc"
    You should add:
    Code (csharp):
    1.  
    2. #include "UnityPBSLighting.cginc"
    3. #define UNITY_BRDF_GI MyAmbient
    4.  
    5. inline half3 MyAmbient (half3 baseColor, half3 specColor, half oneMinusReflectivity, half oneMinusRoughness, half3 normal, half3 viewDir, half occlusion, UnityGI gi) {
    6.    return half3(0.5, 0.0, 0.0);
    7. }
    8.  
    So you import UnityPBSLighting.cginc first, which will define UNITY_BRDF_GI. Then you overwrite this define and supply your own inline function.
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    I managed this by setting the noambient keyword and adding my own ambient color * albedo into the emission.
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    In the surface shader format that still works fine, but if you want to switch to the new format that the Unity 5 Standard shader has, it gets a bit more tricky.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    I did this with a custom standard surface shader in 5.2 rather than overriding the base definition. The specific case I had was very long dynamic objects which extended across areas with extreme ambient color changes. I manually sample to get the SH from multiple points and pass them to the shader to linearly blend between across the length of the object.