|
|
|
|
|
|
return EvalShadow_GetTexcoords( sd, positionWS, ndc, perspProj ); |
|
|
|
} |
|
|
|
|
|
|
|
uint2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj ) |
|
|
|
real2 EvalShadow_GetTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj ) |
|
|
|
{ |
|
|
|
real4 posCS = EvalShadow_WorldToShadow( sd, positionWS, perspProj ); |
|
|
|
real2 posNDC = perspProj ? (posCS.xy / posCS.w) : posCS.xy; |
|
|
|
|
|
|
return uint2( (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy ); |
|
|
|
return posTC * sd.scaleOffset.xy + sd.scaleOffset.zw; |
|
|
|
uint2 EvalShadow_GetIntTexcoords( ShadowData sd, real3 positionWS, out real2 closestSampleNDC, bool perspProj ) |
|
|
|
{ |
|
|
|
real2 texCoords = EvalShadow_GetTexcoords(sd, positionWS, closestSampleNDC, perspProj); |
|
|
|
return uint2(texCoords * sd.textureSize.xy); |
|
|
|
} |
|
|
|
|
|
|
|
// |
|
|
|
// Biasing functions |
|
|
|
|
|
|
sd = shadowContext.shadowDatas[index + faceIndex]; |
|
|
|
|
|
|
|
real4 closestNDC = { 0,0,0,1 }; |
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( 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, true ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, sd.slice, 0 ).x; |
|
|
|
|
|
|
ShadowData sd = shadowContext.shadowDatas[index]; |
|
|
|
|
|
|
|
real4 closestNDC = { 0,0,0,1 }; |
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( 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, true ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, sd.slice, 0 ).x; |
|
|
|
|
|
|
sd = shadowContext.shadowDatas[index + faceIndex]; |
|
|
|
|
|
|
|
real4 closestNDC = { 0,0,0,1 }; |
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( 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, true ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
closestNDC.z = LOAD_TEXTURE2D_ARRAY_LOD( tex, texelIdx, sd.slice, 0 ).x; |
|
|
|
|
|
|
return closestWS.xyz / closestWS.w; |
|
|
|
} |
|
|
|
|
|
|
|
real EvalShadow_SampleClosestDistance_Punctual( ShadowContext shadowContext, Texture2DArray tex, SamplerState sampl, |
|
|
|
real3 positionWS, int index, real3 L, real3 lightPositionWS ) |
|
|
|
{ |
|
|
|
// get the algorithm |
|
|
|
ShadowData sd = shadowContext.shadowDatas[index]; |
|
|
|
uint shadowType; |
|
|
|
UnpackShadowType( sd.shadowType, shadowType ); |
|
|
|
// load the right shadow data for the current face |
|
|
|
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMapFaceID( -L ) + 1) : 0; |
|
|
|
sd = shadowContext.shadowDatas[index + faceIndex]; |
|
|
|
|
|
|
|
real4 closestNDC = { 0,0,0,1 }; |
|
|
|
real2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, true ); |
|
|
|
|
|
|
|
// sample the shadow map |
|
|
|
closestNDC.z = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, sampl, texelIdx, sd.slice, 0 ).x; |
|
|
|
|
|
|
|
// reconstruct depth position |
|
|
|
real4 closestWS = mul( closestNDC, sd.shadowToWorld ); |
|
|
|
real3 occluderPosWS = closestWS.xyz / closestWS.w; |
|
|
|
|
|
|
|
return distance( occluderPosWS, lightPositionWS ); |
|
|
|
} |
|
|
|
|
|
|
|
real3 EvalShadow_GetClosestSample_Cascade( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real4 L ) |
|
|
|
{ |
|
|
|
// load the right shadow data for the current face |
|
|
|
|
|
|
|
|
|
|
if( shadowSplitIndex < 0 ) |
|
|
|
return 1.0; |
|
|
|
return 0.0; |
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, false ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
|
|
|
int shadowSplitIndex = EvalShadow_GetSplitIndex( shadowContext, index, positionWS, payloadOffset, alpha ); |
|
|
|
|
|
|
|
if( shadowSplitIndex < 0 ) |
|
|
|
return 1.0; |
|
|
|
return 0.0; |
|
|
|
uint2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false ); |
|
|
|
uint2 texelIdx = EvalShadow_GetIntTexcoords( sd, positionWS, closestNDC.xy, false ); |
|
|
|
|
|
|
|
// load the texel |
|
|
|
uint texIdx, sampIdx; |
|
|
|
|
|
|
real4 closestWS = mul( closestNDC, sd.shadowToWorld ); |
|
|
|
return closestWS.xyz / closestWS.w; |
|
|
|
} |
|
|
|
|
|
|
|
real EvalShadow_SampleClosestDistance_Cascade( ShadowContext shadowContext, Texture2DArray tex, SamplerState sampl, |
|
|
|
real3 positionWS, real3 normalWS, int index, real4 L, out real3 nearPlanePositionWS ) |
|
|
|
{ |
|
|
|
// load the right shadow data for the current face |
|
|
|
uint payloadOffset; |
|
|
|
real alpha; |
|
|
|
int shadowSplitIndex = EvalShadow_GetSplitIndex( shadowContext, index, positionWS, payloadOffset, alpha ); |
|
|
|
|
|
|
|
if( shadowSplitIndex < 0 ) |
|
|
|
return 0.0; |
|
|
|
|
|
|
|
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; |
|
|
|
|
|
|
|
real4 closestNDC = { 0,0,0,1 }; |
|
|
|
real2 texelIdx = EvalShadow_GetTexcoords( sd, positionWS, closestNDC.xy, false ); |
|
|
|
|
|
|
|
// sample the shadow map |
|
|
|
uint texIdx, sampIdx; |
|
|
|
UnpackShadowmapId( sd.id, texIdx, sampIdx ); |
|
|
|
closestNDC.z = SAMPLE_TEXTURE2D_ARRAY_LOD( tex, sampl, texelIdx, sd.slice, 0 ).x; |
|
|
|
|
|
|
|
// reconstruct depth position |
|
|
|
real4 closestWS = mul( closestNDC, sd.shadowToWorld ); |
|
|
|
real3 occluderPosWS = closestWS.xyz / closestWS.w; |
|
|
|
|
|
|
|
// TODO: avoid the matrix multiplication here. |
|
|
|
real4 nearPlanePos = mul( real4( 0,0,1,1 ), sd.shadowToWorld ); // Note the reversed Z |
|
|
|
nearPlanePositionWS = nearPlanePos.xyz / nearPlanePos.w; |
|
|
|
|
|
|
|
return distance( occluderPosWS, nearPlanePositionWS ); |
|
|
|
} |