@@ -54,9 +54,7 @@ float2 GetLightShadowAtlasUV(ShadowData shadow, ShadowTileData shadowTile, float
|
||||
|
||||
float SampleShadowMap(Texture2D<float> shadowMap, float2 shadowMapUV, float sceneDepth)
|
||||
{
|
||||
// Single hardware sample with filtering
|
||||
float result = SAMPLE_SHADOW_MAP(shadowMap, shadowMapUV, sceneDepth);
|
||||
|
||||
#if SHADOWS_QUALITY == 1
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(-1, 0), sceneDepth);
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(0, -1), sceneDepth);
|
||||
@@ -64,7 +62,6 @@ float SampleShadowMap(Texture2D<float> shadowMap, float2 shadowMapUV, float scen
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(1, 0), sceneDepth);
|
||||
result = result * (1.0f / 4.0);
|
||||
#elif SHADOWS_QUALITY == 2 || SHADOWS_QUALITY == 3
|
||||
// TODO: implement Percentage-Closer Soft Shadows (PCSS) for Ultra quality
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(-1, -1), sceneDepth);
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(-1, 0), sceneDepth);
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(-1, 1), sceneDepth);
|
||||
@@ -75,10 +72,133 @@ float SampleShadowMap(Texture2D<float> shadowMap, float2 shadowMapUV, float scen
|
||||
result += SAMPLE_SHADOW_MAP_OFFSET(shadowMap, shadowMapUV, int2(1, 1), sceneDepth);
|
||||
result = result * (1.0f / 9.0);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
float SampleShadowMapOptimizedPCFHelper(Texture2D<float> shadowMap, float2 baseUV, float u, float v, float2 shadowMapSizeInv, float sceneDepth)
|
||||
{
|
||||
float2 uv = baseUV + float2(u, v) * shadowMapSizeInv;
|
||||
return SAMPLE_SHADOW_MAP(shadowMap, uv, sceneDepth);
|
||||
}
|
||||
|
||||
// [Shadow map sampling method used in The Witness, https://github.com/TheRealMJP/Shadows]
|
||||
float SampleShadowMapOptimizedPCF(Texture2D<float> shadowMap, float2 shadowMapUV, float sceneDepth)
|
||||
{
|
||||
#if SHADOWS_QUALITY != 0
|
||||
float2 shadowMapSize;
|
||||
shadowMap.GetDimensions(shadowMapSize.x, shadowMapSize.y);
|
||||
|
||||
float2 uv = shadowMapUV.xy * shadowMapSize; // 1 unit - 1 texel
|
||||
float2 shadowMapSizeInv = 1.0f / shadowMapSize;
|
||||
|
||||
float2 baseUV;
|
||||
baseUV.x = floor(uv.x + 0.5);
|
||||
baseUV.y = floor(uv.y + 0.5);
|
||||
float s = (uv.x + 0.5 - baseUV.x);
|
||||
float t = (uv.y + 0.5 - baseUV.y);
|
||||
baseUV -= float2(0.5, 0.5);
|
||||
baseUV *= shadowMapSizeInv;
|
||||
|
||||
float sum = 0;
|
||||
#endif
|
||||
#if SHADOWS_QUALITY == 0
|
||||
return SAMPLE_SHADOW_MAP(shadowMap, shadowMapUV, sceneDepth);
|
||||
#elif SHADOWS_QUALITY == 1
|
||||
float uw0 = (3 - 2 * s);
|
||||
float uw1 = (1 + 2 * s);
|
||||
|
||||
float u0 = (2 - s) / uw0 - 1;
|
||||
float u1 = s / uw1 + 1;
|
||||
|
||||
float vw0 = (3 - 2 * t);
|
||||
float vw1 = (1 + 2 * t);
|
||||
|
||||
float v0 = (2 - t) / vw0 - 1;
|
||||
float v1 = t / vw1 + 1;
|
||||
|
||||
sum += uw0 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw0 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v1, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v1, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
return sum * 1.0f / 16;
|
||||
#elif SHADOWS_QUALITY == 2
|
||||
float uw0 = (4 - 3 * s);
|
||||
float uw1 = 7;
|
||||
float uw2 = (1 + 3 * s);
|
||||
|
||||
float u0 = (3 - 2 * s) / uw0 - 2;
|
||||
float u1 = (3 + s) / uw1;
|
||||
float u2 = s / uw2 + 2;
|
||||
|
||||
float vw0 = (4 - 3 * t);
|
||||
float vw1 = 7;
|
||||
float vw2 = (1 + 3 * t);
|
||||
|
||||
float v0 = (3 - 2 * t) / vw0 - 2;
|
||||
float v1 = (3 + t) / vw1;
|
||||
float v2 = t / vw2 + 2;
|
||||
|
||||
sum += uw0 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v0, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
sum += uw0 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v1, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v1, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v1, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
sum += uw0 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v2, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v2, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v2, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
return sum * 1.0f / 144;
|
||||
#elif SHADOWS_QUALITY == 3
|
||||
float uw0 = (5 * s - 6);
|
||||
float uw1 = (11 * s - 28);
|
||||
float uw2 = -(11 * s + 17);
|
||||
float uw3 = -(5 * s + 1);
|
||||
|
||||
float u0 = (4 * s - 5) / uw0 - 3;
|
||||
float u1 = (4 * s - 16) / uw1 - 1;
|
||||
float u2 = -(7 * s + 5) / uw2 + 1;
|
||||
float u3 = -s / uw3 + 3;
|
||||
|
||||
float vw0 = (5 * t - 6);
|
||||
float vw1 = (11 * t - 28);
|
||||
float vw2 = -(11 * t + 17);
|
||||
float vw3 = -(5 * t + 1);
|
||||
|
||||
float v0 = (4 * t - 5) / vw0 - 3;
|
||||
float v1 = (4 * t - 16) / vw1 - 1;
|
||||
float v2 = -(7 * t + 5) / vw2 + 1;
|
||||
float v3 = -t / vw3 + 3;
|
||||
|
||||
sum += uw0 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v0, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw3 * vw0 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u3, v0, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
sum += uw0 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v1, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v1, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v1, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw3 * vw1 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u3, v1, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
sum += uw0 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v2, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v2, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v2, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw3 * vw2 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u3, v2, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
sum += uw0 * vw3 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u0, v3, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw1 * vw3 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u1, v3, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw2 * vw3 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u2, v3, shadowMapSizeInv, sceneDepth);
|
||||
sum += uw3 * vw3 * SampleShadowMapOptimizedPCFHelper(shadowMap, baseUV, u3, v3, shadowMapSizeInv, sceneDepth);
|
||||
|
||||
return sum * (1.0f / 2704);
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Samples the shadow for the given directional light on the material surface (supports subsurface shadowing)
|
||||
ShadowSample SampleDirectionalLightShadow(LightData light, Buffer<float4> shadowsBuffer, Texture2D<float> shadowMap, GBufferSample gBuffer, float dither = 0.0f)
|
||||
{
|
||||
@@ -143,7 +263,7 @@ ShadowSample SampleDirectionalLightShadow(LightData light, Buffer<float4> shadow
|
||||
float2 shadowMapUV = GetLightShadowAtlasUV(shadow, shadowTile, samplePosition, shadowPosition);
|
||||
|
||||
// Sample shadow map
|
||||
result.SurfaceShadow = SampleShadowMap(shadowMap, shadowMapUV, shadowPosition.z);
|
||||
result.SurfaceShadow = SampleShadowMapOptimizedPCF(shadowMap, shadowMapUV, shadowPosition.z);
|
||||
|
||||
// Increase the sharpness for higher cascades to match the filter radius
|
||||
//const float SharpnessScale[MaxNumCascades] = { 1.0f, 1.5f, 3.0f, 3.5f };
|
||||
@@ -207,7 +327,7 @@ ShadowSample SampleLocalLightShadow(LightData light, Buffer<float4> shadowsBuffe
|
||||
float2 shadowMapUV = GetLightShadowAtlasUV(shadow, shadowTile, samplePosition, shadowPosition);
|
||||
|
||||
// Sample shadow map
|
||||
result.SurfaceShadow = SampleShadowMap(shadowMap, shadowMapUV, shadowPosition.z);
|
||||
result.SurfaceShadow = SampleShadowMapOptimizedPCF(shadowMap, shadowMapUV, shadowPosition.z);
|
||||
|
||||
#if defined(USE_GBUFFER_CUSTOM_DATA)
|
||||
// Subsurface shadowing
|
||||
|
||||
Reference in New Issue
Block a user