Access shadow map in URP

Hello guys,

I have some problem when calculating the attenuation through shadow map.

My goal is to implement light scattering (volumetric light) through calculating light attenuation in the ray marching step, and here’s the final snapshot in the built-in render system.

And then I write some code in shader to calculate light attenuation only, and the result looks like this :

And this is how I access shadow map in built-in render system.

 float4 cascadeWeights = GetCascadeWeights_SplitSpheres(wpos);
 bool inside = dot(cascadeWeights, float4(1, 1, 1, 1)) < 4;
 float4 samplePos = GetCascadeShadowCoord(float4(wpos, 1), cascadeWeights);
 atten = inside ? UNITY_SAMPLE_SHADOW(_CascadeShadowMapTexture, samplePos.xyz) : 1.0f;
 atten = _LightShadowData.r + atten * (1 - _LightShadowData.r);

But I got a quite different result in URP, and I used another way to access shadow map. I’m pretty sure those two scenes (transform of scene objects, camera transforms, FOV …etc) are in same condition.

And this is how I access shadow map in URP, and this shader executed as a Blit material.

half cascadeIndex = ComputeCascadeIndex(wpos);
float4 coords = mul(_MainLightWorldToShadow[cascadeIndex], float4(wpos, 1.0));
                            
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half4 shadowParams = GetMainLightShadowParams();
atten = inside ? SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), coords, shadowSamplingData, shadowParams, false) : 1.0f;
atten = shadowParams.r + atten * (1 - shadowParams.r);

The main camera is set in perspective mode (and I know the _MainLightShadowmapTexture built in orthogonal mode), and the shader is from Here.
Is there anything wrong during these steps ? any advice would be appreciated.
[Edit] I just want to know how to sample shadow map in URP and the equivalent way with the built-in method.

Have a nice day !



Finally, I found the answer.

The thing is the default shadow map between Built-in and URP are slightly different.
(The Left is from Built-in, and the Right is from URP)

And in order to make same result, you have to change some parameters in shadows settings, so the code snippet works for sampling the default shadow map.



1 Like

For anyone else coming across this, you can sample the shadow map in a URP shader by adding this to your pass:

#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

And then in the fragment function use this to get the shadow attenuation:

half ShadowAtten(float3 worldPosition)
{
        return MainLightRealtimeShadow(TransformWorldToShadowCoord(worldPosition));
}

This will work with all shadow cascade amounts and is based on this tutorial for shader graph but I cut out the parts that don’t relate to attenuation: Unity Blog

6 Likes

Hi there wanted to ask if you got the volumetric light working? may I ask if you have that repo open sourced? Thanks! I was trying to achieve volumetric lighting too and would be glad to reference it from you :slight_smile:

half ShadowAtten(float3 worldPosition)
{
        return MainLightRealtimeShadow(TransformWorldToShadowCoord(worldPosition));
}

This works great in the Editor but when built for WebGL it just appears to return 0

1 Like

I had a similar problem with shadows in a custom shader, in the editor it worked but in the windows build it did not show the shadows.
A single line of shadow pragma instead of multiple solved the problem.

#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE

It was on Unity 2021.3.26f1 URP 12.1.11.

And AdditionalLightRealtimeShadow() for other lights, although not that this last takes the WS position as it will calculate the position internal, depending on the type of light.

However, I note a difference between unity doing this and me.