Search Unity

Emissive Gi On Custom Shader Not Working

Discussion in 'General Graphics' started by GaelBourhis, Apr 15, 2019.

  1. GaelBourhis

    GaelBourhis

    Joined:
    Aug 25, 2013
    Posts:
    4
    Hi there,

    After some research I managed to make emissive Gi with emission mask work in realtime with Unity Standard Material :

    Screenshot_3660.png

    However, with the same settings and a custom surface shader, the GI does'nt take the emissive map into account and only update color uniformly.

    Screenshot_3661.png
    Screenshot_3662.png
    Screenshot_3663.png
    I'm using
    Code (CSharp):
    1.  meshRenderer.UpdateGIMaterials();
    to make sure the GI apply (and it works), but how to make my custom shader take the emissive map into account?

    Here's my custom shader :
    Code (CSharp):
    1. Shader "Custom/FalseSunEmissive"
    2. {
    3.     Properties
    4.     {
    5.         _EmissionColor ("Emissive Color", Color) = (1,1,1,1)
    6.         _EmissionMap ("Emission map", 2D) = "white" {}
    7.     }
    8.     SubShader
    9.     {
    10.         Tags { "RenderType"="Opaque" }
    11.         LOD 200
    12.  
    13.         CGPROGRAM
    14.         #pragma surface surf Standard fullforwardshadows
    15.         #pragma target 3.0
    16.  
    17.         struct Input
    18.         {
    19.             float2 uv_EmissionMap;
    20.         };
    21.  
    22.         sampler2D _EmissionMap;
    23.         float4 _EmissionColor;
    24.  
    25.         void surf (Input IN, inout SurfaceOutputStandard o)
    26.         {
    27.             fixed4 c = tex2D (_EmissionMap, IN.uv_EmissionMap);
    28.             o.Emission = c * _EmissionColor;
    29.  
    30.             o.Albedo = 1.0;
    31.             o.Alpha = c.a;
    32.         }
    33.         ENDCG
    34.     }
    35.     FallBack off
    36. }
    Thanks in advance for any hints regarding this problem,

    Gaël
     
  2. GaelBourhis

    GaelBourhis

    Joined:
    Aug 25, 2013
    Posts:
    4
    After more research, it seems that adding a meta pass to the shader would allow us to customize what info is passed to the lightmapper :

    https://docs.unity3d.com/530/Documentation/Manual/MetaPass.html

    I found this example, but couldn't make it work : https://forum.unity.com/threads/meta-pass-and-precomputed-realtime-gi-question.346000/

    Here's my updated shader code :
    Code (CSharp):
    1. Shader "Custom/FalseSunEmissive"
    2. {
    3.     Properties
    4.     {
    5.         _EmissionColor ("Emissive Color", Color) = (1,1,1,1)
    6.         _EmissionMap ("Emission map", 2D) = "white" {}
    7.     }
    8.  
    9.     SubShader
    10.     {
    11.         Pass
    12.         {
    13.             Name "META"
    14.             Tags {"LightMode" = "Meta"}
    15.             Cull Off
    16.             CGPROGRAM
    17.  
    18.             #include"UnityStandardMeta.cginc"
    19.  
    20.             sampler2D _GIAlbedoTex;
    21.             fixed4 _GIAlbedoColor;
    22.  
    23.             float4 frag_meta2(v2f_meta i) : SV_Target
    24.             {
    25.                 FragmentCommonData data = UNITY_SETUP_BRDF_INPUT(i.uv);
    26.                 UnityMetaInput o;
    27.                 UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
    28.                 fixed4 c = tex2D(_GIAlbedoTex, i.uv);
    29.                 o.Albedo = fixed3(c.rgb * _GIAlbedoColor.rgb);
    30.  
    31.                 //I put an arbitary value to check the shader but nothing changes :
    32.                 o.Emission = 10.0;//tex2D(_EmissionMap, i.uv.xy).rgb * _EmissionColor;
    33.  
    34.                 return UnityMetaFragment(o);
    35.             }
    36.  
    37.             #pragma vertex vert_meta
    38.             #pragma fragment frag_meta2
    39.             #pragma shader_feature _EMISSION
    40.             #pragma shader_feature _METALLICGLOSSMAP
    41.             #pragma shader_feature ___ _DETAIL_MULX2
    42.             ENDCG
    43.         }
    44.  
    45.        
    46.         Tags { "RenderType"="Opaque" }
    47.         LOD 200
    48.  
    49.         CGPROGRAM
    50.         #pragma surface surf Standard fullforwardshadows nometa
    51.         #pragma target 3.0
    52.  
    53.         sampler2D _MainTex;
    54.  
    55.         struct Input
    56.         {
    57.             float2 uv_MainTex;
    58.         };
    59.  
    60.         sampler2D _EmissionMap;
    61.         float4 _EmissionColor;
    62.  
    63.         void surf (Input IN, inout SurfaceOutputStandard o)
    64.         {
    65.             o.Emission = tex2D(_EmissionMap, IN.uv_MainTex).rgb * _EmissionColor;
    66.             o.Albedo = 1.0;
    67.         }
    68.         ENDCG
    69.     }
    70.     FallBack off
    71. }
    Whatever value I put in the o.Emission of the meta pass gets ignored...

    And here's the c# side :
    Code (CSharp):
    1. private void Start()
    2. {
    3.     MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
    4.     flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
    5.     material.globalIlluminationFlags = flags;
    6. }
    7.  
    8. void Update()
    9. {
    10.     material.SetColor("_EmissionColor", color);
    11.     material.SetTexture("_EmissionMap", emissionMap);
    12.  
    13.     meshRenderer.UpdateGIMaterials();
    14. }
     
  3. VLukianenko

    VLukianenko

    Joined:
    Mar 27, 2017
    Posts:
    30
    I made a shader using same unity manual tutorial, and it was working in the project I've made it in - baking GI as expected. However, same shader isn't working in a new project with same Unity version (2018.3) and seemingly same lighting, quality and graphics settings... I must be missing something, but I don't know what...

    EDIT:
    Alright, I seem to have figured it out. Firstly, my custom shdaer didn't define _EMISSION keyword. Without that, custom meta pass didn't write into emission map. Secondly, it wanted _Emission color property to be present, so I had to rename my variable to match what unity libraries want it to be. After that it seems to work!

    Thus, for GaelBourhis I'd try renaming _EmissionColor variable to _Emission, and as a workaround to ensure "_EMISSION" keyword is present is to swap shader of material back to standard, check "Emission" there, and then swap back to custom shader. (Then, via debug inspector view you can see that _EMISSION keyword is present. Inputing it there manually for some reason doesn't work for me...)
     
    Last edited: Feb 21, 2020
    rustinlee and CarpeFunSoftware like this.
  4. rustinlee

    rustinlee

    Joined:
    May 31, 2014
    Posts:
    20
    Making sure _EMISSION was set as a shader keyword on the material using the inspector's debug mode worked for me, thanks -- I also had to set the Lightmap Flags property to 2.