|
|
|
@ -8,6 +8,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "ReceiverPlaneDepthBias.azsli"
|
|
|
|
|
|
|
|
|
|
|
|
// Pcf filtering taken from legacy Cry/Lumberyard ShadowCommon.cfi.
|
|
|
|
// Pcf filtering taken from legacy Cry/Lumberyard ShadowCommon.cfi.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Approximate an expensive but smooth bicubic filter by taking multiple bilinear samples and then weighting the samples appropriately.
|
|
|
|
// Approximate an expensive but smooth bicubic filter by taking multiple bilinear samples and then weighting the samples appropriately.
|
|
|
|
@ -28,8 +30,12 @@ struct SampleShadowMapBicubicParameters
|
|
|
|
float invShadowMapSize;
|
|
|
|
float invShadowMapSize;
|
|
|
|
SamplerComparisonState samplerState;
|
|
|
|
SamplerComparisonState samplerState;
|
|
|
|
float comparisonValue;
|
|
|
|
float comparisonValue;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Optionally pass in a non-zero value into the receiverPlaneDepthBias to reduce shadow acne with large Pcf kernels
|
|
|
|
|
|
|
|
float2 receiverPlaneDepthBias;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float SampleShadowMapBicubic_4Tap(SampleShadowMapBicubicParameters param)
|
|
|
|
float SampleShadowMapBicubic_4Tap(SampleShadowMapBicubicParameters param)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// Compute the shadow map UV and fractionals.
|
|
|
|
// Compute the shadow map UV and fractionals.
|
|
|
|
@ -47,13 +53,19 @@ float SampleShadowMapBicubic_4Tap(SampleShadowMapBicubicParameters param)
|
|
|
|
float2 uv1 = (fractionalUV / weights1) + 1.0;
|
|
|
|
float2 uv1 = (fractionalUV / weights1) + 1.0;
|
|
|
|
|
|
|
|
|
|
|
|
// Accumulate the shadow results and return the resolve value.
|
|
|
|
// Accumulate the shadow results and return the resolve value.
|
|
|
|
float shadow;
|
|
|
|
float shadow = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const float2 uvOffsets[4] = {float2(uv0.x, uv0.y), float2(uv1.x, uv0.y), float2(uv0.x, uv1.y), float2(uv1.x, uv1.y)};
|
|
|
|
|
|
|
|
const float weights[4] = {weights0.x * weights0.y, weights1.x * weights0.y, weights0.x * weights1.y, weights1.x * weights1.y};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[unroll]
|
|
|
|
|
|
|
|
for(int i = 0 ; i < 4; ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const float2 texCoordOffset = uvOffsets[i] * param.invShadowMapSize;
|
|
|
|
|
|
|
|
const float fragmentDistance = param.comparisonValue + ApplyReceiverPlaneDepthBias(param.receiverPlaneDepthBias, texCoordOffset);
|
|
|
|
|
|
|
|
shadow += weights[i] * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + texCoordOffset, param.shadowPos.z), fragmentDistance);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
shadow = weights0.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadow += weights1.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadow += weights0.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadow += weights1.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shadow /= 16.0;
|
|
|
|
shadow /= 16.0;
|
|
|
|
return shadow * shadow;
|
|
|
|
return shadow * shadow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -80,20 +92,26 @@ float SampleShadowMapBicubic_9Tap(SampleShadowMapBicubicParameters param)
|
|
|
|
float2 uv1 = (3.0 + fractionalUV) / weights1;
|
|
|
|
float2 uv1 = (3.0 + fractionalUV) / weights1;
|
|
|
|
float2 uv2 = (fractionalUV / weights2) + 2.0;
|
|
|
|
float2 uv2 = (fractionalUV / weights2) + 2.0;
|
|
|
|
|
|
|
|
|
|
|
|
// Accumulate the shadow results and return the resolve value.
|
|
|
|
|
|
|
|
float shadowResult;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shadowResult = weights0.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadowResult += weights1.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadowResult += weights2.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shadowResult += weights0.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
const float2 uvOffsets[9] = {float2(uv0.x, uv0.y), float2(uv1.x, uv0.y), float2(uv2.x, uv0.y),
|
|
|
|
shadowResult += weights1.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
float2(uv0.x, uv1.y), float2(uv1.x, uv1.y), float2(uv2.x, uv1.y),
|
|
|
|
shadowResult += weights2.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
float2(uv0.x, uv2.y), float2(uv1.x, uv2.y), float2(uv2.x, uv2.y) };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const float weights[9] = {weights0.x * weights0.y, weights1.x * weights0.y, weights2.x * weights0.y,
|
|
|
|
|
|
|
|
weights0.x * weights1.y, weights1.x * weights1.y, weights2.x * weights1.y,
|
|
|
|
|
|
|
|
weights0.x * weights2.y, weights1.x * weights2.y, weights2.x * weights2.y};
|
|
|
|
|
|
|
|
|
|
|
|
shadowResult += weights0.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
// Accumulate the shadow results and return the resolve value.
|
|
|
|
shadowResult += weights1.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
float shadowResult = 0;
|
|
|
|
shadowResult += weights2.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
|
|
|
|
[unroll]
|
|
|
|
|
|
|
|
for(int i = 0 ; i < 9 ; ++i)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const float2 texCoordOffset = uvOffsets[i] * param.invShadowMapSize;
|
|
|
|
|
|
|
|
const float fragmentDistance = param.comparisonValue + ApplyReceiverPlaneDepthBias(param.receiverPlaneDepthBias, texCoordOffset);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shadowResult += weights[i] * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + texCoordOffset, param.shadowPos.z), fragmentDistance);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
shadowResult /= 144.0;
|
|
|
|
shadowResult /= 144.0;
|
|
|
|
return shadowResult * shadowResult;
|
|
|
|
return shadowResult * shadowResult;
|
|
|
|
@ -123,28 +141,27 @@ float SampleShadowMapBicubic_16Tap(SampleShadowMapBicubicParameters param)
|
|
|
|
float2 uv2 = -((7.0 * fractionalUV + 5.0) / weights2) + 1.0;
|
|
|
|
float2 uv2 = -((7.0 * fractionalUV + 5.0) / weights2) + 1.0;
|
|
|
|
float2 uv3 = -(fractionalUV / weights3) + 3.0;
|
|
|
|
float2 uv3 = -(fractionalUV / weights3) + 3.0;
|
|
|
|
|
|
|
|
|
|
|
|
// Accumulate the shadow results and return the resolve value.
|
|
|
|
const float2 uvOffsets[16] = {float2(uv0.x, uv0.y), float2(uv1.x, uv0.y), float2(uv2.x, uv0.y), float2(uv3.x, uv0.y),
|
|
|
|
float shadow;
|
|
|
|
float2(uv0.x, uv1.y), float2(uv1.x, uv1.y), float2(uv2.x, uv1.y), float2(uv3.x, uv1.y),
|
|
|
|
|
|
|
|
float2(uv0.x, uv2.y), float2(uv1.x, uv2.y), float2(uv2.x, uv2.y), float2(uv3.x, uv2.y),
|
|
|
|
shadow = weights0.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
float2(uv0.x, uv3.y), float2(uv1.x, uv3.y), float2(uv2.x, uv3.y), float2(uv3.x, uv3.y)};
|
|
|
|
shadow += weights1.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadow += weights2.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
const float weights[16] = {weights0.x * weights0.y, weights1.x * weights0.y, weights2.x * weights0.y, weights3.x * weights0.y,
|
|
|
|
shadow += weights3.x * weights0.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv0.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
weights0.x * weights1.y, weights1.x * weights1.y, weights2.x * weights1.y, weights3.x * weights1.y,
|
|
|
|
|
|
|
|
weights0.x * weights2.y, weights1.x * weights2.y, weights2.x * weights2.y, weights3.x * weights2.y,
|
|
|
|
shadow += weights0.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
weights0.x * weights3.y, weights1.x * weights3.y, weights2.x * weights3.y, weights3.x * weights3.y};
|
|
|
|
shadow += weights1.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadow += weights2.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
// Accumulate the shadow results and return the resolve value.
|
|
|
|
shadow += weights3.x * weights1.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv1.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
float shadow = 0;
|
|
|
|
|
|
|
|
|
|
|
|
shadow += weights0.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
[unroll]
|
|
|
|
shadow += weights1.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
for(int i = 0 ; i < 16 ; ++i)
|
|
|
|
shadow += weights2.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
{
|
|
|
|
shadow += weights3.x * weights2.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv2.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
const float2 texCoordOffset = uvOffsets[i] * param.invShadowMapSize;
|
|
|
|
|
|
|
|
const float fragmentDistance = param.comparisonValue + ApplyReceiverPlaneDepthBias(param.receiverPlaneDepthBias, texCoordOffset);
|
|
|
|
shadow += weights0.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv0.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
shadow += weights1.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv1.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
shadow += weights[i] * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + texCoordOffset, param.shadowPos.z), fragmentDistance);
|
|
|
|
shadow += weights2.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv2.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
}
|
|
|
|
shadow += weights3.x * weights3.y * param.shadowMap.SampleCmpLevelZero(param.samplerState, float3(texelCenter + float2(uv3.x, uv3.y) * param.invShadowMapSize, param.shadowPos.z), param.comparisonValue);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shadow /= 2704;
|
|
|
|
shadow /= 2704;
|
|
|
|
return shadow * shadow;
|
|
|
|
return shadow * shadow;
|
|
|
|
|