fixing CSM gaps

pull/2/head
cosmonaut 2020-09-18 22:43:12 -07:00
parent a55e33f9a9
commit 314b308840
6 changed files with 64 additions and 39 deletions

View File

@ -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; }

Binary file not shown.

Binary file not shown.

View File

@ -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;

View File

@ -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;
}

View File

@ -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;