From 59c52fc94cf7261816f0106118268d7b50635219 Mon Sep 17 00:00:00 2001 From: marauder2k7 Date: Mon, 6 Jan 2025 14:24:39 +0000 Subject: [PATCH] Fix for bug reported by Rod Reverted to the original calc clip space aabb to fix flickering bug reported by Rod in discord. Unfortunately this reintroduces the original issue of faint shadows showing at all times on the first split. But shadows render correctly where they are expected. A full review of pssm is required for later updates to be made. --- .../lighting/shadowMap/pssmLightShadowMap.cpp | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp b/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp index a6dc0294e..54e498667 100644 --- a/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp +++ b/Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp @@ -135,29 +135,30 @@ void PSSMLightShadowMap::_calcSplitPos(const Frustum& currFrustum) Box3F PSSMLightShadowMap::_calcClipSpaceAABB(const Frustum& f, const MatrixF& transform, F32 farDist) { - PROFILE_SCOPE(PSSMLightShadowMap_calcClipSpaceAABB); - - // Transform frustum corners to light space. - Point3F transformedPoints[8]; + // Calculate frustum center + Point3F center(0, 0, 0); const Point3F* frustumPoints = f.getPoints(); - for (U32 i = 0; i < 8; i++) { - transformedPoints[i] = frustumPoints[i]; - transform.mulP(transformedPoints[i]); + for (U32 i = 0; i < 8; i++) + { + const Point3F& pt = frustumPoints[i]; + center += pt; } + center /= 8; - // Compute the AABB for the transformed points. + // Calculate frustum bounding sphere radius + F32 radius = 0.0f; + for (U32 i = 0; i < 8; i++) + radius = getMax(radius, (frustumPoints[i] - center).lenSquared()); + radius = mFloor(mSqrt(radius)); + + // Now build box for sphere Box3F result; - result.minExtents.set(F32_MAX, F32_MAX, F32_MAX); - result.maxExtents.set(-F32_MAX, -F32_MAX, -F32_MAX); + Point3F radiusBox(radius, radius, radius); + result.minExtents = center - radiusBox; + result.maxExtents = center + radiusBox; - for (U32 i = 0; i < 8; i++) { - result.minExtents.setMin(transformedPoints[i]); - result.maxExtents.setMax(transformedPoints[i]); - } - - // Clamp Z to within near and far distances to avoid over-extension. - result.minExtents.z = getMax(result.minExtents.z, 0.0f); // Z must be non-negative in light space. - result.maxExtents.z = getMin(result.maxExtents.z, farDist); + // Transform to light projection space + transform.mul(result); return result; } @@ -174,9 +175,10 @@ void PSSMLightShadowMap::_roundProjection(const MatrixF& lightMat, const MatrixF lightProjection.mul(origin); origin /= origin.w; - // Convert to texture space (based on shadow map resolution). - F32 texelWidth = mShadowMapTex->getWidth() / (mNumSplits < 4 ? mNumSplits : 2); - Point2F texelScale(texelWidth * 0.5f, mShadowMapTex->getHeight() * 0.5f); + // Convert to shadow map texel space. + const F32 texelWidth = mShadowMapTex->getWidth() / (mNumSplits < 4 ? mNumSplits : 2); + const F32 texelHeight = mShadowMapTex->getHeight(); + Point2F texelScale(texelWidth * 0.5f, texelHeight * 0.5f); // Adjust origin to align to nearest texel. Point2F originTexelSpace(origin.x * texelScale.x, origin.y * texelScale.y);