Search Unity

Sprite with shadows

Discussion in 'Shaders' started by Rafael-cmk, Jul 17, 2019.

  1. Rafael-cmk

    Rafael-cmk

    Joined:
    Jun 28, 2016
    Posts:
    30
    Hi everyone,
    I need a big favor, I don't know a thing about shaders and I need a special one for my project, if someone could help me with that I will really appreciate.

    Basically, I need a sprite that still act as a sprite respecting the sorting layers and order, but that can cast/receive shadows, I managed to just edit the original deffuse shader to do that but I had to use transparent cutout wich is bad thing, some of my sprites are half transparent and can't use that, so, is that a way to solve it?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,002
    Unity doesn't support shadow receiving on transparent objects, so no, there isn't a way to solve this. Not without entirely rewriting Unity's lighting & shadow system yourself (or using the HDRP, which supports shadows on transparent objects, but isn't 2D friendly).
     
  3. Rafael-cmk

    Rafael-cmk

    Joined:
    Jun 28, 2016
    Posts:
    30
    I know that actualy, but isn't there a way to cast the shadow as transparent cutout and then render it as normal transparent? I don't really need these half transparent sprites to receive shadow. For example, the solution I have at the moment is just using a second sprite with an invisible shader just to cast that shadow.

    Another problem I'm having is this shader I modified from the default diffuse always rendering behind normal sprites.

    Here is the shader I modified.
    Code (CSharp):
    1. Shader "Custom/SpriteWithShadow"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.         _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    9.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    10.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    11.         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
    12.         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    13.     }
    14.  
    15.     SubShader
    16.     {
    17.         Tags
    18.         {
    19.             "Queue"="AlphaTest"
    20.             "IgnoreProjector"="True"
    21.             "RenderType"="TransparentCutout"
    22.             "PreviewType"="Plane"
    23.             "CanUseSpriteAtlas"="True"
    24.         }
    25.  
    26.         Cull Off
    27.         Lighting Off
    28.         ZWrite Off
    29.         Blend One OneMinusSrcAlpha
    30.  
    31.         CGPROGRAM
    32.         #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing addshadow alphatest:_Cutoff
    33.         #pragma multi_compile_local _ PIXELSNAP_ON
    34.         #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    35.         #include "UnitySprites.cginc"
    36.  
    37.         struct Input
    38.         {
    39.             float2 uv_MainTex;
    40.             fixed4 color;
    41.         };
    42.  
    43.         void vert (inout appdata_full v, out Input o)
    44.         {
    45.             v.vertex = UnityFlipSprite(v.vertex, _Flip);
    46.  
    47.             #if defined(PIXELSNAP_ON)
    48.             v.vertex = UnityPixelSnap (v.vertex);
    49.             #endif
    50.  
    51.             UNITY_INITIALIZE_OUTPUT(Input, o);
    52.             o.color = v.color * _Color * _RendererColor;
    53.         }
    54.  
    55.         void surf (Input IN, inout SurfaceOutput o)
    56.         {
    57.             fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
    58.             o.Albedo = c.rgb * c.a;
    59.             o.Alpha = c.a;
    60.         }
    61.         ENDCG
    62.     }
    63.  
    64. Fallback "Transparent/VertexLit"
    65. }
    66.  
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,002
    Sprite sorting via the component depends on the material's / shader's render queue being the same as all other sprites you want to control sorting with. Using any queue other than Transparent (3000) means the sorting group and sorting order won't be respected, or rather they are, but the queue takes precedence. Unfortunately Unity only allows shadow receiving for objects that are using an opaque queue, between 0 and 2500.

    Luckily, since you don't care about shadow receiving, only shadow casting, that's a lot easier. Really you can probably get away with removing addshadow from your #pragma surface line and replacing your Fallback line with:
    Fallback "Transparent/Cutout/VertexLit"

    If this is a mobile project, that might not be enough because of the "external alpha" texture usage on some devices, but if this is only going to be on PC or console, that should be it.

    After that change the shader to be "Queue"="Transparent" and get rid of the alpha test.
     
    Last edited: Jul 18, 2019
  5. Rafael-cmk

    Rafael-cmk

    Joined:
    Jun 28, 2016
    Posts:
    30
    Cool, it works! but, it is for smartphones... What should I do then?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,002
    Then you may need to use a custom shadow caster pass. Take the shadow caster pass from the Cutout/VertexLit shader and replace the tex2D() with the SampleSpriteTexture(), and add these lines:

    #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    #include "UnitySprites.cginc"


    You can download the built in shaders, or helpfully someone has been uploading them to github here:
    https://github.com/TwoTailsGames/Un...aultResourcesExtra/AlphaTest-VertexLit.shader
     
  7. Rafael-cmk

    Rafael-cmk

    Joined:
    Jun 28, 2016
    Posts:
    30
    I can't make it work, I get an error message.
    Shader error in 'Sprites/Shadow/Only Cast': redefinition of 'v2f' at line 78 (on d3d11)

    Code (CSharp):
    1. Shader "Sprites/Shadow/Only Cast"
    2. {
    3.     Properties
    4.     {
    5.         [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    6.         _Color ("Tint", Color) = (1,1,1,1)
    7.         [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    8.         _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    9.         [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1)
    10.         [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1)
    11.         [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {}
    12.         [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    13.     }
    14.  
    15.     SubShader
    16.     {
    17.         Tags
    18.         {
    19.             "Queue"="Transparent"
    20.             "IgnoreProjector"="True"
    21.             "RenderType"="Transparent"
    22.             "PreviewType"="Plane"
    23.             "CanUseSpriteAtlas"="True"
    24.         }
    25.  
    26.         Cull Off
    27.         Lighting Off
    28.         ZWrite Off
    29.         Blend One OneMinusSrcAlpha
    30.  
    31.         CGPROGRAM
    32.         #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing
    33.         #pragma multi_compile_local _ PIXELSNAP_ON
    34.         #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    35.         #include "UnitySprites.cginc"
    36.  
    37.         struct Input
    38.         {
    39.             float2 uv_MainTex;
    40.             fixed4 color;
    41.         };
    42.  
    43.         void vert (inout appdata_full v, out Input o)
    44.         {
    45.             v.vertex = UnityFlipSprite(v.vertex, _Flip);
    46.  
    47.             #if defined(PIXELSNAP_ON)
    48.             v.vertex = UnityPixelSnap (v.vertex);
    49.             #endif
    50.  
    51.             UNITY_INITIALIZE_OUTPUT(Input, o);
    52.             o.color = v.color * _Color * _RendererColor;
    53.         }
    54.  
    55.         void surf (Input IN, inout SurfaceOutput o)
    56.         {
    57.             fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color;
    58.             o.Albedo = c.rgb * c.a;
    59.             o.Alpha = c.a;
    60.         }
    61.         ENDCG
    62.  
    63.         // Pass to render object as a shadow caster
    64.         Pass {
    65.             Name "Caster"
    66.             Tags { "LightMode" = "ShadowCaster" }
    67.  
    68.             CGPROGRAM
    69.             #pragma vertex vert
    70.             #pragma fragment frag
    71.             #pragma target 2.0
    72.             #pragma multi_compile_shadowcaster
    73.             #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
    74.             #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    75.             #include "UnityCG.cginc"
    76.             #include "UnitySprites.cginc"
    77.  
    78.             struct v2f {
    79.                 V2F_SHADOW_CASTER;
    80.                 float2  uv : TEXCOORD1;
    81.                 UNITY_VERTEX_OUTPUT_STEREO
    82.             };
    83.  
    84.             uniform float4 _MainTex_ST;
    85.  
    86.             v2f vert( appdata_base v )
    87.             {
    88.                 v2f o;
    89.                 UNITY_SETUP_INSTANCE_ID(v);
    90.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    91.                 TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    92.                 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    93.                 return o;
    94.             }
    95.  
    96.             uniform sampler2D _MainTex;
    97.             uniform fixed _Cutoff;
    98.             uniform fixed4 _Color;
    99.  
    100.             float4 frag( v2f i ) : SV_Target
    101.             {
    102.                 fixed4 texcol = SampleSpriteTexture( _MainTex, i.uv );
    103.                 clip( texcol.a*_Color.a - _Cutoff );
    104.  
    105.                 SHADOW_CASTER_FRAGMENT(i)
    106.             }
    107.             ENDCG
    108.  
    109.         }
    110.     }
    111.  
    112. //Fallback "Transparent/Cutout/VertexLit"
    113. }
    114.  
     
  8. ed_s

    ed_s

    Unity Technologies

    Joined:
    Apr 17, 2015
    Posts:
    34
    bgolus likes this.
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,002
    UnitySprites.cginc already has a strict named v2f defined, hence the error. Rename the v2f struct and references to it in your pass to something like v2f_shadow

    After that you’ll probably still have other errors. Look at how SampleSprite is used in the surf function, you can’t just rename tex2D to SampleSprite.
     
  10. Rafael-cmk

    Rafael-cmk

    Joined:
    Jun 28, 2016
    Posts:
    30
    I give up. if any freelancer want to help me out I will appreciate to make a deal.