|
|
|
|
|
|
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.normalBias.w ) ); |
|
|
|
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.nrmlBias.w ) ); |
|
|
|
return lerp( 1.0, weight, EvalShadow_ReceiverBiasWeightFlag( sd.normalBias.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.normalBias.w ) ); |
|
|
|
return lerp( 1.0, SAMPLE_TEXTURE2D_ARRAY_SHADOW( tex, samp, EvalShadow_GetTexcoords( sd, pos, perspProj ), sd.slice ).x, EvalShadow_ReceiverBiasWeightFlag( sd.normalBias.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 normalBiasMin = sd.normalBias.x; |
|
|
|
float normalBiasMax = sd.normalBias.y; |
|
|
|
float normalBiasScale = sd.normalBias.z; |
|
|
|
sine = clamp( sine * nrmlBiasScale, nrmlBiasMin, nrmlBiasMax ); |
|
|
|
sine = clamp( sine * normalBiasScale, normalBiasMin, normalBiasMax ); |
|
|
|
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.normalBias.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.normalBias.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_GetCubeFaceID( L ) + 1]; |
|
|
|
ShadowData sd = shadowContext.shadowDatas[index + CubeMapFaceID( -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_GetCubeFaceID( L ) + 1]; \ |
|
|
|
ShadowData sd = shadowContext.shadowDatas[index + CubeMapFaceID( -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_GetCubeFaceID( L ) + 1].rot0; |
|
|
|
sd.rot1 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot1; |
|
|
|
sd.rot2 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot2; |
|
|
|
sd.shadowToWorld = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].shadowToWorld; |
|
|
|
sd.scaleOffset.zw = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].scaleOffset.zw; |
|
|
|
sd.slice = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].slice; |
|
|
|
sd.rot0 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot0; |
|
|
|
sd.rot1 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot1; |
|
|
|
sd.rot2 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot2; |
|
|
|
sd.shadowToWorld = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].shadowToWorld; |
|
|
|
sd.scaleOffset.zw = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].scaleOffset.zw; |
|
|
|
sd.slice = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].slice; |
|
|
|
} |
|
|
|
|
|
|
|
uint texIdx, sampIdx; |
|
|
|
|
|
|
[branch] \ |
|
|
|
if( shadowType == GPUSHADOWTYPE_POINT ) \ |
|
|
|
{ \ |
|
|
|
sd.rot0 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot0; \ |
|
|
|
sd.rot1 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot1; \ |
|
|
|
sd.rot2 = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].rot2; \ |
|
|
|
sd.shadowToWorld = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].shadowToWorld; \ |
|
|
|
sd.scaleOffset.zw = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].scaleOffset.zw; \ |
|
|
|
sd.slice = shadowContext.shadowDatas[index + EvalShadow_GetCubeFaceID( L ) + 1].slice; \ |
|
|
|
sd.rot0 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot0; \ |
|
|
|
sd.rot1 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot1; \ |
|
|
|
sd.rot2 = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].rot2; \ |
|
|
|
sd.shadowToWorld = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].shadowToWorld; \ |
|
|
|
sd.scaleOffset.zw = shadowContext.shadowDatas[index + CubeMapFaceID( -L ) + 1].scaleOffset.zw; \ |
|
|
|
sd.slice = shadowContext.shadowDatas[index + CubeMapFaceID( -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_GetCubeFaceID( L ) + 1; |
|
|
|
int faceIndex = CubeMapFaceID( -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_GetCubeFaceID( L ) + 1; |
|
|
|
int faceIndex = CubeMapFaceID( -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_GetCubeFaceID( L ) + 1) : 0; |
|
|
|
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMapFaceID( -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_GetCubeFaceID( L ) + 1) : 0; |
|
|
|
int faceIndex = shadowType == GPUSHADOWTYPE_POINT ? (CubeMapFaceID( -L ) + 1) : 0; |
|
|
|
sd = shadowContext.shadowDatas[index + faceIndex]; |
|
|
|
|
|
|
|
real4 closestNDC = { 0,0,0,1 }; |
|
|
|