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 cc460f8..c5b5a89 100644 Binary files a/Effects/FXB/DeferredPBREffect.fxb and b/Effects/FXB/DeferredPBREffect.fxb differ diff --git a/Effects/FXB/SimpleDepthEffect.fxb b/Effects/FXB/SimpleDepthEffect.fxb index 64ee5cd..8e94476 100644 Binary files a/Effects/FXB/SimpleDepthEffect.fxb and b/Effects/FXB/SimpleDepthEffect.fxb differ 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;