Emissive Gi On Custom Shader Not Working

Hi there,

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

4430542--404809--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.




I’m using

 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 :

Shader "Custom/FalseSunEmissive"
{
    Properties
    {
        _EmissionColor ("Emissive Color", Color) = (1,1,1,1)
        _EmissionMap ("Emission map", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows
        #pragma target 3.0

        struct Input
        {
            float2 uv_EmissionMap;
        };

        sampler2D _EmissionMap;
        float4 _EmissionColor;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            fixed4 c = tex2D (_EmissionMap, IN.uv_EmissionMap);
            o.Emission = c * _EmissionColor;

            o.Albedo = 1.0;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack off
}

Thanks in advance for any hints regarding this problem,

Gaël

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 :

I found this example, but couldn’t make it work : Meta pass and Precomputed Realtime GI Question

Here’s my updated shader code :

Shader "Custom/FalseSunEmissive"
{
    Properties
    {
        _EmissionColor ("Emissive Color", Color) = (1,1,1,1)
        _EmissionMap ("Emission map", 2D) = "white" {}
    }

    SubShader
    {
        Pass
        {
            Name "META"
            Tags {"LightMode" = "Meta"}
            Cull Off
            CGPROGRAM

            #include"UnityStandardMeta.cginc"

            sampler2D _GIAlbedoTex;
            fixed4 _GIAlbedoColor;

            float4 frag_meta2(v2f_meta i) : SV_Target
            {
                FragmentCommonData data = UNITY_SETUP_BRDF_INPUT(i.uv);
                UnityMetaInput o;
                UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
                fixed4 c = tex2D(_GIAlbedoTex, i.uv);
                o.Albedo = fixed3(c.rgb * _GIAlbedoColor.rgb);

                //I put an arbitary value to check the shader but nothing changes :
                o.Emission = 10.0;//tex2D(_EmissionMap, i.uv.xy).rgb * _EmissionColor;

                return UnityMetaFragment(o);
            }

            #pragma vertex vert_meta
            #pragma fragment frag_meta2
            #pragma shader_feature _EMISSION
            #pragma shader_feature _METALLICGLOSSMAP
            #pragma shader_feature ___ _DETAIL_MULX2
            ENDCG
        }

       
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows nometa
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        sampler2D _EmissionMap;
        float4 _EmissionColor;

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            o.Emission = tex2D(_EmissionMap, IN.uv_MainTex).rgb * _EmissionColor;
            o.Albedo = 1.0;
        }
        ENDCG
    }
    FallBack off
}

Whatever value I put in the o.Emission of the meta pass gets ignored…

And here’s the c# side :

private void Start()
{
    MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
    flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
    material.globalIlluminationFlags = flags;
}

void Update()
{
    material.SetColor("_EmissionColor", color);
    material.SetTexture("_EmissionMap", emissionMap);

    meshRenderer.UpdateGIMaterials();
}

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…)

2 Likes

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.