How to get point light shadows working in custom URP HLSL shader? 6000.2.0f1

You can see this shadow bug where the (only) two point light shadows are fighting each other:
fnova163

This doesn’t happen if I turn off either point light:
fnova164

Unity 6000.2.0f1 URP with Forward rendering.
Does anyone what I am doing wrong?

It doesn’t happen in Forward+ but Forward+ has different bizarre lighting problems that I don’t want to get into yet

My shader is quite simple to demonstrate. There is very little documentation on Additional Shadows for URP:

Shader "Custom/URP_PointLight_Simple 1"
{
    Properties {}

    SubShader
    {
        Tags { "RenderPipeline" = "UniversalPipeline" }
        Pass
        {
            Name "UniversalForward"
            Tags { "LightMode" = "UniversalForward" }

            HLSLPROGRAM
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"

            #pragma vertex vert
            #pragma fragment frag
            
            #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
            
            Varyings vert (Attributes IN)
            {
                Varyings OUT;
                OUT.positionWS  = TransformObjectToWorld(IN.positionOS.xyz);
                OUT.positionCS  = TransformWorldToHClip(OUT.positionWS);

                return OUT;
            }

            float4 frag (Varyings IN) : SV_Target
            {
                float3 diffuse = float3(0,0,0);
                half shadow = 0;

                int lightCount = GetAdditionalLightsCount();
                for (int i = 0; i < lightCount; i++)
                {
                    Light light  = GetAdditionalLight(i, IN.positionWS);
                    shadow      += AdditionalLightRealtimeShadow(i, IN.positionWS, normalize(light.direction));
                    diffuse     += light.color * light.distanceAttenuation;
                }

                return float4(diffuse  * shadow, 1.0);
            }
            ENDHLSL
        }

       Pass
        {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }
            ZWrite On
            ZTest LEqual
            ColorMask 0
            Cull Off
            HLSLPROGRAM
            #pragma vertex ShadowPassVertex
            #pragma fragment ShadowPassFragment

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
            ENDHLSL
        }
    }
}

Any ideas?

Maximum Additional lights set to 8 with pixel lighting. I’ve tried messing with cascades, shadow distance, hard/soft shadows, etc. I think its strictly a shader issue

You’re shader is missing this important keyword set, or was it stripped for your example?

#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS

In your fragment function, the for-loop doesn’t follow the same convention as URP’s core shaders. I believe the issue could lie with not using the LIGHT_LOOP_BEGIN macro, which is crucial for Forward+ and ensures the that lightIndex is correct between Forward and Forward+.

The correct implementation would be:

uint pixelLightCount = GetAdditionalLightsCount();
LIGHT_LOOP_BEGIN(pixelLightCount)
	Light light = GetAdditionalLight(lightIndex, IN.positionWS);
    light.shadowAttenuation = AdditionalLightRealtimeShadow(lightIndex, IN.positionWS, light.direction);
	shadow += light.shadowAttenuation;

	diffuse += light.color * light.distanceAttenuation;
LIGHT_LOOP_END

I’ve not tested this, but went off tracing a working light loop to the source functions. It may actually be easier to follow URP’s own format, even if that involves Forward+, but at least you can rule out missing some things

Sorry I should have mentioned that I already tried adding those pragmas as well as the LIGHT_LOOP (mentioned here: Unity - Manual: Render additional lights in a shader in URP), they don’t have any effect, so I resorted to the basic for loop (I am using Forward, not Forward+)

I dug through Unity’s code trying their various macros without success.

Edit: Couldn’t figure it out how to fix it using Forward so I switched to Forward+ :person_shrugging: