Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

URP - Sampling Shadow Map from Shader Graph?

Discussion in 'Universal Render Pipeline' started by DennisGregs, Mar 31, 2020.

  1. DennisGregs

    DennisGregs

    Joined:
    Feb 4, 2020
    Posts:
    9
    Hi, I have been trying to sample the shadow map from the shader graph using a custom node. I am grabbing the main light of the scene in a custom HLSL shader, which works just fine, as I am getting its direction properly. However, the shadowAttenuation of the light doesn't give me the correct value, it always returns 1. Shadows are turned on, and they work fine with the built in shaders, is this a known issue, or am I doing something wrong?

    The shader in question:
    Code (CSharp):
    1. void CustomLightingFunc_float(float3 Position, out float3 Direction, out float3 Color, out float ShadowAttenuation)
    2. {
    3.     float4 shadowCoord = TransformWorldToShadowCoord(Position);
    4.     Light light = GetMainLight(shadowCoord);
    5.     Direction = light.direction;
    6.     Color = light.color;
    7.     ShadowAttenuation = light.shadowAttenuation;
    8. }
    Thanks in advance!
     
    Last edited: Apr 6, 2020
  2. Kronnect

    Kronnect

    Joined:
    Nov 16, 2014
    Posts:
    2,877
    Are you using an Unlit Master node? Try using the PBR node instead and link the output of your lighting function node to the Emission port.
    The Unlit master node does not declare the keywords used for shadow stuff.
     
    cultureulterior likes this.
  3. Modafuka

    Modafuka

    Joined:
    Nov 21, 2019
    Posts:
    45
    I learned basic from shader graph, then i move to hand code shader, shader graph is painful.
     
  4. DennisGregs

    DennisGregs

    Joined:
    Feb 4, 2020
    Posts:
    9
    I started from PBR using emission, and moved to Unlit afterwards, but both of them have the exact same issue. I have also tried to manually sample the shadow map myself using the function all the way down where shadowAttenuation comes from, and I get the same result. Manually setting values to the shadowAttenuation works like a charm, so it's nothing to do with the rest of the shader, it's the shadow map sampling in specific that doesn't return the correct value.

    I watched Unite Copenhagen which is fairly recent, and Ciro was using the Unlit node there, so it should be possible to do...
     
  5. falsevac

    falsevac

    Joined:
    Mar 16, 2016
    Posts:
    33
    I'm having the same issue right now. I have a similar custom node to get ShadowAttenuation. My shader works great in realtime, but unable to bake the shadows and then render using the resulting shadowmap .
     
  6. DennisGregs

    DennisGregs

    Joined:
    Feb 4, 2020
    Posts:
    9
    I updated to latest and it does indeed seem to work with PBR graph. It seems a little overkill for what I need, but oh well.
     
  7. falsevac

    falsevac

    Joined:
    Mar 16, 2016
    Posts:
    33
    Hi Dennis, you're saying that you can bake lights in a Shader Graph and GetMainLight() in your custom function now automatically returns .direction, .color, and .shadowAttenuation from the shadow map instead of the dynamic light? Thanks.
     
  8. DennisGregs

    DennisGregs

    Joined:
    Feb 4, 2020
    Posts:
    9
    I'm not baking lights, only using realtime lighting.
     
  9. zh4ngwei88

    zh4ngwei88

    Joined:
    Nov 7, 2017
    Posts:
    2
    Did you manage to get it working?
     
  10. AverageCG

    AverageCG

    Joined:
    Nov 13, 2017
    Posts:
    19
    Having the same issue, probably from starting at the same resources (
    ).
    Shadows are not rendering for me..
     
  11. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    161
    I have this working with the main light but same issue with additional lights. Did anyone have this working with additional lights?
     
  12. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    161
    Just to update...

    For unlit this is still a good bit broken.

    I got somewhere by adding my own custom node to URP shadergraph to get the light 0 shadow attenuation. It works well but on the device unity strips the shader so I need to figure that out (for now told it not to strip unused).

    So I am getting a single point light shadow casting and am able to apply that in my shadergraph using the following node (may need some tweaks). Code adopted from the lighting.hlsl or possibly the shadows.hlsl from Unity.

    Might require the _ADDITIONAL_LIGHT_SHADOWS shader keywords.

    Code (CSharp):
    1. // returns 0.0 if position is in light's shadow
    2. // returns 1.0 if position is in light
    3. void Shadow_Attenuation_float(int lightIndex, float3 positionWS, float3 lightDirection, out float shadowAtten)
    4. {
    5. #if SHADERGRAPH_PREVIEW
    6.     shadowAtten = 1.0;
    7.     return;
    8. #endif
    9.  
    10.     ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData();
    11.  
    12.     half4 shadowParams = GetAdditionalLightShadowParams(lightIndex);
    13.  
    14.     int shadowSliceIndex = shadowParams.w;
    15.  
    16.     UNITY_BRANCH
    17.     if (shadowSliceIndex < 0)
    18.     {
    19.         shadowAtten = 1.0;
    20.         return;
    21.     }
    22.  
    23.     half isPointLight = shadowParams.z;
    24.  
    25.     UNITY_BRANCH
    26.     if (isPointLight)
    27.     {
    28.         // This is a point light, we have to find out which shadow slice to sample from
    29.         float cubemapFaceId = CubeMapFaceID(-lightDirection);
    30.         shadowSliceIndex += cubemapFaceId;
    31.     }
    32.  
    33. #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
    34.     float4 shadowCoord = mul(_AdditionalLightsWorldToShadow_SSBO[shadowSliceIndex], float4(positionWS, 1.0));
    35. #else
    36.     float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[shadowSliceIndex], float4(positionWS, 1.0));
    37. #endif
    38.  
    39.     shadowAtten = SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_AdditionalLightsShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, true);
    40. }
    41.  
     
    falsevac likes this.
  13. peeweekVFX

    peeweekVFX

    Joined:
    Oct 19, 2015
    Posts:
    13
    Quick tip about how to enable these keywords in shadergraph : You can add boolean keywords to the blackboard. I tried adding _SHADOWS_SOFT and _ADDITIONAL_LIGHT_SHADOWS and it solved the issue. I set them as non-exposed, multi-compile and global. Haven't tried any more combinations but it seems that setting as shader feature also works.

    You don't need to add these as nodes in the graph.

    upload_2022-8-8_9-12-16.png

    You can also verify it's working by looking at the keywords in the frame debugger. Once these keywords are set, the shadowmap should then be bound to the material to be sampled.
     
    Bovine and cultureulterior like this.
  14. Bovine

    Bovine

    Joined:
    Oct 13, 2010
    Posts:
    161
    Maybe this is why my shader is being stripped as unused if I leave that enabled. I think I have these properties set as exposed so...