HDRP getting shadow attenuation

I’m working on a custom “Simple Lit” lighting model for HDRP (12.1.8) and since there is no usable documentation on HDRP’s shaders nor detailed inner workings of the rendering pipeline I’ve decided to investigate this matter on my own and here’s what I’ve found after several days of digging through the HDRP’s shader code base mess:

When talking about Lit material type in forward rendering mode the shadows are calculated in something called a LightLoop which is executed in ShaderPassForward.hlsl by following code:

LightLoopOutput lightLoopOutput;
LightLoop(V, posInput, preLightData, bsdfData, builtinData, featureFlags, lightLoopOutput);

Here’s the include path: Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPassForward.hlsl

The light loop evaluates each light in the scene and calculates Directional, Punctual and Enviromental contributions as well as shadows. To access these shadows you will need to execute the following code in your fragment program:

// Gets the main light in the scene
DirectionalLightData light = _DirectionalLightDatas[0];

float3 positionWS = posInput.positionWS;
float3 lightDirWS = -light.forward;

// Samples the shadow map and returns shadow attenuation value for the current pixel
float shadow = GetDirectionalShadowAttenuation(
    InitShadowContext(),
    posInput.positionSS,
    positionWS,
    GetNormalForShadowBias(bsdfData),
    light.shadowIndex,
    lightDirWS);

However when using the code above, HDRP generates ugly artifacts highlighted red while also generating proper shadow receiving from cube above highlighted green. I believe these “self shadowing” artifacts are caused either by shadow map compression or the PCF soft shadow filtering.

These shadows will also be affected by HDRP’s settings like enable / disable, shadow map resolution or cascades. What HDRP does to hide these artifacts is calculate standard diffuse (N dot L) lighting on top which results in following shadows:

There are still some artifacts visible but usually the intensity of these shadows are around 30% - 20% of this because of ambient lighting in your scene which will hide these ugly patterns, in fact if you look very closely on the HDRP/Lit material you will also see them.

BUT these shadows only come from one directional light so you will have to calculate punctual and other by yourself + you will probably need implement other shadow controlling logic too such as Dimmer, Tint and so on… Luckily for us the DirectionalLightData struct holds all this information:

// Generated from UnityEngine.Rendering.HighDefinition.DirectionalLightData
// PackingRules = Exact
struct DirectionalLightData
{
    float3 positionRWS;
    uint lightLayers;
    float lightDimmer;
    float volumetricLightDimmer;
    float3 forward; // Negate this to get direction from vertex / pixel to light
    int cookieMode;
    float4 cookieScaleOffset;
    float3 right;
    int shadowIndex;
    float3 up;
    int contactShadowIndex;
    float3 color; // Light color tint ofc
    int contactShadowMask;
    float3 shadowTint; // Only necessary when you plan to have colored shadows, but usually this is pure black
    float shadowDimmer; // Important variable to implement
    float volumetricShadowDimmer;
    int nonLightMappedOnly;
    real minRoughness;
    int screenSpaceShadowIndex;
    real4 shadowMaskSelector;
    float2 cascadesBorderFadeScaleBias;
    float diffuseDimmer; // Dimmers for when you decide to calculate your own lighting model like I do
    float specularDimmer;
    float penumbraTint;
    float isRayTracedContactShadow;
    float distanceFromCamera;
    float angularDiameter;
    float flareFalloff;
    float flareCosInner;
    float flareCosOuter;
    float __unused__;
    float3 flareTint;
    float flareSize;
    float3 surfaceTint;
    float4 surfaceTextureScaleOffset;
};

Above I’ve commented some variables that I consider as important to implement. This is what I know so far the forward lighting process is very complicated and basically lies in following scripts ordered by calling hierarchy:

  • ShaderPassForward.hlsl

  • LightLoop.hlsl

  • Lit.hlsl or other lighting type that you will use

  • SurfaceShading.hlsl

I hope this post helps all wariors like me who were trying to dig through the shader mess, gl! :smile:

5 Likes