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?
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).
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): Shader "Custom/SpriteWithShadow" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 } SubShader { Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha CGPROGRAM #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing addshadow alphatest:_Cutoff #pragma multi_compile_local _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA #include "UnitySprites.cginc" struct Input { float2 uv_MainTex; fixed4 color; }; void vert (inout appdata_full v, out Input o) { v.vertex = UnityFlipSprite(v.vertex, _Flip); #if defined(PIXELSNAP_ON) v.vertex = UnityPixelSnap (v.vertex); #endif UNITY_INITIALIZE_OUTPUT(Input, o); o.color = v.color * _Color * _RendererColor; } void surf (Input IN, inout SurfaceOutput o) { fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color; o.Albedo = c.rgb * c.a; o.Alpha = c.a; } ENDCG } Fallback "Transparent/VertexLit" }
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.
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
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): Shader "Sprites/Shadow/Only Cast" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Cull Off Lighting Off ZWrite Off Blend One OneMinusSrcAlpha CGPROGRAM #pragma surface surf Lambert vertex:vert nofog nolightmap nodynlightmap keepalpha noinstancing #pragma multi_compile_local _ PIXELSNAP_ON #pragma multi_compile _ ETC1_EXTERNAL_ALPHA #include "UnitySprites.cginc" struct Input { float2 uv_MainTex; fixed4 color; }; void vert (inout appdata_full v, out Input o) { v.vertex = UnityFlipSprite(v.vertex, _Flip); #if defined(PIXELSNAP_ON) v.vertex = UnityPixelSnap (v.vertex); #endif UNITY_INITIALIZE_OUTPUT(Input, o); o.color = v.color * _Color * _RendererColor; } void surf (Input IN, inout SurfaceOutput o) { fixed4 c = SampleSpriteTexture (IN.uv_MainTex) * IN.color; o.Albedo = c.rgb * c.a; o.Alpha = c.a; } ENDCG // Pass to render object as a shadow caster Pass { Name "Caster" Tags { "LightMode" = "ShadowCaster" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #pragma multi_compile_shadowcaster #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders #pragma multi_compile _ ETC1_EXTERNAL_ALPHA #include "UnityCG.cginc" #include "UnitySprites.cginc" struct v2f { V2F_SHADOW_CASTER; float2 uv : TEXCOORD1; UNITY_VERTEX_OUTPUT_STEREO }; uniform float4 _MainTex_ST; v2f vert( appdata_base v ) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } uniform sampler2D _MainTex; uniform fixed _Cutoff; uniform fixed4 _Color; float4 frag( v2f i ) : SV_Target { fixed4 texcol = SampleSpriteTexture( _MainTex, i.uv ); clip( texcol.a*_Color.a - _Cutoff ); SHADOW_CASTER_FRAGMENT(i) } ENDCG } } //Fallback "Transparent/Cutout/VertexLit" }
FYI, there's a thread about the Experimental 2D Lights and Shader Graph support in LWRP: https://forum.unity.com/threads/experimental-2d-lights-and-shader-graph-support-in-lwrp.683623/ Shadow are not in yet but are planned for later this year. https://forum.unity.com/threads/exp...er-graph-support-in-lwrp.683623/#post-4594807
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.