Search Unity

Receiving Shadows in URP, CG

Discussion in 'Shaders' started by ArseneySorokin, Jan 7, 2022.

  1. ArseneySorokin

    ArseneySorokin

    Joined:
    Jan 23, 2013
    Posts:
    63
    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):
    1.  
    2. #pragma multi_compile_fwdbase
    3. #include "AutoLight.cginc"
    4. LIGHTING_COORDS(3, 4)
    5. TRANSFER_VERTEX_TO_FRAGMENT(o);
    6. LIGHT_ATTENUATION(i);
    7.  
    but LIGHT_ATTENUATION(i); always seems to be 1.

    Here's my full code. Please assist -
    Code (CSharp):
    1. // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
    2.  
    3. Shader "Unlit/TerrainBlendShader"
    4. {
    5.     Properties
    6.     {
    7.          _MainTex("Texture", 2D) = "white" {}
    8.          _Texture1("Texture 1", 2D) = "white" {}
    9.          _Texture2("Texture 2", 2D) = "white" {}
    10.          _Texture3("Texture 3", 2D) = "white" {}
    11.          _Texture4("Texture 4", 2D) = "white" {}
    12.     }    SubShader
    13.     {
    14.         Tags { "RenderType"="Opaque" }
    15.         LOD 100
    16.  
    17.         Pass
    18.         {
    19.             CGPROGRAM
    20.             #pragma vertex vert
    21.             #pragma fragment frag
    22.  
    23.             #pragma multi_compile_fwdbase //shadows
    24.             #include "AutoLight.cginc" //shadows
    25.  
    26.  
    27.             #include "UnityCG.cginc"
    28.             #define Z_TEXTURE_CHANNELS 6
    29.             #define Z_DEFINE_MESH_ATTRIBUTES COLOR UV3 UV4
    30.  
    31.             struct appdata
    32.             {
    33.                 float4 vertex : POSITION;
    34.                 float2 uv : TEXCOORD0;
    35.                 float4 uv2 : TEXCOORD2;
    36.                 float4 uv3 : TEXCOORD3;
    37.                 float4 color : COLOR;
    38.                 float3 normal : NORMAL;
    39.             };
    40.  
    41.             struct v2f
    42.             {
    43.                 float2 uv : TEXCOORD0;
    44.                 float4 vertex : SV_POSITION;
    45.                 float4 color : COLOR;
    46.                 float3 normal :TEXCOORD1;
    47.                 float3 worldPos : TEXCOORD2;
    48.                 LIGHTING_COORDS(3, 4) //shadows
    49.             };
    50.  
    51.             sampler2D _MainTex;
    52.             sampler2D _Texture1;
    53.             sampler2D _Texture2;
    54.             sampler2D _Texture3;
    55.             sampler2D _Texture4;
    56.             float4 _MainTex_ST;
    57.  
    58.             v2f vert (appdata v)
    59.             {
    60.                 v2f o;
    61.                 o.vertex = UnityObjectToClipPos(v.vertex);
    62.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    63.                 o.color = v.color;
    64.                 o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    65.                 o.normal = UnityObjectToWorldNormal(v.normal);
    66.                 TRANSFER_VERTEX_TO_FRAGMENT(o);//shadows
    67.                 return o;
    68.             }
    69.  
    70.             fixed4 frag (v2f i) : SV_Target
    71.             {
    72.                 const float3 light = _WorldSpaceLightPos0.xyz;
    73.                 const float lambert_light = saturate(dot(i.normal, light));
    74.  
    75.                 fixed4 col2 = tex2D(_Texture1, i.uv) * i.color.x;
    76.                 fixed4 col3 = tex2D(_Texture2, i.uv) * i.color.y;
    77.                 fixed4 col4 = tex2D(_Texture3, i.uv) * i.color.z;
    78.                 fixed4 col5 = tex2D(_Texture4, i.uv) * i.color.w;
    79.  
    80.                 fixed4 col1 = tex2D(_MainTex, i.uv) * (1 - i.color.x - i.color.y - i.color.z - i.color.w) ;
    81.  
    82.                 fixed4 finalColor = fixed4((col1 + col2 + col3 + col4 + col5).xyz * lambert_light, 1);
    83.                 finalColor.rgb ;
    84.  
    85.                 return finalColor * LIGHT_ATTENUATION(i); //shadow
    86.             }
    87.             ENDCG
    88.         }
    89.         //Shadow Pass
    90.        Pass
    91.        {
    92.            Tags {"LightMode" = "ShadowCaster"}
    93.  
    94.            CGPROGRAM
    95.            #pragma vertex vert
    96.            #pragma fragment frag
    97.            #pragma multi_compile_shadowcaster
    98.            #include "UnityCG.cginc"
    99.  
    100.            struct v2f {
    101.                V2F_SHADOW_CASTER;
    102.            };
    103.  
    104.            v2f vert(appdata_base v)
    105.            {
    106.                v2f o;
    107.                TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
    108.                return o;
    109.            }
    110.  
    111.            float4 frag(v2f i) : SV_Target
    112.            {
    113.                SHADOW_CASTER_FRAGMENT(i)
    114.            }
    115.            ENDCG
    116.        }
    117.     }
    118.     FallBack "Universal Render Pipeline/Lit"
    119. }
    120.  
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    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.
     
  3. ArseneySorokin

    ArseneySorokin

    Joined:
    Jan 23, 2013
    Posts:
    63
    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?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    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.