Search Unity

Unity 5 Surface Shader - Passes

Discussion in 'Shaders' started by MaT227, Apr 8, 2015.

  1. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    Hello everyone,

    I am would like some precisions about surface shaders in Unity 5.

    It seems that it is the same system as the previous Unity version with a surface function, a lighting function and a vertex function, of course some are optional.

    But it seems that the classic shaders are made using several passes : forward, forward add, deferred, meta and shadow. Can someone give precisions about those passes ?

    If I want to write a custom meta or shadow pass should I need to write a full vertex and fragment shader or can I use them with a surface shader ?

    Thanks a lot.
     
  2. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    Any idea ?
     
  3. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    You would need to write a vertex & pixel shader, because that's actually the whole purpose of the surface shader : it will generate base pass, lighting pass, shadow caster pass etc... for you.

    So you can't use a Surface Shader for just one of those pass, as it's a "meta" shader used to generate those in turn.

    In an broad sense/approximation, Unity Standard Shader is the hand written version of what a surface shader generate for you

    But if you know shader code well enough, you can bypass surface shader and rewrite all those pass yourself indeed, allowing to do some "ultra custom" lighting process. There is a lot of dependency though, so would have to be careful to not miss a thing! (best way is probably starting from a Standard Shader and replacing function one by one...)
     
  4. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    @UnityGuillaume Thank you for your answer. The aim was to avoid all the dependency handling as there are a lot of them as you said. I asked this question because I already looked at the Standard shader and I was a bit "afraid" :p
    Anyway, I think that I don't have much choices. :D
     
  5. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    @UnityGuillaume I think that the only annoying thing is that in the new surface shader system with UnityGI and UnityLight, you don't have access to the atten component like in the previous version of the lighting function as it is part of the light.color.
    Now you are not able anymore to really compose your own lighting in a surface shader unless if you write a full vertex and fragment shader which is a bit long...
     
  6. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    @UnityGuillaume Any specific reason why you don't expose the atten value ?
     
  7. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    I may be mistaken, I'm not fully accustomed to new rendering pipeline yet, but I think the function :

    "Lighting<CustomLightingName>_GI" is "called" to fill the data (indirect & direct lighting) And it's input UnityGIInput have an atten value.

    Usually that function call UnityGlobalIllumination, who initialize the gi varfor the "Unity lighting". But you don't have to, you can fill the gi data as you what.

    So if your Lighting Model is called AwesomeLighting, you can define a function :


    Code (CSharp):
    1. inline void LightingAwesomeLighting_GI (
    2.     SurfaceOutput s, //replace by your input struct if you have one
    3.     UnityGIInput data,
    4.     inout UnityGI gi)
    5. {
    6.     gi = UnityGlobalIllumination (data, s.Occlusion, s.Smoothness, s.Normal); // this is default lighting
    7.  
    8.     //either override some data
    9.    gi.light.color = float3(0,1,0);
    10.  
    11.     ///or never call UnityGlobalIllumination  and do whatever your like. Check UnityGlobalIllumination function to see what unity does and copy past it to modify it at your will
    12. }
     
  8. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    @UnityGuillaume Thank you so much for your answer. I've already looked very quicky at the UnityGlobalIllumination function but I thought that it was only realted to realtime/static GI.
    But it appears that it is related as you said to indirect and direct lighting. So I might be able to do what I want in this function.

    Thank you again. :D
     
  9. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    @UnityGuillaume Sorry to launch the discussion again, but after a small test, the solution you gave me is very good but it has a small disadvantage but maybe I missed something.
    If I override the gi.light.color, it only affects the directionnal light as the point light color is always added.

    Is it possible to access data for point lights ?

    Edit: After a small test, it appear that the atten value exposed in the GlobalIllumination function is not related to point light attenuation... Any idea how can I access those values (I smell the full vertex and fragment shader...) ? :(
     
    Last edited: Apr 15, 2015
  10. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Damn tested more in depth and you're right : GI is only for...well the GI =D So it cover only the "main light" of the scene.

    If you open the generated code for a shader in Unity (button "Show Generated code" when a shader is selected), you have what unity have generated from your surface shader (and can indeed see that it generate all the pass you saw in the Standard Shader).

    And you will see that, for the additive forward pass (so for all other light than the main light) :

    Code (CSharp):
    1.  UnityGI gi;
    2.   UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
    3.   gi.indirect.diffuse = 0;
    4.   gi.indirect.specular = 0;
    5.   #if !defined(LIGHTMAP_ON)
    6.       gi.light.color = _LightColor0.rgb;
    7.       gi.light.dir = lightDir;
    8.       gi.light.ndotl = LambertTerm (o.Normal, gi.light.dir);
    9.   #endif
    10. gi.light.color *= atten;// HERE
    11. //call the lighting function defined in your SurfaceShader
    12.   c += LightingFunction (o, worldViewDir, gi);
    it multiply by atten before passing the gi data = /


    For deferred path...well light are rendered after that and composited, so you can't access their informations...(but that's a deferred rendering limitation, you would need to write custom light rendering shaders, vert+pixels, and not possible in Unity so far I think...Apart using CommandBuffer to render into the light buffer directly with custom light types)


    I don't know why atten is not a parameter anymore, there may be a deeper reason regarding on how Unity 5 rendering work, but no idea sorry : / (Maybe @Aras or @robert know)
     
  11. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    Thank you again for your answer @UnityGuillaume, I think that I have no choice if I want to access the atten value for other lights, I'll have to build a vertex & fragment shader... :(
    But maybe @Aras or @robert have a solution :D

    If you look at the vertex&fragment shader functions you can access the atten value.
    Code (CSharp):
    1. UnityLight MainLight (half3 normalWorld)
    2. UnityLight AdditiveLight (half3 normalWorld, half3 lightDir, half atten)
     
  12. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
  13. MaT227

    MaT227

    Joined:
    Jul 3, 2012
    Posts:
    628
    Is there anybody who know if there is a possibility to access the atten value ? Or maybe override the MainLight and AdditiveLight function in a surface shader ?