From 314b3088404bcb3a1d5d9761f3c1871d28d317ff Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Fri, 18 Sep 2020 22:43:12 -0700 Subject: [PATCH] fixing CSM gaps --- Effects/DeferredPBREffect.cs | 2 +- Effects/FXB/DeferredPBREffect.fxb | Bin 55208 -> 55496 bytes Effects/FXB/SimpleDepthEffect.fxb | Bin 848 -> 832 bytes Effects/HLSL/DeferredPBREffect.fx | 73 ++++++++++++++++++++---------- Effects/HLSL/SimpleDepthEffect.fx | 2 +- Renderer.cs | 26 +++++------ 6 files changed, 64 insertions(+), 39 deletions(-) diff --git a/Effects/DeferredPBREffect.cs b/Effects/DeferredPBREffect.cs index 1ad21d4..181d1ec 100644 --- a/Effects/DeferredPBREffect.cs +++ b/Effects/DeferredPBREffect.cs @@ -46,7 +46,7 @@ namespace Kav public Matrix LightSpaceMatrixFour { get; set; } public Matrix ViewMatrix { get; set; } - public float[] CascadeFarPlanes; + public readonly float[] CascadeFarPlanes; public Vector3 DirectionalLightColor { get; set; } public Vector3 DirectionalLightDirection { get; set; } diff --git a/Effects/FXB/DeferredPBREffect.fxb b/Effects/FXB/DeferredPBREffect.fxb index cc460f8a1157194da6882a0633a2c72f1fa92235..c5b5a89f711c3908e1db68c776981bd68f368ea5 100644 GIT binary patch literal 55496 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

@zjj)mjE9A{(T z_;KM_I1bG5XJgiu(u^HM6UWpn2lTlDYQ9*53Z*gjjAIa{@=@9*dE$G&?W z{KEQozLKzeB8n;L{Cl=3Q&wK9*8M4)6BC!SPu-JhTI*59H8MBG26L6t{Zq&tIWjdd zfj;H5OFh~>Y-Pr7Qro4Dv-{#48^-SM=g8E=Zx*ooE6;8cd(C)hmv)T{vsLyN+kOlBT$kNztY1|Yqxy52>>TEv zHqvwEC_TrqM?1_9@}l?N#L-^)tzEmnf4`d}Qxm^Nzj6P5X=ThaS#kT$TA4#Q|JaSyA>T#8;)@Aw(965#@HOh{INidj7s|<3hCUABZJgY76O`SCE z4(^L9hY*R79tkM2|dq|QfeoWAPkl=qoFm+o#Dcl+#gcz5wG zGBLJbEwh+Y!#>Pb%)VsozK~;;GMv@4?+%^27U(-&vxl@{<|ehhCiG3*(Vba!>w;hC zm_1LJeFJ~AUpq}5%GhW1`%_9)nKw7iF$G;^b-5mnalI+zF$H;}zMD%OW1IIk?=s`7 zZcj6ZSoGbAd)aVh`+CmYcxl7zo%7*ra*kO~uCh#X!}t4~UT+3@VjOA3=TS}P75fJ! zb&j=PjT%a^#$4_L`;0rG*FDYLA`kS*JWN-P*}S>6@$NACIqmZp*rbhwTB`eL zHEC@uh5bp)pROjXAL_9EteTAG&luovXnnLy7%tAovL@JuUr}}?HkLk-g!rM zThFeZ?5@Flf1#Y+QrbTc7Sce8%D-}&2Jgy7)>8AFg%&S%E007Mr6_Nk| diff --git a/Effects/HLSL/DeferredPBREffect.fx b/Effects/HLSL/DeferredPBREffect.fx index 0ce4d56..14a58c2 100644 --- a/Effects/HLSL/DeferredPBREffect.fx +++ b/Effects/HLSL/DeferredPBREffect.fx @@ -111,7 +111,7 @@ float ComputeShadow(float3 positionWorldSpace, float3 N, float L) int shadowCascadeIndex = 0; // 0 is closest for (int i = 0; i < NUM_SHADOW_CASCADES; i++) { - if (positionCameraSpace.z < CascadeFarPlanes[i]) + if (abs(positionCameraSpace.z) < CascadeFarPlanes[i]) { shadowCascadeIndex = i; break; @@ -146,35 +146,61 @@ float ComputeShadow(float3 positionWorldSpace, float3 N, float L) projectionCoords.x = (projectionCoords.x * 0.5) + 0.5; projectionCoords.y = (projectionCoords.y * 0.5) + 0.5; projectionCoords.y *= -1; + // in XNA clip z is 0 to 1 already - float closestDepth; - if (shadowCascadeIndex == 0) + float inc = 1.0 / 1024.0; + + float shadowFactor = 0; + for (int row = -1; row <= 1; row++) { - closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy).r; - } - else if (shadowCascadeIndex == 1) - { - closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy).r; - } - else if (shadowCascadeIndex == 2) - { - closestDepth = SAMPLE_TEXTURE(shadowMapThree, projectionCoords.xy).r; - } - else - { - closestDepth = SAMPLE_TEXTURE(shadowMapFour, projectionCoords.xy).r; + for (int col = -1; col <= 1; col++) + { + float closestDepth; + if (shadowCascadeIndex == 0) + { + closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy + float2(row, col) * inc).r; + } + else if (shadowCascadeIndex == 1) + { + closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy + float2(row, col) * inc).r; + } + else if (shadowCascadeIndex == 2) + { + closestDepth = SAMPLE_TEXTURE(shadowMapThree, projectionCoords.xy + float2(row, col) * inc).r; + } + else + { + closestDepth = SAMPLE_TEXTURE(shadowMapFour, projectionCoords.xy + float2(row, col) * inc).r; + } + shadowFactor += projectionCoords.z - bias > closestDepth ? 1.0 : 0.0; + } } - float currentDepth = projectionCoords.z; + shadowFactor /= 9.0; - if (currentDepth - bias > closestDepth) + if (projectionCoords.z > 1.0) { - return 1.0; - } - else - { - return 0.0; + shadowFactor = 1.0; } + + return shadowFactor; + + + // float currentDepth = projectionCoords.z; + + // if (currentDepth > 1.0) + // { + // return 0.0; + // } + + // if (currentDepth - bias > closestDepth) + // { + // return 1.0; + // } + // else + // { + // return 0.0; + // } } float3 ComputeLight( @@ -239,7 +265,6 @@ float4 ComputeColor( float3 radiance = DirectionalLightColor; float shadow = ComputeShadow(worldPosition, N, L); - Lo += ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, (1.0 - shadow)); float3 ambient = float3(0.03, 0.03, 0.03) * albedo; // * AO; diff --git a/Effects/HLSL/SimpleDepthEffect.fx b/Effects/HLSL/SimpleDepthEffect.fx index f813bd7..3598eb5 100644 --- a/Effects/HLSL/SimpleDepthEffect.fx +++ b/Effects/HLSL/SimpleDepthEffect.fx @@ -24,7 +24,7 @@ VertexShaderOutput main_vs(VertexShaderInput input) VertexShaderOutput output; output.Position = mul(input.Position, ModelViewProjection); - output.Depth = output.Position.z / output.Position.w; + output.Depth = output.Position.z; return output; } diff --git a/Renderer.cs b/Renderer.cs index 8d05f96..b16a3b7 100644 --- a/Renderer.cs +++ b/Renderer.cs @@ -8,6 +8,7 @@ namespace Kav { private const int MAX_SHADOW_CASCADES = 4; + private GraphicsDevice GraphicsDevice { get; } private int RenderDimensionsX { get; } private int RenderDimensionsY { get; } @@ -235,11 +236,11 @@ namespace Kav // render the individual shadow maps - var frustumDistance = camera.FarPlane - camera.NearPlane; - var sectionDistance = frustumDistance / NumShadowCascades; - + var previousFarPlane = camera.NearPlane; for (var i = 0; i < NumShadowCascades; i++) { + var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 5f, 1f)); + // divide the view frustum var shadowCamera = new PerspectiveCamera( camera.Position, @@ -247,11 +248,13 @@ namespace Kav camera.Up, camera.FieldOfView, camera.AspectRatio, - camera.NearPlane + (i * sectionDistance), - camera.NearPlane + ((i + 1) * sectionDistance) + previousFarPlane, + farPlane ); RenderShadowMap(shadowCamera, modelTransforms, directionalLight, i); + + previousFarPlane = farPlane; } } @@ -265,9 +268,7 @@ namespace Kav GraphicsDevice.Clear(Color.White); GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.BlendState = BlendState.Opaque; - - var right = Vector3.Cross(Vector3.Up, directionalLight.Direction); - var up = Vector3.Cross(directionalLight.Direction, right); + var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection); Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); @@ -278,7 +279,7 @@ namespace Kav } frustumCenter /= 8f; - var lightView = Matrix.CreateLookAt(frustumCenter, frustumCenter - directionalLight.Direction, camera.View.Right); + var lightView = Matrix.CreateLookAt(frustumCenter + directionalLight.Direction, frustumCenter, Vector3.Backward); for (var i = 0; i < frustumCorners.Length; i++) { @@ -286,16 +287,15 @@ namespace Kav } BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); - Vector3 lightPosition = frustumCenter + directionalLight.Direction * -lightBox.Min.Z; - SimpleDepthEffect.View = Matrix.CreateLookAt(lightPosition, frustumCenter, camera.View.Right); + SimpleDepthEffect.View = lightView; SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter( lightBox.Min.X, lightBox.Max.X, lightBox.Min.Y, lightBox.Max.Y, - 0, - lightBox.Max.Z - lightBox.Min.Z + -lightBox.Max.Z - 10f, // TODO: near clip plane needs scene AABB info to get rid of this magic value + -lightBox.Min.Z ); var lightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection;