Hello everyone, I have a texture blend shader (to be used with PolyBrush) and I cannot get it to receive shadows. I've tried other built-in shaders to make sure the problem is the receiver and not the caster and I have even tried this in a standard pipeline project, or just adding the shadow receiver stuff to a much simpler shader, but nothing works. From what I've read all I need is the following lines - Code (CSharp): #pragma multi_compile_fwdbase #include "AutoLight.cginc" LIGHTING_COORDS(3, 4) TRANSFER_VERTEX_TO_FRAGMENT(o); LIGHT_ATTENUATION(i); but LIGHT_ATTENUATION(i); always seems to be 1. Here's my full code. Please assist - Code (CSharp): // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' Shader "Unlit/TerrainBlendShader" { Properties { _MainTex("Texture", 2D) = "white" {} _Texture1("Texture 1", 2D) = "white" {} _Texture2("Texture 2", 2D) = "white" {} _Texture3("Texture 3", 2D) = "white" {} _Texture4("Texture 4", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase //shadows #include "AutoLight.cginc" //shadows #include "UnityCG.cginc" #define Z_TEXTURE_CHANNELS 6 #define Z_DEFINE_MESH_ATTRIBUTES COLOR UV3 UV4 struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float4 uv2 : TEXCOORD2; float4 uv3 : TEXCOORD3; float4 color : COLOR; float3 normal : NORMAL; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float4 color : COLOR; float3 normal :TEXCOORD1; float3 worldPos : TEXCOORD2; LIGHTING_COORDS(3, 4) //shadows }; sampler2D _MainTex; sampler2D _Texture1; sampler2D _Texture2; sampler2D _Texture3; sampler2D _Texture4; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.color = v.color; o.worldPos = mul(unity_ObjectToWorld, v.vertex); o.normal = UnityObjectToWorldNormal(v.normal); TRANSFER_VERTEX_TO_FRAGMENT(o);//shadows return o; } fixed4 frag (v2f i) : SV_Target { const float3 light = _WorldSpaceLightPos0.xyz; const float lambert_light = saturate(dot(i.normal, light)); fixed4 col2 = tex2D(_Texture1, i.uv) * i.color.x; fixed4 col3 = tex2D(_Texture2, i.uv) * i.color.y; fixed4 col4 = tex2D(_Texture3, i.uv) * i.color.z; fixed4 col5 = tex2D(_Texture4, i.uv) * i.color.w; fixed4 col1 = tex2D(_MainTex, i.uv) * (1 - i.color.x - i.color.y - i.color.z - i.color.w) ; fixed4 finalColor = fixed4((col1 + col2 + col3 + col4 + col5).xyz * lambert_light, 1); finalColor.rgb ; return finalColor * LIGHT_ATTENUATION(i); //shadow } ENDCG } //Shadow Pass Pass { Tags {"LightMode" = "ShadowCaster"} CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_shadowcaster #include "UnityCG.cginc" struct v2f { V2F_SHADOW_CASTER; }; v2f vert(appdata_base v) { v2f o; TRANSFER_SHADOW_CASTER_NORMALOFFSET(o) return o; } float4 frag(v2f i) : SV_Target { SHADOW_CASTER_FRAGMENT(i) } ENDCG } } FallBack "Universal Render Pipeline/Lit" }
Everything you listed is things you need to receive shadows, but you're missing Tags {"LightMode" = "ForwardBase"} in the forward Pass. That should make the LIGHT_ATTENUATION macro do something in the shader you have... ... in the built in forward renderer. None of that will do anything when you're using the URP, because the URP's lit shaders are completely different than the built in renderer, and the two are entirely incompatible. If you want to write a shader for the URP, you'll probably want to use Shader Graph and not write the shader by hand because URP's lighting system is entirely undocumented by Unity, and I think people in the community gave up trying to write tutorials on it since Unity kept changing it every few weeks.
Oh damn. So what you're saying is that there is no known way to achieve what I am trying to do? I was really wondering whether I should switch back to the standard render pipeline. I sort of chose URP instinctively because my game is for mobile, so I wanted better performance. But this is the second key feature which I need and URP does not have (the first being the "Don't Clear" cameras). Assuming I write most of the shaders myself, do you recon there's a reason to stay in URP?
Oh, no, that’s not what I’m saying. People absolutely know how to do this. What I’m saying there’s no tutorials I can point to to help you out because the information keeps changing. If you’re well versed in shader code you can read the shader code for the URP and work out how to do it yourself. But generally if you can do that you’re not asking these kinds of questions on the forum. Anecdotally, I’ve seen no evidence that the URP is faster on mobile. In fact mostly I’ve seen the opposite. It can be faster in very specific setups, but most of the time it’s no different or slower. What URP offers is some benefits in terms of lighting on transparent objects working better than the built in, especially shadow receiving (which isn’t allowed at all in the built in), a slightly easier workflow in terms of optimization where you don’t need to rely on static or dynamic batching to get decent performance, and Shader Graph. Though that last one is no longer limited to the SRPs as you can use Shader Graph for the built in pipeline now too. However yes, “don’t clear” doesn’t exist anymore in an easy to access way.