My custom shader does not work in Unity 5

Hi there!
I have a little problem. As the headline says, my custom shader stopped working in Unity 5.

Shader "Custom/FoldInvisSprite"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        _a ("a", float) = 100
        _b ("b", float) = 100
        _under ("u", int) = 1
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting On
        ZWrite Off
        Fog { Mode Off }
        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
        CGPROGRAM
            // Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members _a,_b)
            #pragma exclude_renderers d3d11 xbox360
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile DUMMY PIXELSNAP_ON
            #include "UnityCG.cginc"
           
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
            };
           
            fixed4 _Color;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;
            float _a;
            float _b;
            float _under;

            fixed4 frag(v2f IN) : COLOR
            {
            if((_a * IN.texcoord.x + _b - IN.texcoord.y) * _under > 0){
                    return tex2D(_MainTex, IN.texcoord) * IN.color;
                   
                }
            else
                return 0;
            }
           
        ENDCG
        }
    }
}

I can see just black rectangles instead of sprites. Does anyone have any clue where the problem is?
I’d be grateful for any help.

Thanks!
Vojta

My custom shader also doesn’t work, it seems that “Blend SrcAlpha OneMinusSrcAlpha” is getting completely ignored

me too,same issue after unity5 with Blend SrcAlpha OneMinusSrcAlpha , all other Blend states are working as expected

1 Like

I know apparently some things changed with shaders in 5, like compiling to hlsl or glsl or something automatically? I wonder if that switch-over has produced some new bugs.

I’m also having issues with this it seems. I’m glad I’m not the only one :slight_smile:

Blending can be different for each pass of the shader. It is therefore supposed to go inside the Pass block. The same actually goes for some other settings. In the past it also worked if set in the Subshader block, but they might have cleaned this up. That could be why it’s ignored in the shader above.

I tried moving those settings around, the Blend SrcAlpha OneMinusSrcAlpha doesn’t seem to work no matter where I paste it :S

Frankly, I’m not sure, what you mean… I tried many things, no positive result…

Here you go this should fix it, although not sure where you got the shader but it’s a bit un-optimised in places. Anyway, let me know if this works:

Shader "Custom/FoldInvisSprite"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)
        [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
        _a ("a", float) = 100
        _b ("b", float) = 100
        _under ("u", int) = 1
    }
 
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
        Cull Off
        Lighting On
        ZWrite Off
        Fog { Mode Off }
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {
        CGPROGRAM
            // Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members _a,_b)
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile DUMMY PIXELSNAP_ON
            #include "UnityCG.cginc"
          
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };
            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                half2 texcoord  : TEXCOORD0;
            };
          
            fixed4 _Color;
            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                    OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif
                return OUT;
            }
            sampler2D _MainTex;
            float _a;
            float _b;
            float _under;
            fixed4 frag(v2f IN) : COLOR
            {
                if((_a * IN.texcoord.x + _b - IN.texcoord.y) * _under > 0)
                {
                    return tex2D(_MainTex, IN.texcoord) * IN.color;
                  
                }
                else
                {
                    return 0;
                }
            }
          
        ENDCG
        }
    }
}

If it works okay I can optimise it for you if you need. Anyone else with any shaders that don’t work post them and I’ll fix them for you.

2 Likes

Damn, sir Jonny Roy, I want that brain of yours. Works fine. Where do you think the code is unoptimised? I may try to find someone else to help me with optimising this, since I don’t wanna waste your time. Just this is a huge help, thank you so much!

Anyway this is my first post I wanted to say that I had a shader problem (I’m not a good shader writer) but I just wanted to share some knowledge if someone had the same problem with the shaders

I changed all these things and my shader started to work again.
OLD: #pragma surface surf Lambert
NEW: #pragma surface surf Standard fullforwardshadows

OLD: void surf(Input IN, inout SurfaceOutput o) {
NEW: void surf (Input IN, inout SurfaceOutputStandard o) {

Maybe it will help you with your shaders

1 Like

I am running into the same issues trying to rewrite a shader I’ve written for Unity 4, blending seems broken.

We wanted a splatmap shader that allowed for more than 4 textures, so after attempting arcane magic with packing floats into RGBA in order to do 8 or more textures I ended up simply layering materials. A simple One OneMinusSrcAlpha blend used to do the trick but in Unity 5 I’m completely at a loss. The blend mode simply doesn’t seem to work, and any other blendmode makes my terrain see-through.

I’m trying to adapt the Terrain shader from the Viking demo here; but I can neither get the blending to work as described above and my shadows receiving seem to be broken.

If anyone can help that would be greatly appreciated.

Shader "TerrainSurface"
{
    Properties
    {
        _Control ("Control (R)", 2D) = "red" {}

        _WorldSplatScale("WorldSplat Scale", Float) = 0.3
        _WorldSplatOffset("Offset XY", Vector) = (0.5, 0.5, 0.0, 0.0)

        _EdgeMask("Edge Mask", 2D) = "white" {}
        _EdgeMaskScale("Edge Mask Scale", Float) = 2

        _MaskSoftness ("Mask Softness", Float ) = 1.23
        _MaskMinStep ("Mask Min Step", Float ) = 0.3
        _MaskMaxStep ("Mask Max Step", Float ) = 0.5
   
        _Splat0 ("Albedo 0", 2D) = "white" {}

        _Splat0Scale("Scale", Float) = 0.2

        _Splat1 ("Albedo 1", 2D) = "white" {}

        _Splat1Scale("Scale", Float) = 0.2

        _Mask ("Mask", 2D) = "black" {}
   
        _NormalMap ("NormalMap 0", 2D) = "bump" {}
        _NormalMap2 ("NormalMap 1", 2D) = "bump" {}
       
        [LM_Specular] [LM_Glossiness] _SpecGlossMap("Specular 0", 2D) = "white" {}
        [LM_Specular] [LM_Glossiness] _SpecGlossMap2("Specular 1", 2D) = "white" {}
    }

    // SM3+
    SubShader
    {
        Tags { "RenderType" = "Opaque" }

        Blend One OneMinusSrcAlpha
       
        CGPROGRAM
        #pragma surface surf StandardSpecular fullforwardshadows addshadow
        // until texCubeLOD is solved
        #pragma exclude_renderers gles
        #pragma target 3.0

               
        struct Input
        {
            float4 color;
            float2 uv_MainTex;
            float2 uv_MainTex2;
            float2 uv_Mask;
            float3 worldPos;
            float3 worldNormal;
        };

        sampler2D _Control;

        float _WorldSplatScale;
        float4 _WorldSplatOffset;
           
        sampler2D _EdgeMask;
        float _EdgeMaskScale;

        float _MaskSoftness;
        float _MaskMinStep;
        float _MaskMaxStep;

        sampler2D _Splat0;
        sampler2D _Splat1;

        float _Splat0Scale;
        float _Splat1Scale;

        sampler2D _NormalMap;
        sampler2D _NormalMap2;
   
        sampler2D _SpecGlossMap;
        sampler2D _SpecGlossMap2;
   
        sampler2D _Mask;
   
        void surf (Input IN, inout SurfaceOutputStandardSpecular o)
        {
            float3 projNormal = saturate(pow(IN.worldNormal * 1.4, 4));
            float3 mask = tex2D(_Control, (IN.worldPos.xz * _WorldSplatScale * float2(1.0, -1.0))+_WorldSplatOffset.xy);

            float3 edgeMask = tex2D(_EdgeMask, IN.worldPos.xz * _EdgeMaskScale);
            mask = 1-clamp(1-(1-mask.r * (edgeMask)) + mask.r,0,1);
            mask *= mask * _MaskSoftness;
            mask = smoothstep(max(0,_MaskMinStep),max(0,_MaskMaxStep),mask);

            fixed blend = tex2D(_Mask, IN.uv_Mask).a;
   
            fixed4 albedo1 = tex2D(_Splat0, IN.worldPos.xz * _Splat0Scale);
            fixed4 spec1    = tex2D(_SpecGlossMap, IN.worldPos.xz * _Splat0Scale);
             fixed3 normal1 = UnpackNormal (tex2D (_NormalMap, IN.worldPos.xz * _Splat0Scale));

            fixed4 albedo2 = tex2D(_Splat1, IN.worldPos.xz * _Splat0Scale);
            fixed4 spec2 = tex2D(_SpecGlossMap2, IN.worldPos.xz * _Splat0Scale);
             fixed3 normal2 = UnpackNormal (tex2D (_NormalMap2, IN.worldPos.xz * _Splat0Scale));

             fixed4 specGloss = lerp (spec1, spec2, blend);
           
            o.Albedo         = lerp (albedo1, albedo2, blend);
             o.Specular         = mask.r * specGloss.rgb;
            o.Smoothness     = mask.r * specGloss.a;
              o.Normal         = mask.r * lerp (normal1, normal2, blend);
              o.Alpha            = mask.r;
        }
        ENDCG
    }

    CustomEditor "BlendShaderGUI"
}

Hey Jonny Roy, would be awesome if you could take a look at the following shader, which worked for me in 4.6 but doesn’t work the same way in 5.0:

I too would be appreciative if someone could help fix the shader posted in this thread:

Hey Jonny Roy, thanks so much for helping everyone out! That’s so amazing of you given shader programming’s high barrier of entry. A friend of mine recently gave me some shader code and like everyone else, every object with the shader turns black on builds. Could you take a look at mine? It gets errors like

“Program ‘frag_surf’, error X4506: ps_4_0_level_9_1 input limit (8) exceeded, shader uses 9 inputs.
Compiling Fragment program with DIRECTIONAL SHADOWS_SCREEN SHADOWS_NATIVE LIGHTMAP_OFF DIRLIGHTMAP_OFF DYNAMICLIGHTMAP_OFF FOG_LINEAR”

and

“Too many math instructions for SM2.0 (66 needed, max is 64). Try #pragma target 3.0
Compiling Fragment program with DIRECTIONAL SHADOWS_OFF LIGHTMAP_OFF DIRLIGHTMAP_OFF DYNAMICLIGHTMAP_OFF FOG_LINEAR”

Here’s the code:

Shader "RimLightingScroll"
{
    Properties
    {
_DiffuseColor("_DiffuseColor", Color) = (1,0,0,1)
_RimColor("_RimColor", Color) = (0,0.1188812,1,1)
_RimPower("_RimPower", Range(0.1,3) ) = 1.707772
_Glossiness("_Glossiness", Range(0.1,1) ) = 0.4300518
_SpecularColor("_SpecularColor", Color) = (0.3006994,1,0,1)
_MainTex("_MainTex", 2D) = "white" {}
_ScanA("ScanA", 2D) = "black" {}
_ScanB("ScanB", 2D) = "black" {}
_ScanForeground("ScanForeground", 2D) = "black" {}
_ScanColor("ScanColor", Color) = (1,1,1,1)

    }
  
    SubShader
    {
        Tags
        {
"Queue"="Geometry"
"IgnoreProjector"="False"
"RenderType"="Opaque"

        }

      
Cull Back
ZWrite On
ZTest LEqual
ColorMask RGBA
Fog{
}


        CGPROGRAM
#pragma surface surf BlinnPhongEditor  vertex:vert
#pragma target 2.0


float4 _DiffuseColor;
float4 _RimColor;
float _RimPower;
float _Glossiness;
float4 _SpecularColor;
sampler2D _MainTex;
sampler2D _ScanA;
sampler2D _ScanB;
sampler2D _ScanForeground;
float4 _ScanColor;

            struct EditorSurfaceOutput {
                half3 Albedo;
                half3 Normal;
                half3 Emission;
                half3 Gloss;
                half Specular;
                half Alpha;
                half4 Custom;
            };
          
            inline half4 LightingBlinnPhongEditor_PrePass (EditorSurfaceOutput s, half4 light)
            {
half3 spec = light.a * s.Gloss;
half4 c;
c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
c.a = s.Alpha;
return c;

            }

            inline half4 LightingBlinnPhongEditor (EditorSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
            {
                half3 h = normalize (lightDir + viewDir);
              
                half diff = max (0, dot ( lightDir, s.Normal ));
              
                float nh = max (0, dot (s.Normal, h));
                float spec = pow (nh, s.Specular*128.0);
              
                half4 res;
                res.rgb = _LightColor0.rgb * diff;
                res.w = spec * Luminance (_LightColor0.rgb);
                res *= atten * 2.0;

                return LightingBlinnPhongEditor_PrePass( s, res );
            }
          
            struct Input {
                float2 uv_MainTex;
float4 color : COLOR;
float2 uv_ScanForeground;
float2 uv_ScanB;
float2 uv_ScanA;
float3 viewDir;

            };

            void vert (inout appdata_full v, out Input o) {
            UNITY_INITIALIZE_OUTPUT(Input,o);
float4 VertexOutputMaster0_0_NoInput = float4(0,0,0,0);
float4 VertexOutputMaster0_1_NoInput = float4(0,0,0,0);
float4 VertexOutputMaster0_2_NoInput = float4(0,0,0,0);
float4 VertexOutputMaster0_3_NoInput = float4(0,0,0,0);


            }
          

            void surf (Input IN, inout EditorSurfaceOutput o) {
                o.Normal = float3(0.0,0.0,1.0);
                o.Alpha = 1.0;
                o.Albedo = 0.0;
                o.Emission = 0.0;
                o.Gloss = 0.0;
                o.Specular = 0.0;
                o.Custom = 0.0;
              
float4 Sampled2D0=tex2D(_MainTex,IN.uv_MainTex.xy);
float4 Multiply1=IN.color * _DiffuseColor;
float4 Multiply3=Sampled2D0 * Multiply1;
float4 Sampled2D3=tex2D(_ScanForeground,IN.uv_ScanForeground.xy);
float4 Sampled2D2=tex2D(_ScanB,IN.uv_ScanB.xy);
float4 Sampled2D1=tex2D(_ScanA,IN.uv_ScanA.xy);
float4 Add0=Sampled2D2 + Sampled2D1;
float4 Multiply4=Sampled2D3 * Add0;
float4 Multiply5=_ScanColor * Multiply4;
float4 Fresnel0_1_NoInput = float4(0,0,1,1);
float4 Fresnel0=(1.0 - dot( normalize( float4( IN.viewDir.x, IN.viewDir.y,IN.viewDir.z,1.0 ).xyz), normalize( Fresnel0_1_NoInput.xyz ) )).xxxx;
float4 Pow0=pow(Fresnel0,_RimPower.xxxx);
float4 Multiply0=_RimColor * Pow0;
float4 Multiply2=IN.color * Multiply0;
float4 Add1=Multiply5 + Multiply2;
float4 Master0_1_NoInput = float4(0,0,1,1);
float4 Master0_5_NoInput = float4(1,1,1,1);
float4 Master0_7_NoInput = float4(0,0,0,0);
float4 Master0_6_NoInput = float4(1,1,1,1);
o.Albedo = Multiply3;
o.Emission = Add1;
o.Specular = _Glossiness.xxxx;
o.Gloss = _SpecularColor;

                o.Normal = normalize(o.Normal);
            }
        ENDCG
    }
    Fallback "Diffuse"
}

Well, it’s mainly this section:

if((_a * IN.texcoord.x + _b - IN.texcoord.y) * _under > 0)
                {
                    return tex2D(_MainTex, IN.texcoord) * IN.color;
                  
                }
                else
                {
                    return 0;
                }

With shader code the parts in the frag function basically get called for every pixel and so need to be as efficient as possible, “if” statements are one of the slowest functions you can call, so should be avoided, basically replace the above with this:

float blankVal=(_a * IN.texcoord.x + _b - IN.texcoord.y) * _under;
                return tex2D(_MainTex, IN.texcoord) * IN.color * (1 - step(blankVal, 0.0));

Basically with if, the shader runs both bits of code every time, then decides which value to go with after it evaluates the if, it’s just because they batch process multiple pixels at one, I’ve changed this to use the step command which basically compares the first value to the second and return 0 if the second is greater than or equal to the second otherwise 1 (which is why I did 1 - the step), it should give the same result and be quite a bit faster.

Hi Cygnusfear,

I’d need more of a repro showing the issue with this as it’s a little more complex and specific, if you can upload a simple sample project I’ll see what I can do.

Thanks,

Jon

1 Like

Actually as a guess…try changing this:
#pragma surface surf StandardSpecular fullforwardshadows addshadow

To this:
#pragma surface surf StandardSpecular alpha:blend fullforwardshadows addshadow

Not sure if it will work, but might be the issue.

No problem Kiron, out of interest are you targeting windows store with this? Or just iOS, android? It’s a slightly trickier one to fix this one, but depending on what your targeting depends on how easy the fix is!

Well, we are targeting the Steam platform at the moment, but in the future we’re looking to do iOS and Android. It would be great if you can just help us out with a PC solution and we’ll worry about mobile later.

Thanks so much for helping!

And just curious, do you recommend any tutorials/learning resources for starting to program shaders for Unity? It seems to be a very uncommonly educated topic in programming, like specific knowledge for triple A studios