return uint2( (posTC * sd.scaleOffset.xy + sd.scaleOffset.zw) * sd.textureSize.xy );
}
int EvalShadow_GetCubeFaceID( real3 sampleToLight )
{
real3 lightToSample = -sampleToLight; // TODO: pass the correct (flipped) direction
#ifdef INTRINSIC_CUBEMAP_FACE_ID
return (int)CubeMapFaceID(lightToSample);
#else
// TODO: use CubeMapFaceID() defined in Common.hlsl for all pipelines on all platforms.
real3 dir = sampleToLight;
real3 adir = abs(dir);
// +Z -Z
int faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
// +X -X
if (adir.x > adir.y && adir.x > adir.z)
{
faceIndex = dir.x > 0.0 ? CUBEMAPFACE_NEGATIVE_X : CUBEMAPFACE_POSITIVE_X;
}
// +Y -Y
else if (adir.y > adir.x && adir.y > adir.z)
{
faceIndex = dir.y > 0.0 ? CUBEMAPFACE_NEGATIVE_Y : CUBEMAPFACE_POSITIVE_Y;
}
return faceIndex;
#endif
}
//
// Biasing functions
[branch]
if( shadowAlgorithm <= GPUSHADOWALGORITHM_PCF_TENT_7X7 )
{
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.nrmlBias.w ) );
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.no rma lBias.w ) );
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) );
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.no rma lBias.w ) );
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.nrmlBias.w ) );
return lerp( 1.0, SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, samp, EvalShadow_GetTexcoords( sd, pos, perspProj ), sd.slice ).x, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) );
real3 pos = EvalShadow_ReceiverBiasWeightPos( positionWS, normalWS, L, EvalShadow_WorldTexelSize( sd, L_dist, perspProj ), sd.edgeTolerance, EvalShadow_ReceiverBiasWeightUseNormalFlag( sd.no rma lBias.w ) );
return lerp( 1.0, SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, samp, EvalShadow_GetTexcoords( sd, pos, perspProj ), sd.slice ).x, EvalShadow_ReceiverBiasWeightFlag( sd.no rma lBias.w ) );
}
real EvalShadow_ReceiverBiasWeight( ShadowData sd, Texture2DArray tex, SamplerState samp, real3 positionWS, real3 normalWS, real3 L, real L_dist, bool perspProj )
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 no rma lBiasMin = sd.no rma lBias.x;
float no rma lBiasMax = sd.no rma lBias.y;
float no rma lBiasScale = sd.no rma lBias.z;
sine = clamp( sine * nrmlBiasScale, nrmlBiasMin, nrmlBiasMax );
sine = clamp( sine * no rma lBiasScale, no rma lBiasMin, no rma lBiasMax );
tangent = clamp( tangent * viewBiasScale * lightviewBiasWeight, viewBiasMin, viewBiasMax );
float3 view_bias = L * tangent;
float3 normal_bias = normalWS * sine;
float3 nrm = cross( p1.xyz - tcs, p2.xyz - tcs );
nrm.xy /= -nrm.z;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.no rma lBias.w ) * nrm.xy) : 0.0.xx;
}
float2 EvalShadow_SampleBias_Ortho( ShadowData sd, float3 normalWS )
nrm.xy /= -nrm.z;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.nrmlBias.w ) * nrm.xy) : 0.0.xx;
return isfinite( nrm.xy ) ? (EvalShadow_SampleBiasFlag( sd.no rma lBias.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; }
//
real EvalShadow_PointDepth( ShadowContext shadowContext, real3 positionWS, real3 normalWS, int index, real3 L, real L_dist )
{
ShadowData sd = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1];
ShadowData sd = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1];
// get the algorithm
uint shadowType, shadowAlgorithm;
UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
#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_Get CubeFaceID( L ) + 1]; \
ShadowData sd = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1]; \
/* bias the world position */ \
real recvBiasWeight = EvalShadow_ReceiverBiasWeight( sd, tex, samp, positionWS, normalWS, L, L_dist, true ); \
positionWS = EvalShadow_ReceiverBias( sd, positionWS, normalWS, L, L_dist, recvBiasWeight, true ); \
[branch]
if( shadowType == GPUSHADOWTYPE_POINT )
{
sd.rot0 = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].rot0;
sd.rot1 = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].rot1;
sd.rot2 = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].rot2;
sd.shadowToWorld = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].shadowToWorld;
sd.scaleOffset.zw = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].scaleOffset.zw;
sd.slice = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].slice;
sd.rot0 = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].rot0;
sd.rot1 = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].rot1;
sd.rot2 = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].rot2;
sd.shadowToWorld = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].shadowToWorld;
sd.scaleOffset.zw = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].scaleOffset.zw;
sd.slice = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].slice;
}
uint texIdx, sampIdx;
[branch] \
if( shadowType == GPUSHADOWTYPE_POINT ) \
{ \
sd.rot0 = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].rot0; \
sd.rot1 = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].rot1; \
sd.rot2 = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].rot2; \
sd.shadowToWorld = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].shadowToWorld; \
sd.scaleOffset.zw = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].scaleOffset.zw; \
sd.slice = shadowContext.shadowDatas[index + EvalShadow_Get CubeFaceID( L ) + 1].slice; \
sd.rot0 = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].rot0; \
sd.rot1 = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].rot1; \
sd.rot2 = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].rot2; \
sd.shadowToWorld = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].shadowToWorld; \
sd.scaleOffset.zw = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].scaleOffset.zw; \
sd.slice = shadowContext.shadowDatas[index + CubeMap FaceID( - L ) + 1].slice; \
} \
\
/* bias the world position */ \
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];
// load the right shadow data for the current face
int faceIndex = EvalShadow_Get CubeFaceID( L ) + 1;
int faceIndex = CubeMap FaceID( - L ) + 1;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
// get the algorithm
ShadowData sd = shadowContext.shadowDatas[index];
// load the right shadow data for the current face
int faceIndex = EvalShadow_Get CubeFaceID( L ) + 1;
int faceIndex = CubeMap FaceID( - L ) + 1;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint shadowType;
UnpackShadowType( sd.shadowType, shadowType );
// load the right shadow data for the current face
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (EvalShadow_Get CubeFaceID( L ) + 1) : 0;
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMap FaceID( - L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };
uint shadowType;
UnpackShadowType( sd.shadowType, shadowType );
// load the right shadow data for the current face
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (EvalShadow_Get CubeFaceID( L ) + 1) : 0;
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMap FaceID( - L ) + 1) : 0;
sd = shadowContext.shadowDatas[index + faceIndex];
real4 closestNDC = { 0,0,0,1 };