|
|
|
|
|
|
// function called by spot, point and directional eval routines to calculate shadow coordinates |
|
|
|
real3 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real3 posNDC, bool clampToRect ) |
|
|
|
{ |
|
|
|
real4 posCS = mul(real4(positionWS, 1.0), sd.worldToShadow); |
|
|
|
real4 posCS = mul( real4( positionWS, 1.0 ), sd.worldToShadow ); |
|
|
|
real3 posTC = posNDC * 0.5 + 0.5; |
|
|
|
real3 posTC = float3( posNDC.xy * 0.5 + 0.5, posNDC.z ); |
|
|
|
#if UNITY_REVERSED_Z |
|
|
|
posTC.z = 1.0 - posTC.z; |
|
|
|
#endif |
|
|
|
|
|
|
|
return posTC; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|
|
|
// sample the texture according to the given algorithm |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
real EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \ |
|
|
|
real EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \ |
|
|
|
real3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \ |
|
|
|
real3 lpos = positionWS + L.xyz * L.w; \ |
|
|
|
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 */ \ |
|
|
|
|
|
|
/* get shadowmap texcoords */ \ |
|
|
|
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|
|
|
/* sample the texture */ \ |
|
|
|
real slice; \ |
|
|
|
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 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]; \ |
|
|
|
|
|
|
/* get shadowmap texcoords */ \ |
|
|
|
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|
|
|
/* sample the texture */ \ |
|
|
|
real slice; \ |
|
|
|
float slice; \ |
|
|
|
UnpackShadowmapId( sd.id, slice ); \ |
|
|
|
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|
|
|
} |
|
|
|
|
|
|
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); |
|
|
|
// sample the texture according to the given algorithm |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm ); |
|
|
|
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx ); |
|
|
|
|
|
|
real EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real4 L ) \ |
|
|
|
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; \ |
|
|
|
|
|
|
[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; \ |
|
|
|
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; \ |
|
|
|
} \ |
|
|
|
|
|
|
/* get shadowmap texcoords */ \ |
|
|
|
real3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \ |
|
|
|
/* sample the texture */ \ |
|
|
|
real slice; \ |
|
|
|
float slice; \ |
|
|
|
UnpackShadowmapId( sd.id, slice ); \ |
|
|
|
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, tex, samp ); \ |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
// sample the texture |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
|
|
|
|
uint shadowType, shadowAlgorithm; |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#define EvalShadow_CascadedDepth_( _samplerType ) \ |
|
|
|
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
real relDistance; \ |
|
|
|
real relDistance; \ |
|
|
|
real4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real border = borders[shadowSplitIndex]; \ |
|
|
|
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \ |
|
|
|
real border = borders[shadowSplitIndex]; \ |
|
|
|
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \ |
|
|
|
real3 orig_pos = positionWS; \ |
|
|
|
real3 orig_pos = positionWS; \ |
|
|
|
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \ |
|
|
|
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz ); \ |
|
|
|
real3 wposDir = normalize( -splitSphere + positionWS ); \ |
|
|
|
real cascDot = dot( cascadeDir, wposDir ); \ |
|
|
|
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \ |
|
|
|
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[min( shadowSplitIndex+1, kMaxShadowCascades-1 )].xyz ); \ |
|
|
|
real3 wposDir = normalize( -splitSphere + positionWS ); \ |
|
|
|
real cascDot = dot( cascadeDir, wposDir ); \ |
|
|
|
real3 posNDC; \ |
|
|
|
real3 posNDC; \ |
|
|
|
real slice; \ |
|
|
|
float slice; \ |
|
|
|
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \ |
|
|
|
real shadow1 = 1.0; \ |
|
|
|
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \ |
|
|
|
real shadow1 = 1.0; \ |
|
|
|
\ |
|
|
|
shadowSplitIndex++; \ |
|
|
|
if( shadowSplitIndex < kMaxShadowCascades ) \ |
|
|
|
|
|
|
return shadow; \ |
|
|
|
} \ |
|
|
|
\ |
|
|
|
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
real EvalShadow_CascadedDepth_Blend( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
{ \ |
|
|
|
uint shadowAlgorithms[kMaxShadowCascades] = { SHADOW_REPEAT_CASCADE( shadowAlgorithm ) }; \ |
|
|
|
return EvalShadow_CascadedDepth_Blend( shadowContext, shadowAlgorithms, tex, samp, positionWS, normalWS, index, L ); \ |
|
|
|
|
|
|
} |
|
|
|
// sample the texture |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
|
|
|
|
uint shadowType, shadowAlgorithm; |
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
#define EvalShadow_CascadedDepth_( _samplerType ) \ |
|
|
|
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithms[kMaxShadowCascades], Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
real relDistance; \ |
|
|
|
real relDistance; \ |
|
|
|
\ |
|
|
|
real4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
\ |
|
|
|
real4 scales = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real4 borders = asfloat( shadowContext.payloads[payloadOffset] ); \ |
|
|
|
real border = borders[shadowSplitIndex]; \ |
|
|
|
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \ |
|
|
|
\ |
|
|
|
real border = borders[shadowSplitIndex]; \ |
|
|
|
real alpha = border <= 0.0 ? 0.0 : saturate( (relDistance - (1.0 - border)) / border ); \ |
|
|
|
\ |
|
|
|
real3 orig_pos = positionWS; \ |
|
|
|
real3 orig_pos = positionWS; \ |
|
|
|
real3 posNDC; \ |
|
|
|
real3 posNDC; \ |
|
|
|
\ |
|
|
|
\ |
|
|
|
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \ |
|
|
|
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[nextSplit].xyz ); \ |
|
|
|
real3 wposDir = normalize( -splitSphere + positionWS ); \ |
|
|
|
real cascDot = dot( cascadeDir, wposDir ); \ |
|
|
|
real3 splitSphere = dirShadowSplitSpheres[shadowSplitIndex].xyz; \ |
|
|
|
real3 cascadeDir = normalize( -splitSphere + dirShadowSplitSpheres[nextSplit].xyz ); \ |
|
|
|
real3 wposDir = normalize( -splitSphere + positionWS ); \ |
|
|
|
real cascDot = dot( cascadeDir, wposDir ); \ |
|
|
|
\ |
|
|
|
\ |
|
|
|
if( shadowSplitIndex != nextSplit && step( EvalShadow_hash12( posTC.xy ), alpha ) ) \ |
|
|
|
{ \ |
|
|
|
sd = shadowContext.shadowDatas[index + 1 + nextSplit]; \ |
|
|
|
|
|
|
/* sample the texture */ \ |
|
|
|
real slice; \ |
|
|
|
float slice; \ |
|
|
|
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \ |
|
|
|
real shadow = SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithms[shadowSplitIndex], tex, samp ); \ |
|
|
|
\ |
|
|
|
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
\ |
|
|
|
real EvalShadow_CascadedDepth_Dither( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, real3 positionWS, real3 normalWS, int index, real3 L ) \ |
|
|
|
{ \ |
|
|
|
uint shadowAlgorithms[kMaxShadowCascades] = { SHADOW_REPEAT_CASCADE( shadowAlgorithm ) }; \ |
|
|
|
return EvalShadow_CascadedDepth_Dither( shadowContext, shadowAlgorithms, tex, samp, positionWS, normalWS, index, L ); \ |
|
|
|
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
closestNDC.z = LoadShadow_T2DA( shadowContext, texIdx, texelIdx, slice ); |
|
|
|
|
|
|
|
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId(sd.id, slice); |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, slice, 0 ).x; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
closestNDC.z = LoadShadow_T2DA( shadowContext, texIdx, texelIdx, slice ); |
|
|
|
|
|
|
|
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId(sd.id, slice); |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, slice, 0 ).x; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
closestNDC.z = LoadShadow_T2DA( shadowContext, texIdx, texelIdx, slice ); |
|
|
|
|
|
|
|
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId(sd.id, slice); |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, slice, 0 ).x; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
closestNDC.z = LoadShadow_T2DA( shadowContext, texIdx, texelIdx, slice ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
real slice; |
|
|
|
float slice; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx, slice ); |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, slice, 0 ).x; |
|
|
|
|
|
|
|