浏览代码

Changed shadow biasing. Biasing can now use normal and light vector information to avoid artifacts.

Added:
- normal+view biasing
- light view only biasing
- per sample biasing for wide PCF filters
- corner light leaking mitigation
- defines to control what type of biasing should be enabled
- a few new UI controls in the additionalshadowdata component

Removed previous biasing controls. They won't have any effect anymore.
/main
uygar 7 年前
当前提交
c8556633
共有 16 个文件被更改,包括 491 次插入300 次删除
  1. 45
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/Shadow.hlsl
  2. 498
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  3. 140
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl
  4. 8
      ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowTexFetch.hlsl
  5. 12
      ScriptableRenderPipeline/Core/CoreRP/Shadow/AdditionalShadowData.cs
  6. 11
      ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs
  7. 6
      ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs
  8. 12
      ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs.hlsl
  9. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute
  10. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightEvaluation.hlsl
  11. 15
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Shadow.hlsl
  12. 4
      TestbedPipelines/Fptl/LightingTemplate.hlsl
  13. 9
      TestbedPipelines/Fptl/Shadow.hlsl
  14. 6
      TestbedPipelines/OnTileDeferredPipeline/Shaders/LightingTemplate.hlsl
  15. 9
      TestbedPipelines/OnTileDeferredPipeline/Shaders/Shadow.hlsl
  16. 8
      TestbedPipelines/OnTileDeferredPipeline/Shaders/UnityStandardForwardMobile.cginc

45
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/Shadow.hlsl


*/
/* Default values for optional defines:
#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0 // Dynamic indexing only works on >= sm 5.1
#define SHADOW_OPTIMIZE_REGISTER_USAGE 0 // Redefine this as 1 in your ShadowContext.hlsl to optimize for register usage over instruction count
// #define SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL // Enable custom implementations of GetPunctualShadowAttenuation. If not defined, a default implementation will be used.
// #define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL // Enable custom implementations of GetDirectionalShadowAttenuation. If not defined, a default implementation will be used.
#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0 // Dynamic indexing only works on >= sm 5.1
#define SHADOW_OPTIMIZE_REGISTER_USAGE 0 // Redefine this as 1 in your ShadowContext.hlsl to optimize for register usage over instruction count
#define SHADOW_USE_VIEW_BIAS_SCALING 0 // Enable view bias scaling to mitigate light leaking across edges. Uses the light vector if SHADOW_USE_ONLY_VIEW_BASED_BIASING is defined, otherwise uses the normal.
#define SHADOW_USE_ONLY_VIEW_BASED_BIASING 0 // Enable only light view vector based biasing. If undefined, biasing will be based on the normal and calling code must provide a valid normal.
#define SHADOW_USE_SAMPLE_BIASING 0 // Enable per sample biasing for wide multi-tap PCF filters. Incompatible with SHADOW_USE_ONLY_VIEW_BASED_BIASING.
// #define SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL // Enable custom implementations of GetPunctualShadowAttenuation. If not defined, a default implementation will be used.
// #define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL // Enable custom implementations of GetDirectionalShadowAttenuation. If not defined, a default implementation will be used.
#define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0
# define SHADOW_SUPPORTS_DYNAMIC_INDEXING 0
#define SHADOW_OPTIMIZE_REGISTER_USAGE 0
# define SHADOW_OPTIMIZE_REGISTER_USAGE 0
#endif
#ifndef SHADOW_USE_VIEW_BIAS_SCALING
# define SHADOW_USE_VIEW_BIAS_SCALING 0
#endif
#ifndef SHADOW_USE_SAMPLE_BIAS
# define SHADOW_USE_SAMPLE_BIAS 0
#endif
#ifndef SHADOW_USE_SAMPLE_BIAS
# define SHADOW_USE_SAMPLE_BIAS 0
#endif
#if SHADOW_USE_ONLY_VIEW_BASED_BIASING != 0
# if SHADOW_USE_SAMPLE_BIASING != 0
# pragma message "Shadows: SHADOW_USE_SAMPLE_BIASING was enabled together with SHADOW_USE_ONLY_VIEW_BASED_BIASING. Sample biasing requires the normal. Disabling SHADOW_USE_SAMPLE_BIASING again."
# undef SHADOW_USE_SAMPLE_BIASING
# define SHADOW_USE_SAMPLE_BIASING 0
# endif
#endif
#include "CoreRP/Shadow/ShadowBase.cs.hlsl" // ShadowData definition, auto generated (don't modify)

}
// shadow sampling prototypes
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L );
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L, real2 positionSS );
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L, real L_dist );
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L, real L_dist, real2 positionSS );
// shadow sampling prototypes with screenspace info
real GetDirectionalShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L );

#include "ShadowAlgorithms.hlsl" // engine default algorithms (don't modify)
#ifndef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L )
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L, real L_dist )
return EvalShadow_PunctualDepth(shadowContext, positionWS, normalWS, shadowDataIndex, L);
return EvalShadow_PunctualDepth( shadowContext, positionWS, normalWS, shadowDataIndex, L, L_dist );
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real4 L, real2 positionSS )
real GetPunctualShadowAttenuation( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int shadowDataIndex, real3 L, real L_dist, real2 positionSS )
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L, L_dist );
}
#endif

498
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


// There are two variants provided, one takes the texture and sampler explicitly so they can be statically passed in.
// The variant without resource parameters dynamically accesses the texture when sampling.
// Helper function to offset depth based on the surface normal and light direction.
// If the light hits the surface perpendicularly there will be no offset.
real3 EvalShadow_NormalBias( real3 normalWS, real NoL, real2 texelSize, real normalBias )
{
return max( texelSize.x, texelSize.y ) * normalBias * (1.0 - NoL) * normalWS;
}
real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real3 posNDC, bool clampToRect )
real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real3 posNDC, bool clampToRect, bool perspProj )
posCS.z -= sd.bias * posCS.w;
posNDC = posCS.xyz / posCS.w;
posNDC = perspProj ? (posCS.xyz / posCS.w) : posCS.xyz;
real3 posTC = float3( posNDC.xy * 0.5 + 0.5, posNDC.z );
real3 posTC = real3( posNDC.xy * 0.5 + 0.5, posNDC.z );
posTC.xy = clampToRect ? clamp( posTC.xy, sd.texelSizeRcp.zw*0.5, 1.0.xx - sd.texelSizeRcp.zw*0.5 ) : posTC.xy;
posTC.xy = posTC.xy * sd.scaleOffset.xy + sd.scaleOffset.zw;

real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS )
real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, bool perspProj )
return EvalShadow_GetTexcoords( sd, positionWS, ndc, false );
return EvalShadow_GetTexcoords( sd, positionWS, ndc, false, perspProj );
uint2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC )
uint2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj )
real2 posNDC = posCS.xy / posCS.w;
real2 posNDC = perspProj ? (posCS.xy / posCS.w) : posCS.xy;
// calc TCs
real2 posTC = posNDC * 0.5 + 0.5;
closestSampleNDC = (floor(posTC * sd.textureSize.zw) + 0.5) * sd.texelSizeRcp.zw * 2.0 - 1.0.xx;

//
// Biasing functions
//
// helper function to get the world texel size
real EvalShadow_WorldTexelSize( ShadowData sd, float L_dist, bool perspProj )
{
return perspProj ? (sd.viewBias.w * L_dist) : sd.viewBias.w;
}
// used to scale down view biases to mitigate light leaking across shadowed corners
#if SHADOW_USE_VIEW_BIAS_SCALING != 0
real EvalShadow_ReceiverBiasWeightFlag( float flag )
{
return (asint( flag ) & 2) ? 1.0 : 0.0;
}
real3 EvalShadow_ReceiverBiasWeightPos( real3 positionWS, real3 normalWS, real3 L, real worldTexelSize )
{
#if SHADOW_USE_ONLY_VIEW_BASED_BIASING != 0
return positionWS + L * worldTexelSize;
#else
return positionWS + normalWS * worldTexelSize;
#endif
}
real EvalShadow_ReceiverBiasWeight( ShadowContext shadowContext, uint shadowAlgorithm, ShadowData sd, uint texIdx, uint sampIdx, real3 positionWS, real3 normalWS, real3 L, real L_dist, real slice, bool perspProj )
{
real weight = 1.0;
[branch]
if( shadowAlgorithm <= GPUSHADOWALGORITHM_PCF_TENT_7X7 )
{
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ) );
real3 tcs = EvalShadow_GetTexcoords( sd, pos, perspProj );
weight = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, tcs, slice ).x;
}
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) );
}
real EvalShadow_ReceiverBiasWeight( ShadowData sd, Texture2DArray tex, SamplerComparisonState samp, real3 positionWS, real3 normalWS, real3 L, real L_dist, real slice, bool perspProj )
{
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ) );
return lerp( 1.0, SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, samp, EvalShadow_GetTexcoords( sd, pos, perspProj ), slice ).x, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) );
}
real EvalShadow_ReceiverBiasWeight( ShadowData sd, Texture2DArray tex, SamplerState samp, real3 positionWS, real3 normalWS, real3 L, real L_dist, real slice, bool perspProj )
{
// only used by PCF filters
return 1.0;
}
#else // SHADOW_USE_VIEW_BIAS_SCALING != 0
real EvalShadow_ReceiverBiasWeight( ShadowContext shadowContext, uint shadowAlgorithm, ShadowData sd, uint texIdx, uint sampIdx, real3 positionWS, real3 normalWS, real3 L, real L_dist, real slice, bool perspProj ) { return 1.0; }
real EvalShadow_ReceiverBiasWeight( ShadowData sd, Texture2DArray tex, SamplerComparisonState samp, real3 positionWS, real3 normalWS, real3 L, real L_dist, real slice, bool perspProj ) { return 1.0; }
real EvalShadow_ReceiverBiasWeight(ShadowData sd, Texture2DArray tex, SamplerState samp, real3 positionWS, real3 normalWS, real3 L, real L_dist, real slice, bool perspProj) { return 1.0; }
#endif // SHADOW_USE_VIEW_BIAS_SCALING != 0
// receiver bias either using the normal to weight normal and view biases, or just light view biasing
float3 EvalShadow_ReceiverBias( ShadowData sd, float3 positionWS, float3 normalWS, float3 L, float L_dist, float lightviewBiasWeight, bool perspProj )
{
#if SHADOW_USE_ONLY_VIEW_BASED_BIASING != 0 // only light vector based biasing
float viewBiasScale = sd.viewBias.z;
return positionWS + L * viewBiasScale * lightviewBiasWeight * EvalShadow_WorldTexelSize( sd, L_dist, perspProj );
#else // biasing based on the angle between the normal and the light vector
float viewBiasMin = sd.viewBias.x;
float viewBiasMax = sd.viewBias.y;
float viewBiasScale = sd.viewBias.z;
float nrmlBiasMin = sd.nrmlBias.x;
float nrmlBiasMax = sd.nrmlBias.y;
float nrmlBiasScale = sd.nrmlBias.z;
float NdotL = saturate( dot( normalWS, L ) );
float sine = sqrt( saturate( 1.0 - NdotL * NdotL ) );
float tangent = abs( NdotL ) > 0.0 ? (sine / NdotL) : 0.0;
sine = clamp( sine * nrmlBiasScale, nrmlBiasMin, nrmlBiasMax );
tangent = clamp( tangent * viewBiasScale * lightviewBiasWeight, viewBiasMin, viewBiasMax );
float3 view_bias = L * tangent;
float3 normal_bias = normalWS * sine;
return positionWS + (normal_bias + view_bias) * EvalShadow_WorldTexelSize( sd, L_dist, perspProj );
#endif
}
// sample bias used by wide PCF filters to offset individual taps
#if SHADOW_USE_SAMPLE_BIASING != 0
real EvalShadow_SampleBiasFlag( float flag )
{
return (asint( flag ) & 1) ? 1.0 : 0.0;
}
float2 EvalShadow_SampleBias_Persp( ShadowData sd, float3 positionWS, float3 normalWS, float3 tcs )
{
float3 e1, e2;
if( abs( normalWS.z ) > 0.05 )
{
e1 = float3( 1.0, 0.0, -normalWS.x / normalWS.z );
e2 = float3( 0.0, 1.0, -normalWS.y / normalWS.z );
}
else if( abs( normalWS.y ) > 0.05 )
{
e1 = float3( 1.0, -normalWS.x / normalWS.y, 0.0 );
e2 = float3( 0.0, -normalWS.z / normalWS.y, 1.0 );
}
else
{
e1 = float3( -normalWS.y / normalWS.x, 1.0, 0.0 );
e2 = float3( -normalWS.z / normalWS.x, 0.0, 1.0 );
}
float4 p1 = mul( float4( positionWS + e1, 1.0 ), sd.worldToShadow );
float4 p2 = mul( float4( positionWS + e2, 1.0 ), sd.worldToShadow );
p1.xyz /= p1.w;
p2.xyz /= p2.w;
p1.xyz = float3( p1.xy * 0.5 + 0.5, p1.z );
p2.xyz = float3( p2.xy * 0.5 + 0.5, p2.z );
p1.xy = p1.xy * sd.scaleOffset.xy + sd.scaleOffset.zw;
p2.xy = p2.xy * sd.scaleOffset.xy + sd.scaleOffset.zw;
float3 nrm = cross( p1.xyz - tcs, p2.xyz - tcs );
nrm.xy /= -nrm.z;
return all( isfinite( nrm.xy ) ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
}
float2 EvalShadow_SampleBias_Ortho( ShadowData sd, float3 normalWS )
{
float3 nrm = mul( (float3x3) sd.shadowToWorld, normalWS );
nrm.x *= sd.scaleOffset.y;
nrm.y *= sd.scaleOffset.x;
nrm.z *= sd.scaleOffset.x * sd.scaleOffset.y;
nrm.xy /= -nrm.z;
return all( isfinite( nrm.xy ) ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
}
#else // SHADOW_USE_SAMPLE_BIASING != 0
float2 EvalShadow_SampleBias_Persp( ShadowData sd, float3 positionWS, float3 normalWS, float3 tcs ) { return 0.0.xx; }
float2 EvalShadow_SampleBias_Ortho( ShadowData sd, float3 normalWS ) { return 0.0.xx; }
#endif // SHADOW_USE_SAMPLE_BIASING != 0
//
real EvalShadow_PointDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L )
real EvalShadow_PointDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist )
ShadowData sd = shadowContext.shadowDatas[index];
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
real3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
// load the right shadow data for the current face
sd = shadowContext.shadowDatas[index + faceIndex];
uint payloadOffset = GetPayloadOffset( sd );
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
ShadowData sd = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1];
// sample the texture according to the given algorithm
// get the texture
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
// bias the world position
float recvBiasWeight = EvalShadow_ReceiverBiasWeight( shadowContext, shadowAlgorithm, sd, texIdx, sampIdx, positionWS, normalWS, L, L_dist, slice, true );
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true );
// get shadowmap texcoords
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, true );
// get the per sample bias
real2 sampleBias = EvalShadow_SampleBias_Persp( sd, positionWS, normalWS, posTC );
// sample the texture according to the given algorithm
uint payloadOffset = GetPayloadOffset( sd );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, texIdx, sampIdx );
#define EvalShadow_PointDepth_( _samplerType ) \
real EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \
{ \
ShadowData sd = shadowContext.shadowDatas[index]; \
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
real3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
/* load the right shadow data for the current face */ \
sd = shadowContext.shadowDatas[index + faceIndex]; \
uint payloadOffset = GetPayloadOffset( sd ); \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
#define EvalShadow_PointDepth_( _samplerType ) \
real EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist ) \
{ \
ShadowData sd = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1]; \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
/* bias the world position */ \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, L_dist, slice, true ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true ); \
/* get shadowmap texcoords */ \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, true ); \
/* get the per sample bias */ \
real2 sampleBias = EvalShadow_SampleBias_Persp( sd, positionWS, normalWS, posTC ); \
/* sample the texture */ \
uint payloadOffset = GetPayloadOffset( sd ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, tex, samp ); \
}
EvalShadow_PointDepth_( SamplerComparisonState )
EvalShadow_PointDepth_( SamplerState )

// Spot shadows
//
real EvalShadow_SpotDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L )
real EvalShadow_SpotDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist )
uint payloadOffset = GetPayloadOffset( sd );
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
real slice;
float slice;
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
// bias the world position
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( shadowContext, shadowAlgorithm, sd, texIdx, sampIdx, positionWS, normalWS, L, L_dist, slice, true );
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true );
// get shadowmap texcoords
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, true );
// get the per sample bias
real2 sampleBias = EvalShadow_SampleBias_Persp( sd, positionWS, normalWS, posTC );
// sample the texture according to the given algorithm
uint payloadOffset = GetPayloadOffset( sd );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, texIdx, sampIdx );
#define EvalShadow_SpotDepth_( _samplerType ) \
real EvalShadow_SpotDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \
{ \
/* load the right shadow data for the current face */ \
ShadowData sd = shadowContext.shadowDatas[index]; \
uint payloadOffset = GetPayloadOffset( sd ); \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
#define EvalShadow_SpotDepth_( _samplerType ) \
real EvalShadow_SpotDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist ) \
{ \
/* load the right shadow data for the current face */ \
ShadowData sd = shadowContext.shadowDatas[index]; \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
/* bias the world position */ \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, L_dist, slice, true ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true ); \
/* get shadowmap texcoords */ \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, true ); \
/* get the per sample bias */ \
real2 sampleBias = EvalShadow_SampleBias_Persp( sd, positionWS, normalWS, posTC ); \
/* sample the texture */ \
uint payloadOffset = GetPayloadOffset( sd ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, tex, samp ); \
}
EvalShadow_SpotDepth_( SamplerComparisonState )
EvalShadow_SpotDepth_( SamplerState )

// Punctual shadows for Point and Spot
//
real EvalShadow_PunctualDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L )
real EvalShadow_PunctualDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist )
// load the right shadow data for the current face
int faceIndex = 0;
UnpackShadowType( sd.shadowType, shadowType );
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
// load the right shadow data for the current face
{
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
real3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
}
else
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
sd = shadowContext.shadowDatas[index + faceIndex];
uint payloadOffset = GetPayloadOffset( sd );
// get shadowmap texcoords
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
// sample the texture according to the given algorithm
sd = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1];
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
// bias the world position
float recvBiasWeight = EvalShadow_ReceiverBiasWeight( shadowContext, shadowAlgorithm, sd, texIdx, sampIdx, positionWS, normalWS, L, L_dist, slice, true );
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true );
// get shadowmap texcoords
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, true );
// get the per sample bias
real2 sampleBias = EvalShadow_SampleBias_Persp( sd, positionWS, normalWS, posTC );
// sample the texture according to the given algorithm
uint payloadOffset = GetPayloadOffset( sd );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, texIdx, sampIdx );
#define EvalShadow_PunctualDepth_( _samplerType ) \
real EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \
{ \
/* load the right shadow data for the current face */ \
int faceIndex = 0; \
/* get the shadow type */ \
ShadowData sd = shadowContext.shadowDatas[index]; \
uint shadowType; \
UnpackShadowType( sd.shadowType, shadowType ); \
\
[branch] \
if( shadowType == GPUSHADOWTYPE_POINT ) \
{ \
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
real3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
} \
else \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
\
sd = shadowContext.shadowDatas[index + faceIndex]; \
uint payloadOffset = GetPayloadOffset( sd ); \
/* get shadowmap texcoords */ \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \
#define EvalShadow_PunctualDepth_( _samplerType ) \
real EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist ) \
{ \
int faceIndex = 0; \
/* get the shadow type */ \
ShadowData sd = shadowContext.shadowDatas[index]; \
uint shadowType; \
UnpackShadowType( sd.shadowType, shadowType ); \
\
/* load the right shadow data for the current face */ \
[branch] \
if( shadowType == GPUSHADOWTYPE_POINT ) \
sd = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1]; \
\
float slice; \
UnpackShadowmapId( sd.id, slice ); \
/* bias the world position */ \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, L_dist, slice, true ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true ); \
/* get shadowmap texcoords */ \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, true ); \
/* get the per sample bias */ \
real2 sampleBias = EvalShadow_SampleBias_Persp( sd, positionWS, normalWS, posTC ); \
/* sample the texture */ \
uint payloadOffset = GetPayloadOffset( sd ); \
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, tex, samp ); \
}
EvalShadow_PunctualDepth_( SamplerComparisonState )
EvalShadow_PunctualDepth_( SamplerState )

real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// sample the texture
uint texIdx, sampIdx;
float slice;
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice );
uint shadowType, shadowAlgorithm;
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias );
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( shadowContext, shadowAlgorithm, sd, texIdx, sampIdx, positionWS, normalWS, L, 1.0, slice, false );
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, 1.0, recvBiasWeight, false );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true, false );
// sample the texture
uint texIdx, sampIdx;
float slice;
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice );
uint shadowType, shadowAlgorithm;
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
real shadow1 = 1.0;
// evaluate the first cascade
real2 sampleBias = EvalShadow_SampleBias_Ortho( sd, normalWS );
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, texIdx, sampIdx );
real shadow1 = 1.0;
shadowSplitIndex++;
if( shadowSplitIndex < kMaxShadowCascades )

if( alpha > 0.0 )
{
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias );
posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, false );
positionWS = EvalShadow_ReceiverBias( sd, orig_pos, normalWS, L, 1.0, recvBiasWeight, false );
posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, false, false );
sampleBias = EvalShadow_SampleBias_Ortho( sd, normalWS );
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, texIdx, sampIdx );
}
}
shadow = lerp( shadow, shadow1, alpha );

real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
\
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
\
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, 1.0, slice, false ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, 1.0, recvBiasWeight, false ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
alpha = cascDot > 0.0 ? alpha : lerp( alpha, 0.0, saturate( -cascDot * 4.0 ) ); \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
\
/* sample the texture */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
\
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
real shadow1 = 1.0; \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true, false ); \
/* evalute the first cascade */ \
real2 sampleBias = EvalShadow_SampleBias_Ortho( sd, normalWS ); \
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
real shadow1 = 1.0; \
\
shadowSplitIndex++; \
if( shadowSplitIndex < kMaxShadowCascades ) \

if( alpha > 0.0 ) \
{ \
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, false ); \
positionWS = EvalShadow_ReceiverBias( sd, orig_pos, normalWS, L, 1.0, recvBiasWeight, false ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, false, false ); \
sampleBias = EvalShadow_SampleBias_Ortho( sd, normalWS ); \
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
shadow1 = SampleShadow_SelectAlgorithm( shadowContext, sd, orig_payloadOffset, posTC, sampleBias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
} \
} \
shadow = lerp( shadow, shadow1, alpha ); \

real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border );
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// get texture description
uint texIdx, sampIdx;
float slice;
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice );
uint shadowType, shadowAlgorithm;
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias );
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( shadowContext, shadowAlgorithm, sd, texIdx, sampIdx, positionWS, normalWS, L, 1.0, slice, false );
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, 1.0, recvBiasWeight, false );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true );
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true, false );
int nextSplit = min( shadowSplitIndex+1, kMaxShadowCascades-1 );
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz;

if( shadowSplitIndex < nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) )
{
sd = shadowContext.shadowDatas[index + 1 + nextSplit];
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[nextSplit] * sd.texelSizeRcp.zw, sd.normalBias );
posTC = EvalShadow_GetTexcoords( sd, positionWS );
positionWS = EvalShadow_ReceiverBias( sd, orig_pos, normalWS, L, 1.0, recvBiasWeight, false );
posTC = EvalShadow_GetTexcoords( sd, positionWS, false );
uint texIdx, sampIdx;
float slice;
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice );
uint shadowType, shadowAlgorithm;
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
real2 sampleBias = EvalShadow_SampleBias_Ortho( sd, normalWS );
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithm, texIdx, sampIdx );
return shadowSplitIndex < (kMaxShadowCascades-1) ? shadow : lerp( shadow, 1.0, alpha );
}

real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \
\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
\
/* get texture description */ \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
\
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[shadowSplitIndex] * sd.texelSizeRcp.zw, sd.normalBias ); \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, 1.0, slice, false ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, 1.0, recvBiasWeight, false ); \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true ); \
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS, posNDC, true, false ); \
\
int nextSplit = min( shadowSplitIndex+1, kMaxShadowCascades-1 ); \
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \

if( shadowSplitIndex != nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) ) \
{ \
sd = shadowContext.shadowDatas[index + 1 + nextSplit]; \
positionWS = orig_pos + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), scales[nextSplit] * sd.texelSizeRcp.zw, sd.normalBias ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
positionWS = EvalShadow_ReceiverBias( sd, orig_pos, normalWS, L, 1.0, recvBiasWeight, false ); \
posTC = EvalShadow_GetTexcoords( sd, positionWS, false ); \
float slice; \
UnpackShadowmapId( sd.id, slice ); \
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
real2 sampleBias = EvalShadow_SampleBias_Ortho( sd, normalWS ); \
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sampleBias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \
return shadowSplitIndex < (kMaxShadowCascades-1) ? shadow : lerp( shadow, 1.0, alpha ); \
} \
\

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
uint texIdx, sampIdx;

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
float slice;

ShadowData sd = shadowContext.shadowDatas[index];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
uint texIdx, sampIdx;

ShadowData sd = shadowContext.shadowDatas[index];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
float slice;

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
uint texIdx, sampIdx;

sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true );
// load the texel
float slice;

ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false );
// load the texel
uint texIdx, sampIdx;

ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
real4 closestNDC = { 0,0,0,1 };
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy );
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false );
// load the texel
uint texIdx, sampIdx;

140
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowSampling.hlsl


//
// 1 tap PCF sampling
//
real SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, real bias, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, uint texIdx, uint sampIdx )
{
real depthBias = asfloat( shadowContext.payloads[payloadOffset].x );
payloadOffset++;

return SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, tcs, slice ).x;
}
real SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, real bias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_1tap( ShadowContext shadowContext, inout uint payloadOffset, real3 tcs, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
real depthBias = asfloat( shadowContext.payloads[payloadOffset].x );
payloadOffset++;

//
// 3x3 tent PCF sampling (4 taps)
//
real SampleShadow_PCF_Tent_3x3( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_Tent_3x3( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, real2 sampleBias, uint slice, uint texIdx, uint sampIdx )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

SampleShadow_ComputeSamples_Tent_3x3(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
[loop] for (int i = 0; i < 4; i++)
{
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z + dot( fetchesUV[i].xy - coord.xy, sampleBias ) ), slice ).x;
real SampleShadow_PCF_Tent_3x3(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_Tent_3x3(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, real2 sampleBias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

SampleShadow_ComputeSamples_Tent_3x3(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
for (int i = 0; i < 4; i++)
{
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z + dot( fetchesUV[i].xy - coord.xy, sampleBias ) ), slice ).x;
}
return shadow;
}

//
real SampleShadow_PCF_Tent_5x5( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_Tent_5x5( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, real2 sampleBias, uint slice, uint texIdx, uint sampIdx )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4( texelSizeRcp.xy, rcp( texelSizeRcp.xy ) );
// add the depth bias
coord.z += depthBias;

real2 fetchesUV[9];
SampleShadow_ComputeSamples_Tent_5x5(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
SampleShadow_ComputeSamples_Tent_5x5( shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV );
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z + dot( fetchesUV[i].xy - coord.xy, sampleBias ) ), slice ).x;
real SampleShadow_PCF_Tent_5x5(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_Tent_5x5(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, real2 sampleBias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4( texelSizeRcp.xy, rcp(texelSizeRcp.xy ) );
// add the depth bias
coord.z += depthBias;

real2 fetchesUV[9];
SampleShadow_ComputeSamples_Tent_5x5(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
SampleShadow_ComputeSamples_Tent_5x5( shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV );
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z + dot( fetchesUV[i].xy - coord.xy, sampleBias ) ), slice ).x;
}
return shadow;

// 7x7 tent PCF sampling (16 taps)
//
real SampleShadow_PCF_Tent_7x7( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_Tent_7x7( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, real2 sampleBias, uint slice, uint texIdx, uint sampIdx )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4( texelSizeRcp.xy, rcp(texelSizeRcp.xy ) );
// add the depth bias
coord.z += depthBias;

real2 fetchesUV[16];
SampleShadow_ComputeSamples_Tent_7x7(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
SampleShadow_ComputeSamples_Tent_7x7( shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV );
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( fetchesUV[i].xy, coord.z + dot( fetchesUV[i].xy - coord.xy, sampleBias ) ), slice ).x;
real SampleShadow_PCF_Tent_7x7(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_Tent_7x7(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 coord, real2 sampleBias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

real4 shadowMapTexture_TexelSize = real4(texelSizeRcp.xy, rcp(texelSizeRcp.xy));
real4 shadowMapTexture_TexelSize = real4( texelSizeRcp.xy, rcp( texelSizeRcp.xy ) );
// add the depth bias
coord.z += depthBias;

real2 fetchesUV[16];
SampleShadow_ComputeSamples_Tent_7x7(shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV);
SampleShadow_ComputeSamples_Tent_7x7( shadowMapTexture_TexelSize, coord.xy, fetchesWeights, fetchesUV );
// the loops are only there to prevent the compiler form coalescing all 16 texture fetches which increases register usage
shadow += fetchesWeights[ 0] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 0].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 1] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 1].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 2] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 2].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 3] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 3].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 0] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 0].xy, coord.z + dot( fetchesUV[ 0].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 1] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 1].xy, coord.z + dot( fetchesUV[ 1].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 2] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 2].xy, coord.z + dot( fetchesUV[ 2].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 3] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 3].xy, coord.z + dot( fetchesUV[ 3].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 4] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 4].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 5] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 5].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 6] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 6].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 7] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 7].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 4] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 4].xy, coord.z + dot( fetchesUV[ 4].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 5] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 5].xy, coord.z + dot( fetchesUV[ 5].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 6] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 6].xy, coord.z + dot( fetchesUV[ 6].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 7] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 7].xy, coord.z + dot( fetchesUV[ 7].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 8] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 8].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 9] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 9].xy, coord.z ), slice ).x;
shadow += fetchesWeights[10] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[10].xy, coord.z ), slice ).x;
shadow += fetchesWeights[11] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[11].xy, coord.z ), slice ).x;
shadow += fetchesWeights[ 8] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 8].xy, coord.z + dot( fetchesUV[ 8].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[ 9] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[ 9].xy, coord.z + dot( fetchesUV[ 9].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[10] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[10].xy, coord.z + dot( fetchesUV[10].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[11] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[11].xy, coord.z + dot( fetchesUV[11].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[12] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[12].xy, coord.z ), slice ).x;
shadow += fetchesWeights[13] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[13].xy, coord.z ), slice ).x;
shadow += fetchesWeights[14] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[14].xy, coord.z ), slice ).x;
shadow += fetchesWeights[15] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[15].xy, coord.z ), slice ).x;
shadow += fetchesWeights[12] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[12].xy, coord.z + dot( fetchesUV[12].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[13] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[13].xy, coord.z + dot( fetchesUV[13].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[14] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[14].xy, coord.z + dot( fetchesUV[14].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[15] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[15].xy, coord.z + dot( fetchesUV[15].xy - coord.xy, sampleBias ) ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z ), slice ).x;
shadow += fetchesWeights[i] * SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( fetchesUV[i].xy, coord.z + dot( fetchesUV[i].xy - coord.xy, sampleBias ) ), slice ).x;
}
#endif
return shadow;

// 9 tap adaptive PCF sampling
//
real SampleShadow_PCF_9tap_Adaptive( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 tcs, real bias, uint slice, uint texIdx, uint sampIdx )
real SampleShadow_PCF_9tap_Adaptive( ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 tcs, real2 sampleBias, uint slice, uint texIdx, uint sampIdx )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

real4 vShadow3x3PCFTerms3 = real4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0, 0.0 );
real4 v20Taps;
v20Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
v20Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z + dot( vShadow3x3PCFTerms1.xy, sampleBias ) ), slice ).x; // 1 1
v20Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z + dot( vShadow3x3PCFTerms1.zy, sampleBias ) ), slice ).x; // -1 1
v20Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z + dot( vShadow3x3PCFTerms1.xw, sampleBias ) ), slice ).x; // 1 -1
v20Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z + dot( vShadow3x3PCFTerms1.zw, sampleBias ) ), slice ).x; // -1 -1
real flSum = dot( v20Taps.xyzw, real4( 0.25, 0.25, 0.25, 0.25 ) );
// fully in light or shadow? -> bail
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )

flSum *= vShadow3x3PCFTerms0.x * 4.0;
real4 v33Taps;
v33Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
v33Taps.x = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z + dot( vShadow3x3PCFTerms2.xz, sampleBias ) ), slice ).x; // 1 0
v33Taps.y = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z + dot( vShadow3x3PCFTerms3.xz, sampleBias ) ), slice ).x; // -1 0
v33Taps.z = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z + dot( vShadow3x3PCFTerms3.zy, sampleBias ) ), slice ).x; // 0 -1
v33Taps.w = SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, real3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z + dot( vShadow3x3PCFTerms2.zy, sampleBias ) ), slice ).x; // 0 1
flSum += dot( v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy );
flSum += SampleCompShadow_T2DA( shadowContext, texIdx, sampIdx, tcs, slice ).x * vShadow3x3PCFTerms0.z;

real SampleShadow_PCF_9tap_Adaptive(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 tcs, real bias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_PCF_9tap_Adaptive(ShadowContext shadowContext, inout uint payloadOffset, real4 texelSizeRcp, real3 tcs, real2 sampleBias, uint slice, Texture2DArray tex, SamplerComparisonState compSamp )
{
real2 params = asfloat( shadowContext.payloads[payloadOffset].xy );
real depthBias = params.x;

real4 vShadow3x3PCFTerms3 = real4(-texelSizeRcp.x, -texelSizeRcp.y, 0.0, 0.0);
real4 v20Taps;
v20Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z ), slice ).x; // 1 1
v20Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z ), slice ).x; // -1 1
v20Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z ), slice ).x; // 1 -1
v20Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z ), slice ).x; // -1 -1
v20Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.xy, tcs.z + dot( vShadow3x3PCFTerms1.xy, sampleBias ) ), slice ).x; // 1 1
v20Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.zy, tcs.z + dot( vShadow3x3PCFTerms1.zy, sampleBias ) ), slice ).x; // -1 1
v20Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.xw, tcs.z + dot( vShadow3x3PCFTerms1.xw, sampleBias ) ), slice ).x; // 1 -1
v20Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms1.zw, tcs.z + dot( vShadow3x3PCFTerms1.zw, sampleBias ) ), slice ).x; // -1 -1
real flSum = dot( v20Taps.xyzw, real4( 0.25, 0.25, 0.25, 0.25 ) );
// fully in light or shadow? -> bail
if( ( flSum == 0.0 ) || ( flSum == 1.0 ) )

flSum *= vShadow3x3PCFTerms0.x * 4.0;
real4 v33Taps;
v33Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z ), slice ).x; // 1 0
v33Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z ), slice ).x; // -1 0
v33Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z ), slice ).x; // 0 -1
v33Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z ), slice ).x; // 0 1
v33Taps.x = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms2.xz, tcs.z + dot( vShadow3x3PCFTerms2.xz, sampleBias ) ), slice ).x; // 1 0
v33Taps.y = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms3.xz, tcs.z + dot( vShadow3x3PCFTerms3.xz, sampleBias ) ), slice ).x; // -1 0
v33Taps.z = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms3.zy, tcs.z + dot( vShadow3x3PCFTerms3.zy, sampleBias ) ), slice ).x; // 0 -1
v33Taps.w = SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, real3( tcs.xy + vShadow3x3PCFTerms2.zy, tcs.z + dot( vShadow3x3PCFTerms2.zy, sampleBias ) ), slice ).x; // 0 1
flSum += dot( v33Taps.xyzw, vShadow3x3PCFTerms0.yyyy );
flSum += SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, compSamp, tcs, slice ).x * vShadow3x3PCFTerms0.z;

//-----------------------------------------------------------------------------------------------------
// helper function to dispatch a specific shadow algorithm
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real depthBias, uint slice, uint algorithm, uint texIdx, uint sampIdx )
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real2 sampleBias, uint slice, uint algorithm, uint texIdx, uint sampIdx )
case GPUSHADOWALGORITHM_PCF_1TAP : return SampleShadow_PCF_1tap( shadowContext, payloadOffset, posTC, depthBias, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_9TAP : return SampleShadow_PCF_9tap_Adaptive( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, depthBias, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_3X3 : return SampleShadow_PCF_Tent_3x3( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_5X5 : return SampleShadow_PCF_Tent_5x5( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_7X7 : return SampleShadow_PCF_Tent_7x7( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_1TAP : return SampleShadow_PCF_1tap( shadowContext, payloadOffset, posTC, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_9TAP : return SampleShadow_PCF_9tap_Adaptive( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_3X3 : return SampleShadow_PCF_Tent_3x3( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_5X5 : return SampleShadow_PCF_Tent_5x5( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_PCF_TENT_7X7 : return SampleShadow_PCF_Tent_7x7( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_VSM : return SampleShadow_VSM_1tap( shadowContext, payloadOffset, posTC, slice, texIdx, sampIdx );
case GPUSHADOWALGORITHM_EVSM_2 : return SampleShadow_EVSM_1tap( shadowContext, payloadOffset, posTC, slice, texIdx, sampIdx, false );
case GPUSHADOWALGORITHM_EVSM_4 : return SampleShadow_EVSM_1tap( shadowContext, payloadOffset, posTC, slice, texIdx, sampIdx, true );

}
}
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real depthBias, uint slice, uint algorithm, Texture2DArray tex, SamplerComparisonState compSamp )
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real2 sampleBias, uint slice, uint algorithm, Texture2DArray tex, SamplerComparisonState compSamp )
case GPUSHADOWALGORITHM_PCF_1TAP : return SampleShadow_PCF_1tap( shadowContext, payloadOffset, posTC, depthBias, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_9TAP : return SampleShadow_PCF_9tap_Adaptive( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, depthBias, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_3X3 : return SampleShadow_PCF_Tent_3x3( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_5X5 : return SampleShadow_PCF_Tent_5x5( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_7X7 : return SampleShadow_PCF_Tent_7x7( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_1TAP : return SampleShadow_PCF_1tap( shadowContext, payloadOffset, posTC, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_9TAP : return SampleShadow_PCF_9tap_Adaptive( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_3X3 : return SampleShadow_PCF_Tent_3x3( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_5X5 : return SampleShadow_PCF_Tent_5x5( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, tex, compSamp );
case GPUSHADOWALGORITHM_PCF_TENT_7X7 : return SampleShadow_PCF_Tent_7x7( shadowContext, payloadOffset, shadowData.texelSizeRcp, posTC, sampleBias, slice, tex, compSamp );
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real depthBias, uint slice, uint algorithm, Texture2DArray tex, SamplerState samp )
real SampleShadow_SelectAlgorithm( ShadowContext shadowContext, ShadowData shadowData, inout uint payloadOffset, real3 posTC, real2 sampleBias, uint slice, uint algorithm, Texture2DArray tex, SamplerState samp )
{
[branch]
switch( algorithm )

8
ScriptableRenderPipeline/Core/CoreRP/ShaderLibrary/Shadow/ShadowTexFetch.hlsl


// Sampler and texture combinations are static. No shadowmap will ever be sampled with two different samplers.
// Once shadowmaps and samplers are fixed consider writing custom dispatchers directly accessing textures and samplers.
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_COMP( _Tex2DArraySlots, _SamplerCompSlots ) \
real4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real slice ) \
real4 SampleCompShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real slice ) \
{ \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \

}
# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_SAMP( _Tex2DArraySlots, _SamplerSlots ) \
real4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real2 tcs, real slice, real lod = 0.0 ) \
real4 SampleShadow_T2DA( ShadowContext ctxt, uint texIdx, uint sampIdx, real2 tcs, real slice, real lod = 0.0 ) \
{ \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \

# define SHADOW_DEFINE_SAMPLING_FUNC_T2DA_LOAD( _Tex2DArraySlots ) \
real LoadShadow_T2DA( ShadowContext ctxt, uint texIdx, uint2 tcs, uint slice, uint lod = 0 ) \
{ \
real res = 1.0; \
real res = 1.0; \
[unroll] for( uint i = 0; i < _Tex2DArraySlots; i++ ) \
{ \
[branch] if( i == texIdx ) \

}
# define SHADOW_DEFINE_SAMPLING_FUNC_TCA_SAMP( _TexCubeArraySlots, _SamplerSlots ) \
real4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real cubeIdx, real lod = 0.0 ) \
real4 SampleShadow_TCA( ShadowContext ctxt, uint texIdx, uint sampIdx, real3 tcs, real cubeIdx, real lod = 0.0 ) \
{ \
real4 res = 1.0.xxxx; \
[unroll] for( uint i = 0; i < _TexCubeArraySlots; i++ ) \

12
ScriptableRenderPipeline/Core/CoreRP/Shadow/AdditionalShadowData.cs


public float contactShadowFadeDistance = 5.0f;
[Range(4, 64)]
public uint contactShadowSampleCount = 8;
// bias control
public float viewBiasMin = 0.5f;
public float viewBiasMax = 10.0f;
[Range(0.0F, 15.0F)]
public float viewBiasScale = 1.0f;
public float nrmlBiasMin = 0.2f;
public float nrmlBiasMax = 4.0f;
[Range(0.0F, 10.0F)]
public float nrmlBiasScale = 1.0f;
public bool sampleBiasScale = true;
public bool edgeLeakFixup = true;
// shadow related parameters
[System.Serializable]

11
ScriptableRenderPipeline/Core/CoreRP/Shadow/Shadow.cs


}
}
// extract texel size in world space
AdditionalShadowData asd = lights[sr.index].light.GetComponent<AdditionalShadowData>();
int flags = 0;
flags |= asd.sampleBiasScale ? (1 << 0) : 0;
flags |= asd.edgeLeakFixup ? (1 << 1) : 0;
sd.viewBias = new Vector4( asd.viewBiasMin, asd.viewBiasMax, asd.viewBiasScale, 2.0f / ce.current.proj.m00 / ce.current.viewport.width * 1.4142135623730950488016887242097f );
sd.nrmlBias = new Vector4( asd.nrmlBiasMin, asd.nrmlBiasMax, asd.nrmlBiasScale, ShadowUtils.Asfloat( flags ) );
// write :(
ce.current.shadowAlgo = (GPUShadowAlgorithm) shadowAlgo;
m_EntryCache[ceIdx] = ce;

// set light specific values that are not related to the shadowmap
GPUShadowType shadowtype = GetShadowLightType(l);
// current bias value range is way too large, so scale by 0.01 for now until we've decided whether to actually keep this value or not.
sd.bias = 0.01f * (SystemInfo.usesReversedZBuffer ? l.shadowBias : -l.shadowBias);
sd.normalBias = 2.0f * l.shadowNormalBias;
shadowIndices.AddUnchecked( (int) shadowDatas.Count() );

6
ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs


public uint id; // packed texture id, sampler id and slice idx
public uint shadowType; // determines the shadow algorithm, i.e. which map to sample and how to interpret the data
public uint payloadOffset; // if this shadow type requires additional data it can be fetched from a global Buffer<uint> at payloadOffset.
// light related params (need to be set via ShadowMgr and derivatives)
public float bias; // bias setting
public float normalBias; // bias based on the normal
public Vector4 viewBias; // x = min, y = max, z = scale, w = shadowmap texel size in world space at distance 1 from light
public Vector4 nrmlBias; // x = min, y = max, z = scale, w = enable/disable sample biasing
public void PackShadowmapId( uint texIdx, uint sampIdx, uint slice )
{

12
ScriptableRenderPipeline/Core/CoreRP/Shadow/ShadowBase.cs.hlsl


uint id;
uint shadowType;
uint payloadOffset;
float bias;
float normalBias;
float4 viewBias;
float4 nrmlBias;
};
//

{
return value.payloadOffset;
}
float GetBias(ShadowData value)
float4 GetViewBias(ShadowData value)
return value.bias;
return value.viewBias;
float GetNormalBias(ShadowData value)
float4 GetNrmlBias(ShadowData value)
return value.normalBias;
return value.nrmlBias;
}

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/DeferredDirectionalShadow.compute


#pragma kernel DeferredDirectionalShadow DEFERRED_DIRECTIONAL=DeferredDirectionalShadow
#pragma kernel DeferredDirectionalShadow_Contact DEFERRED_DIRECTIONAL=DeferredDirectionalShadow_Contact ENABLE_CONTACT_SHADOWS
#define SHADOW_USE_ONLY_VIEW_BASED_BIASING 1 // Enable only light view vector based biasing. If undefined, biasing will be based on the normal and calling code must provide a valid normal.
#include "CoreRP/ShaderLibrary/Common.hlsl"
#include "../ShaderVariables.hlsl"
#include "Lighting.hlsl"

UpdatePositionInput(depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_VP, posInput);
ShadowContext shadowContext = InitShadowContext();
float shadow = GetDirectionalShadowAttenuation(shadowContext, posInput.positionWS, float3(0.0, 0.0, 0.0), (uint)_DirectionalShadowIndex, float3(0.0, 0.0, 0.0));
float shadow = GetDirectionalShadowAttenuation(shadowContext, posInput.positionWS, float3(0.0, 0.0, 0.0), (uint)_DirectionalShadowIndex, _LightDirection);
#ifdef ENABLE_CONTACT_SHADOWS
float contactShadow = 1.0f;

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightEvaluation.hlsl


[branch] if (lightData.shadowIndex >= 0)
{
// TODO: make projector lights cast shadows.
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
float4 L_dist = float4(L, distances.x);
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, N, lightData.shadowIndex, L_dist, posInput.positionSS);
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS, N, lightData.shadowIndex, L, distances.x, posInput.positionSS);
#ifdef SHADOWS_SHADOWMASK
// Note: Legacy Unity have two shadow mask mode. ShadowMask (ShadowMask contain static objects shadow and ShadowMap contain only dynamic objects shadow, final result is the minimun of both value)
// and ShadowMask_Distance (ShadowMask contain static objects shadow and ShadowMap contain everything and is blend with ShadowMask based on distance (Global distance setup in QualitySettigns)).

15
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/LightLoop/Shadow.hlsl


#define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL
#define SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
#define SHADOW_USE_VIEW_BIAS_SCALING 1 // Enable view bias scaling to mitigate light leaking across edges. Uses the light vector if SHADOW_USE_ONLY_VIEW_BASED_BIASING is defined, otherwise uses the normal.
#define SHADOW_USE_SAMPLE_BIASING 1 // Enable per sample biasing for wide multi-tap PCF filters. Incompatible with SHADOW_USE_ONLY_VIEW_BASED_BIASING.
#include "ShadowContext.hlsl"
// This is an example of how to override the default dynamic resource dispatcher

// example of overriding punctual lights
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist )
{
#ifdef SHADOW_DISPATCH_USE_SEPARATE_PUNC_ALGOS
// example for choosing different algos for point and spot lights

Texture2DArray tex = shadowContext.tex2DArray[SHADOW_DISPATCH_POINT_TEX];
SamplerComparisonState compSamp = shadowContext.compSamplers[SHADOW_DISPATCH_POINT_SMP];
uint algo = SHADOW_DISPATCH_POINT_ALG;
return EvalShadow_PointDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
return EvalShadow_PointDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L, L_dist );
}
else
{

return EvalShadow_SpotDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
return EvalShadow_SpotDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L, L_dist );
}
#else
// example for choosing the same algo

return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L, L_dist );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 positionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist, float2 positionSS )
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L, L_dist );
}
#endif

4
TestbedPipelines/Fptl/LightingTemplate.hlsl


[branch]
if (shadowIdx >= 0)
{
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(normalize(light.dir.xyz), dist));
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, normalize(light.dir.xyz), dist);
atten *= shadow;
}

[branch]
if (shadowIdx >= 0)
{
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(vLw, dist));
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, vLw, dist);
atten *= shadow;
}

9
TestbedPipelines/Fptl/Shadow.hlsl


#define SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL // Define this to provide custom implementations of GetPunctualShadowAttenuation
#define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL // Define this to provide custom implementations of GetDirectionalShadowAttenuation
#define SHADOW_USE_ONLY_VIEW_BASED_BIASING 1 // don't use the normal for biasing
#include "ShadowContext.hlsl"

#endif
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist )
return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L, L_dist );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist, float2 unPositionSS )
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L, L_dist );
}
#endif

6
TestbedPipelines/OnTileDeferredPipeline/Shaders/LightingTemplate.hlsl


atten *= tex2D (_LightTextureB0, att.rr).UNITY_ATTEN_CHANNEL;
if (_LightIndexForShadowMatrixArray >= 0)
atten *= GetPunctualShadowAttenuation(shadowContext, wpos, 0.0.xxx, _LightIndexForShadowMatrixArray, float4(lightDir, dist));
atten *= GetPunctualShadowAttenuation(shadowContext, wpos, 0.0.xxx, _LightIndexForShadowMatrixArray, lightDir, dist);
// directional light case
#elif defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE)

if (_LightIndexForShadowMatrixArray >= 0)
atten *= GetDirectionalShadowAttenuation(shadowContext, wpos, 0.0.xxx, _LightIndexForShadowMatrixArray, 0.0.xxx);
atten *= GetDirectionalShadowAttenuation(shadowContext, wpos, 0.0.xxx, _LightIndexForShadowMatrixArray, lightDir);
#if defined (DIRECTIONAL_COOKIE)
colorCookie = tex2Dlod (_LightTexture0, float4(mul(unity_WorldToLight, half4(wpos,1)).xy, 0, 0));

float atten = tex2D (_LightTextureB0, att.rr).UNITY_ATTEN_CHANNEL;
if (_LightIndexForShadowMatrixArray >= 0)
atten *= GetPunctualShadowAttenuation(shadowContext, wpos, 0.0.xxx, _LightIndexForShadowMatrixArray, float4(lightDir, dist));
atten *= GetPunctualShadowAttenuation(shadowContext, wpos, 0.0.xxx, _LightIndexForShadowMatrixArray, lightDir, dist);
#if defined (POINT_COOKIE)
colorCookie = texCUBElod(_LightTexture0, float4(mul(unity_WorldToLight, float4(wpos,1)).xyz, 0));

9
TestbedPipelines/OnTileDeferredPipeline/Shaders/Shadow.hlsl


#define SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL // Define this to provide custom implementations of GetPunctualShadowAttenuation
#define SHADOW_DISPATCH_USE_CUSTOM_DIRECTIONAL // Define this to provide custom implementations of GetDirectionalShadowAttenuation
#define SHADOW_USE_ONLY_VIEW_BASED_BIASING 1 // don't use the normal for biasing
#include "ShadowContext.hlsl"

#endif
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist )
return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L, L_dist );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float L_dist, float2 unPositionSS )
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L, L_dist );
}
#endif

8
TestbedPipelines/OnTileDeferredPipeline/Shaders/UnityStandardForwardMobile.cginc


# error unsupported shader api
#endif
#include "CoreRP/ShaderLibrary/API/Validate.hlsl"
#include "../../Fptl/Shadow.hlsl"
#include "Shadow.hlsl"
struct VertexOutputForwardNew
{

[branch]
if (shadowIdx >= 0 && _transparencyShadows)
{
float shadow = GetDirectionalShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, 0.0.xxx);
float shadow = GetDirectionalShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, -gLightDirection[lightIndex].xyz);
atten *= shadow;
}

[branch]
if (shadowIdx >= 0 && _transparencyShadows)
{
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(vLw, dist));
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, vLw, dist);
atten *= shadow;
}

[branch]
if (shadowIdx >= 0 && _transparencyShadows)
{
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(vLw, dist));
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, vLw, dist);
atten *= shadow;
}

正在加载...
取消
保存