Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Surface Shader For 2D Sprites With Shadowing

Discussion in 'Shaders' started by DeathDealer92, Feb 5, 2016.

  1. DeathDealer92

    DeathDealer92

    Joined:
    Feb 5, 2016
    Posts:
    3
    Hey Everyone,

    I'm working on getting a shader for Sprites that supports Bump Maps, Specular Maps, and full shadows (cast and receives). I have a script that forces my Sprite Renderer to cast/receive shadows and it works with other shaders so the Sprite Renderer isn't the problem. For some reason, it seems that no matter what I do with my shader it will NOT receive shadows and I have no idea why.

    So, I'm looking for either the reason why my shader isn't working properly OR for a different shader that has what I'm looking for. My shader here has a few bells and whistles but really the main things I want is bump/spec mapping and full shadow support.

    Here is my shader that I am having the problems with (some things are still a work in progress on it until I can solve this):
    Code (CSharp):
    1. Shader "Sprites/Custom/Bumped Spec Sprite with Shadows" {
    2.     Properties {
    3.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    4.         _BumpMap ("Normalmap", 2D) = "bump" {}
    5.         _SpecMap("SpecMap", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         _SpecMapIntensity("SpecMap Intensity", Range(0.01, 1)) = 0.078125
    8.         _Shininess("Shininess", Range(0.01, 1)) = 0.078125
    9.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    10.         _Cutoff ("Alpha Cutoff", Range (0,1)) = 0.5
    11.     }
    12.  
    13.     SubShader{
    14.         Tags {
    15.             "Queue"="Transparent"
    16.             "IgnoreProjector"="True"
    17.             "RenderType"="Geometry"
    18.             "PreviewType"="Plane"
    19.             "CanUseSpriteAtlas"="True"
    20.         }
    21.  
    22.         LOD 300
    23.         Cull Off
    24.         Lighting On
    25.         ZWrite Off
    26.         Fog { Mode Off }
    27.  
    28.         CGPROGRAM
    29.         #pragma surface surf ColoredSpecular alpha vertex:vert addshadow alphatest:_Cutoff
    30.         #pragma multi_compile DUMMY PIXELSNAP_ON
    31.         #pragma fragmentoption ARB_precision_hint_fastest
    32.         #pragma target 3.0
    33.  
    34.         sampler2D _MainTex;
    35.         sampler2D _BumpMap;
    36.         sampler2D _SpecMap;
    37.         fixed4 _Color;
    38.         half _Shininess;
    39.         half _SpecMapIntensity;
    40.  
    41.         struct Input {
    42.             float2 uv_MainTex;
    43.             float2 uv_BumpMap;
    44.             float2 uv_SpecMap;
    45.             fixed4 color;
    46.         };
    47.  
    48.         struct MySurfaceOutput {
    49.             half3 Albedo;
    50.             half3 Normal;
    51.             half3 Emission;
    52.             half Specular;
    53.             half3 GlossColor;
    54.             half Gloss;
    55.             half Alpha;
    56.         };
    57.      
    58.         inline half4 LightingColoredSpecular(MySurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
    59.             half3 h = normalize((lightDir + viewDir) * float3(1, -1, 1));
    60.  
    61.             half diff = max(0, dot(s.Normal, lightDir));
    62.  
    63.             float nh = max(0, dot(s.Normal, h));
    64.             float spec = pow(nh, s.Specular * 128.0f) * s.Gloss;
    65.             half3 specCol = spec * s.GlossColor;
    66.  
    67.             half4 c;
    68.             c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * specCol) * (atten * 2);
    69.             c.a = s.Alpha;
    70.  
    71.             return c;
    72.         }
    73.  
    74.         inline half4 LightingColoredSpecular_PrePass(MySurfaceOutput s, half4 light) {
    75.             half3 spec = light.a * s.GlossColor * s.Gloss;
    76.  
    77.             half4 c;
    78.             c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
    79.             c.a = s.Alpha + spec * _SpecColor.a;
    80.  
    81.             return c;
    82.         }
    83.  
    84.         void vert (inout appdata_full v, out Input o) {
    85.             #if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
    86.             v.vertex = UnityPixelSnap (v.vertex);
    87.             #endif
    88.             v.normal = float3(0,0,-1);
    89.             v.tangent =  float4(1, 0, 0, 1);
    90.          
    91.             UNITY_INITIALIZE_OUTPUT(Input, o);
    92.             o.color = _Color;
    93.         }
    94.  
    95.         void surf (Input IN, inout MySurfaceOutput o) {
    96.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * IN.color;
    97.             o.Albedo = c.rgb;
    98.             o.Alpha = c.a;
    99.  
    100.             half4 spec = tex2D(_SpecMap, IN.uv_SpecMap);
    101.             o.GlossColor = spec.rgb;
    102.             o.Gloss = c.a * _SpecMapIntensity;
    103.             o.Specular = _Shininess;
    104.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    105.         }
    106.         ENDCG
    107.     }
    108.     Fallback "Transparent/Cutout/VertexLit"
    109. }
    110.  
    Here is a shader that I have which casts and receives shadows but doesn't support the features that I want (Bump and Specular Mapping):
    Code (CSharp):
    1. Shader "Custom/StandardCutoffCustom" {
    2.     Properties
    3.     {
    4.         _Color("Color", Color) = (1,1,1,1)
    5.         [PerRendererData] _MainTex("Albedo", 2D) = "white" {}
    6.      
    7.         _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
    8.  
    9.         // Blending state
    10.         [HideInInspector] _SrcBlend ("__src", Float) = 1.0
    11.         [HideInInspector] _DstBlend ("__dst", Float) = 0.0
    12.         [HideInInspector] _ZWrite ("__zw", Float) = 1.0
    13.     }
    14.  
    15.     SubShader
    16.     {
    17.         Tags { "RenderType"="AlphaTest"  "PerformanceChecks"="False" }
    18.         LOD 300
    19.         Cull off
    20.  
    21.  
    22.         // ------------------------------------------------------------------
    23.         //  Base forward pass (directional light, emission, lightmaps, ...)
    24.         Pass
    25.         {
    26.             Name "FORWARD"
    27.             Tags { "LightMode" = "ForwardBase" }
    28.  
    29.             Blend [_SrcBlend] [_DstBlend]
    30.             ZWrite [_ZWrite]
    31.  
    32.             CGPROGRAM
    33.             #pragma target 3.0
    34.             #pragma exclude_renderers gles
    35.          
    36.             // -------------------------------------
    37.                  
    38.             #pragma shader_feature _ _ALPHATEST_ON
    39.          
    40.             #pragma multi_compile_fwdbase
    41.             #pragma multi_compile_fog
    42.              
    43.             #pragma vertex vertForwardBase
    44.             #pragma fragment fragForwardBase
    45.  
    46.             #include "UnityStandardCore.cginc"
    47.  
    48.             ENDCG
    49.         }
    50.         // ------------------------------------------------------------------
    51.         //  Additive forward pass (one light per pass)
    52.         Pass
    53.         {
    54.             Name "FORWARD_DELTA"
    55.             Tags { "LightMode" = "ForwardAdd" }
    56.             Blend [_SrcBlend] One
    57.             Fog { Color (0,0,0,0) } // in additive pass fog should be black
    58.             ZWrite Off
    59.             ZTest LEqual
    60.  
    61.             CGPROGRAM
    62.             #pragma target 3.0
    63.             #pragma exclude_renderers gles
    64.  
    65.             // -------------------------------------
    66.  
    67.             #pragma shader_feature _ _ALPHATEST_ON
    68.          
    69.             #pragma multi_compile_fwdadd_fullshadows
    70.             #pragma multi_compile_fog
    71.          
    72.             #pragma vertex vertForwardAdd
    73.             #pragma fragment fragForwardAdd
    74.  
    75.             #include "UnityStandardCore.cginc"
    76.  
    77.             ENDCG
    78.         }
    79.         // ------------------------------------------------------------------
    80.         //  Shadow rendering pass
    81.         Pass {
    82.             Name "ShadowCaster"
    83.             Tags { "LightMode" = "ShadowCaster" }
    84.          
    85.             ZWrite On ZTest LEqual
    86.  
    87.             CGPROGRAM
    88.             #pragma target 3.0
    89.             #pragma exclude_renderers gles
    90.          
    91.             // -------------------------------------
    92.  
    93.  
    94.             #pragma shader_feature _ _ALPHATEST_ON
    95.             #pragma multi_compile_shadowcaster
    96.  
    97.             #pragma vertex vertShadowCaster
    98.             #pragma fragment fragShadowCaster
    99.  
    100.             #include "UnityStandardShadow.cginc"
    101.  
    102.             ENDCG
    103.         }
    104.         // ------------------------------------------------------------------
    105.         //  Deferred pass
    106.         Pass
    107.         {
    108.             Name "DEFERRED"
    109.             Tags { "LightMode" = "Deferred" }
    110.  
    111.             CGPROGRAM
    112.             #pragma target 3.0
    113.             // TEMPORARY: GLES2.0 temporarily disabled to prevent errors spam on devices without textureCubeLodEXT
    114.             #pragma exclude_renderers nomrt gles
    115.          
    116.  
    117.             // -------------------------------------
    118.  
    119.             #pragma shader_feature _ _ALPHATEST_ON
    120.  
    121.             #pragma multi_compile ___ UNITY_HDR_ON
    122.             #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
    123.             #pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    124.             #pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
    125.          
    126.             #pragma vertex vertDeferred
    127.             #pragma fragment fragDeferred
    128.  
    129.             #include "UnityStandardCore.cginc"
    130.  
    131.             ENDCG
    132.         }
    133.     }
    134.     FallBack "VertexLit"
    135. }
    136.  
    Anybody have any ideas or alternatives?

    EDIT:
    I forgot to mention that I realize my shader doesn't have any additional Passes in it which I believe are required for it to correctly receive shadows (blending and all that). However, I spent a ton of time messing with adding different Passes but none seemed to work (or do much of anything, really) so I didn't include anything like that in what I posted.
     
    Last edited: Feb 5, 2016
  2. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,589
    Unity does not support transparent materials, shaders that use the transparent rendering order tag, to receive shadows. The other shader you posted is using the AlphaTest queue, where receiving shadows works.
     
  3. DeathDealer92

    DeathDealer92

    Joined:
    Feb 5, 2016
    Posts:
    3
    Thanks for the response! I actually managed to figure out how to get it to work with Sprites and a normal map but I'm still having issues with my shader which includes a specular map. For some reason, it won't receive shadows. Here is the code for 2D sprites with shadows and normal map support which works:
    Code (CSharp):
    1. Shader "Sprites/Custom/Bumped Diffuse with Shadows" {
    2.     Properties {
    3.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    4.         _BumpMap ("Normalmap", 2D) = "bump" {}
    5.         _Color ("Tint", Color) = (1,1,1,1)
    6.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    7.         _Cutoff ("Alpha Cutoff", Range (0,1)) = 0.5
    8.     }
    9.  
    10.     SubShader {
    11.         Tags {
    12.             "Queue"="AlphaTest"
    13.             "IgnoreProjector"="True"
    14.             "RenderType"="TransparentCutOut"
    15.             "PreviewType"="Plane"
    16.             "CanUseSpriteAtlas"="True"
    17.         }
    18.  
    19.         LOD 300
    20.         Cull Off
    21.         Lighting On
    22.         Fog{ Mode Off }
    23.        
    24.         CGPROGRAM
    25.         #pragma surface surf Lambert alpha vertex:vert addshadow fullforwardshadows alphatest:_Cutoff
    26.         #pragma target 3.0
    27.         #pragma multi_compile DUMMY PIXELSNAP_ON
    28.  
    29.         sampler2D _MainTex;
    30.         sampler2D _BumpMap;
    31.         fixed4 _Color;
    32.  
    33.         struct Input {
    34.             float2 uv_MainTex;
    35.             float2 uv_BumpMap;
    36.         };
    37.        
    38.         void vert (inout appdata_full v, out Input o) {
    39.             #if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
    40.             v.vertex = UnityPixelSnap (v.vertex);
    41.             #endif
    42.             v.normal = float3(0,0,-1);
    43.             v.tangent =  float4(1, 0, 0, 1);
    44.            
    45.             UNITY_INITIALIZE_OUTPUT(Input, o);
    46.         }
    47.  
    48.         void surf (Input IN, inout SurfaceOutput o) {
    49.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    50.             o.Albedo = c.rgb;
    51.             o.Alpha = c.a;
    52.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    53.         }
    54.         ENDCG
    55.     }
    56.  
    57. Fallback "Transparent/Cutout/Diffuse"
    58. }
    59.  
    Here is my current code for bumped and spec with shadows:
    Code (CSharp):
    1. Shader "Sprites/Custom/Bumped Spec Diffuse with Shadows" {
    2.     Properties {
    3.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    4.         _BumpMap ("Normalmap", 2D) = "bump" {}
    5.         _SpecMap("SpecMap", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         _SpecMapIntensity("SpecMap Intensity", Range(0.01, 1)) = 0.078125
    8.         _Shininess("Shininess", Range(0.01, 1)) = 0.078125
    9.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    10.         _Cutoff ("Alpha Cutoff", Range (0,1)) = 0.5
    11.     }
    12.  
    13.     SubShader{
    14.         Tags {
    15.             "Queue"="AlphaTest"
    16.             "IgnoreProjector"="True"
    17.             "RenderType"="TransparentCutOut"
    18.             "PreviewType"="Plane"
    19.             "CanUseSpriteAtlas"="True"
    20.         }
    21.  
    22.         LOD 300
    23.         Cull Off
    24.         Lighting On
    25.         Fog{ Mode Off }
    26.  
    27.         CGPROGRAM
    28.         #pragma surface surf ColoredSpecular alpha vertex:vert addshadow fullforwardshadows alphatest:_Cutoff
    29.         #pragma target 3.0
    30.         #pragma multi_compile DUMMY PIXELSNAP_ON
    31.  
    32.         sampler2D _MainTex;
    33.         sampler2D _BumpMap;
    34.         sampler2D _SpecMap;
    35.         fixed4 _Color;
    36.         half _Shininess;
    37.         half _SpecMapIntensity;
    38.  
    39.         struct Input {
    40.             float2 uv_MainTex;
    41.             float2 uv_BumpMap;
    42.             float2 uv_SpecMap;
    43.         };
    44.  
    45.         struct MySurfaceOutput {
    46.             half3 Albedo;
    47.             half3 Normal;
    48.             half3 Emission;
    49.             half Specular;
    50.             half3 GlossColor;
    51.             half Gloss;
    52.             half Alpha;
    53.         };
    54.        
    55.         inline half4 LightingColoredSpecular(MySurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
    56.             half3 h = normalize((lightDir + viewDir) * float3(1, -1, 1));
    57.  
    58.             half diff = max(0, dot(s.Normal, lightDir));
    59.  
    60.             float nh = max(0, dot(s.Normal, h));
    61.             float spec = pow(nh, s.Specular * 128.0f) * s.Gloss;
    62.             half3 specCol = spec * s.GlossColor;
    63.  
    64.             half4 c;
    65.             c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * specCol) * (atten * 2);
    66.             c.a = s.Alpha;
    67.  
    68.             return c;
    69.         }
    70.  
    71.         inline half4 LightingColoredSpecular_PrePass(MySurfaceOutput s, half4 light) {
    72.             half3 spec = light.a * s.GlossColor * s.Gloss;
    73.  
    74.             half4 c;
    75.             c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
    76.             c.a = s.Alpha + spec * _SpecColor.a;
    77.  
    78.             return c;
    79.         }
    80.  
    81.         void vert (inout appdata_full v, out Input o) {
    82.             #if defined(PIXELSNAP_ON) && !defined(SHADER_API_FLASH)
    83.             v.vertex = UnityPixelSnap (v.vertex);
    84.             #endif
    85.             v.normal = float3(0,0,-1);
    86.             v.tangent =  float4(1, 0, 0, 1);
    87.            
    88.             UNITY_INITIALIZE_OUTPUT(Input, o);
    89.         }
    90.  
    91.         void surf (Input IN, inout MySurfaceOutput o) {
    92.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    93.             o.Albedo = c.rgb;
    94.             o.Alpha = c.a;
    95.  
    96.             half4 spec = tex2D(_SpecMap, IN.uv_SpecMap);
    97.             o.GlossColor = spec.rgb;
    98.             o.Gloss = c.a * _SpecMapIntensity;
    99.             o.Specular = _Shininess;
    100.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    101.         }
    102.         ENDCG
    103.     }
    104.     Fallback "Transparent/Cutout/VertexLit"
    105. }
    106.  
    As you can see, the two are pretty similar but I'm not sure what is causing the issue?