/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include #include static const uint MaxCascadeCount = 4; option enum class ShadowmapLightType { Directional, Spot } o_shadowmapLightType = ShadowmapLightType::Directional; ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback { Texture2DArray m_inputShadowmap; RWTexture2DArray m_outputShadowmap; Buffer m_shadowmapIndexTable; StructuredBuffer m_filterParameters; } [numthreads(16,16,1)] void MainCS(uint3 dispatchId: SV_DispatchThreadID) { const float3 inputSize = GetImageSize(PassSrg::m_inputShadowmap); const float3 outputSize = GetImageSize(PassSrg::m_outputShadowmap); const float depthInClip = PassSrg::m_inputShadowmap[dispatchId].r; const uint shadowmapIndex = GetShadowmapIndex( PassSrg::m_shadowmapIndexTable, dispatchId, inputSize.x); if (shadowmapIndex == ~0) { return; // Early return if it is outside of shadowmaps. } const FilterParameter filterParameter = PassSrg::m_filterParameters[shadowmapIndex]; if (!filterParameter.m_isEnabled) { return; // Early return if filter is disabled. } switch (o_shadowmapLightType) { case ShadowmapLightType::Directional: { const float distanceMin = filterParameter.m_lightDistanceOfCameraViewFrustum; // When the light origin is far from the camera view frustum, // the difference of "depthInClip" in the frustum is so small, // and it often causes light bleeding with ESM. // So this converts it to "depth" to emphasize the difference // within the frustum. const float depth = (depthInClip - distanceMin) / (1. - distanceMin); PassSrg::m_outputShadowmap[dispatchId].r = depth; break; } case ShadowmapLightType::Spot: { const float3 coefficients = float3( filterParameter.m_n_f_n, filterParameter.m_n_f, filterParameter.m_f); // With a spot light shadowmap, "depthInClip" is calculated // as a perspective depth, not a orthogonal one. // So the values are concentrated to near 1.0, // and it often causes light bleeding with ESM. // So this converts it to a linear depth to emphasize the // difference like a orthogonal depth. PassSrg::m_outputShadowmap[dispatchId].r = PerspectiveDepthToLinear(depthInClip, coefficients); break; } } }