Cannot Get Addition Lights Shadow Data

Hello. I have a 3D scene with 2 lights, one directional and one spot light. I want to create a shader graph that will draw the shadows for each like a toon shader. This is because when my character jumps I want him to have a shadow directly below him, but when he’s walking around I want him to have a shadow like the rest of the objects. So I am going to make the spot light cast his shadow mimicking the directional light when he is walking around and then when he jumps I will move it directly above him and cast the shadow below him.

So I’ve managed to use shader graph with a custom shader function to get the shadow data from the main light (directional) and apply shadows on my ground here:

But when I add an addition light and try get the data for the additional lights shadows it doesn’t work

Here is what my scene looks like with a lit shader on the ground to prove the spot light is there and casting a shadow:

And the same with the directional light disabled:

Here is my script with my two methods to get the shadows for the lights:

#ifndef SHADOW
#define SHADOW

void MainLightShadow_float(float3 worldPos, out float shadowAtten)
{
#ifdef SHADERGRAPH_PREVIEW
        shadowAtten = 1;
#else     
    float4 shadowCoord = TransformWorldToShadowCoord(worldPos);
 
    ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
    float shadowStrength = GetMainLightShadowStrength();
    shadowAtten = SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowSamplingData, shadowStrength, false);
#endif
}

void AdditionalLightShadow_float(float3 worldPos, out float shadowAtten)
{
#ifdef SHADERGRAPH_PREVIEW
    shadowAtten = 1;
#else
    shadowAtten = 0;
    float4 shadowCoord = TransformWorldToShadowCoord(worldPos);
    
    int additionalLightCount = GetAdditionalLightsCount();
    for (uint i = 0; i < additionalLightCount; i++)
    {
        ShadowSamplingData shadowSamplingData = GetAdditionalLightShadowSamplingData(i);
        float shadowStrength = GetAdditionalLightShadowStrenth(i);
        float additionalShadowAtten = SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_AdditionalLightsShadowmapTexture), shadowSamplingData, shadowStrength, false);
        
        if (additionalShadowAtten < shadowAtten)
        {
            shadowAtten = additionalShadowAtten;
        }
    }
#endif
}

#endif

I’ve also tried these two methods with no luck:

        Light additionalLight = GetAdditionalLight(i, worldPos);
        half additionalShadowAtten = AdditionalLightRealtimeShadow(i, worldPos, additionalLight.direction);
        
        Light light = GetAdditionalLight(i, worldPos, half4(1, 1, 1, 1));        
        float additionalShadowAtten = light.shadowAttenuation;

I must be missing something, can someone let me know what I need in my AdditionalLightShadow function to make it behave like the one I have for the main light?

Thanks,
Sam

The new Production Ready Shaders sample set (imported from the Package Manager) contains some examples of shaders that are doing custom lighting / toon shading in Shader Graph. Have you taken a look at it yet? It uses a custom node with a code shader - similar to what you have, but may provide the answer you’re looking for.

I personally like to use these custom nodes: GitHub - Cyanilux/URP_ShaderGraphCustomLighting: Some custom lighting functions/sub-graphs for Shader Graph, Universal Render Pipeline

Hey Ben. I have downloaded the samples and had a look in the graphs at them, I couldn’t find one that was getting the value of the addition light shadows but I will have another dig. I didn’t know about the sample scene, it’s very cool and I learnt a lot from it. Sadly it doesn’t do anything with toon shaders.

I have seen this. Just had another play with it and thought this would help

void AdditionalLightShadow_float(float3 worldPos, half4 shadowMask, out float shadowAtten)
{
#ifdef SHADERGRAPH_PREVIEW
    shadowAtten = 1;
#else
    shadowAtten = 0;
    float4 shadowCoord = TransformWorldToShadowCoord(worldPos);
    
    int additionalLightCount = GetAdditionalLightsCount();
    for (uint i = 0; i < additionalLightCount; i++)
    {
        Light additionalLight = GetAdditionalLight(i, worldPos, shadowMask);
        half additionalShadowAtten = AdditionalLightRealtimeShadow(i, worldPos, additionalLight.direction);

        if (additionalShadowAtten > shadowAtten)
        {
            shadowAtten = additionalShadowAtten;
        }
    }
#endif
}

This screen shot I have turned off the main light shadows and only trying to cast shadows on the additional lights, you can see the plane in the background has got a shadow

Seems if I jump off the plane I am on the shadow appears as well but I am not getting the shadow under the character, I’m not sure why.

You’re right. I’m sorry, I told you the wrong sample. The example toon shader is actually in the Feature Examples sample. It looks like this:


It’s on the far right side of the line of examples in the URPFeatureExamples scene.

1 Like