Transparency Shader : Render only lit enemies.

I got involved in a project as a programmer and got task to write a custom shader. I’m not very experienced with shaders. To get straight to the heart of the matter, I need to write shader which will renders objects (enemies) transparently when they’re unlit and renders them normally when they illuminated by the light. I’ve got the desired effect recently with code provided below:

Shader “BrokenTime/EnemyVisibility” {

Properties {
_DesatVal (“Desaturation value”, Range(1, 100)) = 1
_MainTex (“Texture”, 2D) = “white” {}
_Color (“Main Color”, Color) = (1,1,1,1)
[HideInInspector] _TempColor (“Temp Color”, Color) = (1,1,1,1)
[HideInInspector] _TempAlpha (“Temp Alpha”, float) = 2
}

SubShader {
ColorMask RGB

Tags {
“RenderType” = “Transparent”
“Queue” = “Transparent”
“IgnoreProjector” = “True”
}

Lighting On Cull Off ZWrite on
Blend SrcAlpha OneMinusSrcAlpha

CGPROGRAM
#pragma surface surf SimpleLambert alpha:fade

sampler2D _MainTex;

fixed4 _Color;
fixed4 _TempColor;
fixed _TempAlpha;

half _DesatVal;

struct Input {
float2 uv_MainTex;
};

half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half4 c;
c.rgb = _TempColor * _LightColor0.rgb * (NdotL * atten * 2);
c.a = 1;
return c;
}

void surf (Input IN, inout SurfaceOutput o) {
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
_TempColor = c; // get texture default color
_TempAlpha = tex2D(_MainTex, IN.uv_MainTex).a;

}

ENDCG
}
Fallback “Diffuse”
}

However sometimes a problem arises. When enemies are unlit they occasionaly turn totally black.
I’ve attached some screens when it works fine and when error appears. I will be really, really grateful if someone leds me to the solution of this problem.



Hi,

I modify a bit your shader and ended with that to have your effect.
I made some test and didn’t had the black effect with a spotlight, tell me if it’s work for you!

Shader "BrokenTime/EnemyVisibility" {

    Properties {
        _DesatVal ("Desaturation value", Range(1, 100)) = 1
        _MainTex ("Texture", 2D) = "white" {}
        _Color ("Main Color", Color) = (1,1,1,1)
//        [HideInInspector] _TempColor ("Temp Color", Color) = (1,1,1,1)
//        [HideInInspector] _TempAlpha ("Temp Alpha", float) = 2
    }

    SubShader {
        ColorMask RGB

        Tags {
        "RenderType" = "Transparent"
        "Queue" = "Transparent"
        "IgnoreProjector" = "True"
        }

        Lighting On
        Cull Off
        ZWrite on
        Blend SrcAlpha OneMinusSrcAlpha


        CGPROGRAM
        #pragma surface surf SimpleLambert alpha:fade

        sampler2D _MainTex;

        fixed4 _Color;
//        fixed4 _TempColor;
//        fixed _TempAlpha;

        half _DesatVal;

        struct Input {
            float2 uv_MainTex;
        };

        half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
            half NdotL = dot (s.Normal, lightDir);
            half4 c;
            float lightValue = (NdotL * atten * 2);
            c.rgb = s.Albedo * _LightColor0.rgb * lightValue;
            c.a = lightValue;
            return c;
        }

        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
//            _TempColor = c; // get texture default color
//            _TempAlpha = tex2D(_MainTex, IN.uv_MainTex).a;
            o.Albedo = c.rgb;
            o.Alpha = 0;
        }

    ENDCG
    }
    Fallback "Diffuse"
}
1 Like

^ Yes to add to @Balikk answer - you can’t modify constants in shaders (float/float2…). Firstly keep in mind that this shader will be executed by multiple threads concurrently and writing into same property register would result in race condition.

2 Likes

Thank you guys so much. I will try this as soon as I get home and check if its working as intended :smile:

Okay, everything works fine now, no more rendering errors. Thank you !

2 Likes