rendering: improve main light shadow receiver filtering
This commit is contained in:
@@ -93,6 +93,49 @@ Shader "Builtin Forward Lit"
|
||||
return output;
|
||||
}
|
||||
|
||||
float SampleShadowVisibility(float2 sampleUv, float receiverDepth)
|
||||
{
|
||||
if (sampleUv.x < 0.0f || sampleUv.x > 1.0f ||
|
||||
sampleUv.y < 0.0f || sampleUv.y > 1.0f) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
const float shadowDepth = ShadowMapTexture.Sample(ShadowMapSampler, sampleUv).r;
|
||||
return receiverDepth <= shadowDepth ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
float ResolveShadowPcfAxisWeight(int offset)
|
||||
{
|
||||
const int absoluteOffset = abs(offset);
|
||||
if (absoluteOffset == 0) {
|
||||
return 6.0f;
|
||||
}
|
||||
if (absoluteOffset == 1) {
|
||||
return 4.0f;
|
||||
}
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float ComputeShadowPcfVisibility(float2 shadowUv, float receiverDepth, float2 shadowTexelSize)
|
||||
{
|
||||
float weightedVisibility = 0.0f;
|
||||
float weightSum = 0.0f;
|
||||
[unroll]
|
||||
for (int offsetY = -2; offsetY <= 2; ++offsetY) {
|
||||
const float weightY = ResolveShadowPcfAxisWeight(offsetY);
|
||||
[unroll]
|
||||
for (int offsetX = -2; offsetX <= 2; ++offsetX) {
|
||||
const float weight = weightY * ResolveShadowPcfAxisWeight(offsetX);
|
||||
const float2 sampleUv =
|
||||
shadowUv + float2((float)offsetX, (float)offsetY) * shadowTexelSize;
|
||||
weightedVisibility += SampleShadowVisibility(sampleUv, receiverDepth) * weight;
|
||||
weightSum += weight;
|
||||
}
|
||||
}
|
||||
|
||||
return weightSum > 0.0f ? weightedVisibility / weightSum : 1.0f;
|
||||
}
|
||||
|
||||
float ComputeShadowAttenuation(float3 positionWS, float3 normalWS, float3 lightDirectionWS)
|
||||
{
|
||||
#ifndef XC_MAIN_LIGHT_SHADOWS
|
||||
@@ -136,25 +179,10 @@ Shader "Builtin Forward Lit"
|
||||
const float receiverDepth = shadowNdc.z - gShadowSampling.receiverDepthBias;
|
||||
#endif
|
||||
const float2 shadowTexelSize = gShadowMapMetrics.inverseMapSize;
|
||||
float visibility = 0.0f;
|
||||
[unroll]
|
||||
for (int offsetY = -1; offsetY <= 1; ++offsetY) {
|
||||
[unroll]
|
||||
for (int offsetX = -1; offsetX <= 1; ++offsetX) {
|
||||
const float2 sampleUv =
|
||||
shadowUv + float2((float)offsetX, (float)offsetY) * shadowTexelSize;
|
||||
if (sampleUv.x < 0.0f || sampleUv.x > 1.0f ||
|
||||
sampleUv.y < 0.0f || sampleUv.y > 1.0f) {
|
||||
visibility += 1.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
const float shadowDepth = ShadowMapTexture.Sample(ShadowMapSampler, sampleUv).r;
|
||||
visibility += receiverDepth <= shadowDepth ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
visibility *= (1.0f / 9.0f);
|
||||
const float visibility = ComputeShadowPcfVisibility(
|
||||
shadowUv,
|
||||
receiverDepth,
|
||||
shadowTexelSize);
|
||||
const float shadowStrength = saturate(gShadowSampling.shadowStrength);
|
||||
return lerp(1.0f - shadowStrength, 1.0f, visibility);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user