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 LightSpaceMatrixFour { get; set; }
public Matrix ViewMatrix { get; set; } public Matrix ViewMatrix { get; set; }
public float[] CascadeFarPlanes; public readonly float[] CascadeFarPlanes;
public Vector3 DirectionalLightColor { get; set; } public Vector3 DirectionalLightColor { get; set; }
public Vector3 DirectionalLightDirection { 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 int shadowCascadeIndex = 0; // 0 is closest
for (int i = 0; i < NUM_SHADOW_CASCADES; i++) for (int i = 0; i < NUM_SHADOW_CASCADES; i++)
{ {
if (positionCameraSpace.z < CascadeFarPlanes[i]) if (abs(positionCameraSpace.z) < CascadeFarPlanes[i])
{ {
shadowCascadeIndex = i; shadowCascadeIndex = i;
break; break;
@ -146,35 +146,61 @@ float ComputeShadow(float3 positionWorldSpace, float3 N, float L)
projectionCoords.x = (projectionCoords.x * 0.5) + 0.5; projectionCoords.x = (projectionCoords.x * 0.5) + 0.5;
projectionCoords.y = (projectionCoords.y * 0.5) + 0.5; projectionCoords.y = (projectionCoords.y * 0.5) + 0.5;
projectionCoords.y *= -1; projectionCoords.y *= -1;
// in XNA clip z is 0 to 1 already
float closestDepth; float inc = 1.0 / 1024.0;
if (shadowCascadeIndex == 0)
float shadowFactor = 0;
for (int row = -1; row <= 1; row++)
{ {
closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy).r; for (int col = -1; col <= 1; col++)
} {
else if (shadowCascadeIndex == 1) float closestDepth;
{ if (shadowCascadeIndex == 0)
closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy).r; {
} closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy + float2(row, col) * inc).r;
else if (shadowCascadeIndex == 2) }
{ else if (shadowCascadeIndex == 1)
closestDepth = SAMPLE_TEXTURE(shadowMapThree, projectionCoords.xy).r; {
} closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy + float2(row, col) * inc).r;
else }
{ else if (shadowCascadeIndex == 2)
closestDepth = SAMPLE_TEXTURE(shadowMapFour, projectionCoords.xy).r; {
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; shadowFactor = 1.0;
}
else
{
return 0.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( float3 ComputeLight(
@ -239,7 +265,6 @@ float4 ComputeColor(
float3 radiance = DirectionalLightColor; float3 radiance = DirectionalLightColor;
float shadow = ComputeShadow(worldPosition, N, L); float shadow = ComputeShadow(worldPosition, N, L);
Lo += ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, (1.0 - shadow)); Lo += ComputeLight(L, radiance, F0, V, N, albedo, metallic, roughness, (1.0 - shadow));
float3 ambient = float3(0.03, 0.03, 0.03) * albedo; // * AO; float3 ambient = float3(0.03, 0.03, 0.03) * albedo; // * AO;

View File

@ -24,7 +24,7 @@ VertexShaderOutput main_vs(VertexShaderInput input)
VertexShaderOutput output; VertexShaderOutput output;
output.Position = mul(input.Position, ModelViewProjection); output.Position = mul(input.Position, ModelViewProjection);
output.Depth = output.Position.z / output.Position.w; output.Depth = output.Position.z;
return output; return output;
} }

View File

@ -8,6 +8,7 @@ namespace Kav
{ {
private const int MAX_SHADOW_CASCADES = 4; private const int MAX_SHADOW_CASCADES = 4;
private GraphicsDevice GraphicsDevice { get; } private GraphicsDevice GraphicsDevice { get; }
private int RenderDimensionsX { get; } private int RenderDimensionsX { get; }
private int RenderDimensionsY { get; } private int RenderDimensionsY { get; }
@ -235,11 +236,11 @@ namespace Kav
// render the individual shadow maps // render the individual shadow maps
var frustumDistance = camera.FarPlane - camera.NearPlane; var previousFarPlane = camera.NearPlane;
var sectionDistance = frustumDistance / NumShadowCascades;
for (var i = 0; i < NumShadowCascades; i++) for (var i = 0; i < NumShadowCascades; i++)
{ {
var farPlane = camera.FarPlane / (MathHelper.Max((NumShadowCascades - i - 1) * 5f, 1f));
// divide the view frustum // divide the view frustum
var shadowCamera = new PerspectiveCamera( var shadowCamera = new PerspectiveCamera(
camera.Position, camera.Position,
@ -247,11 +248,13 @@ namespace Kav
camera.Up, camera.Up,
camera.FieldOfView, camera.FieldOfView,
camera.AspectRatio, camera.AspectRatio,
camera.NearPlane + (i * sectionDistance), previousFarPlane,
camera.NearPlane + ((i + 1) * sectionDistance) farPlane
); );
RenderShadowMap(shadowCamera, modelTransforms, directionalLight, i); RenderShadowMap(shadowCamera, modelTransforms, directionalLight, i);
previousFarPlane = farPlane;
} }
} }
@ -265,9 +268,7 @@ namespace Kav
GraphicsDevice.Clear(Color.White); GraphicsDevice.Clear(Color.White);
GraphicsDevice.DepthStencilState = DepthStencilState.Default; GraphicsDevice.DepthStencilState = DepthStencilState.Default;
GraphicsDevice.BlendState = BlendState.Opaque; 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); var cameraBoundingFrustum = new BoundingFrustum(camera.View * camera.Projection);
Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners(); Vector3[] frustumCorners = cameraBoundingFrustum.GetCorners();
@ -278,7 +279,7 @@ namespace Kav
} }
frustumCenter /= 8f; 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++) for (var i = 0; i < frustumCorners.Length; i++)
{ {
@ -286,16 +287,15 @@ namespace Kav
} }
BoundingBox lightBox = BoundingBox.CreateFromPoints(frustumCorners); 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( SimpleDepthEffect.Projection = Matrix.CreateOrthographicOffCenter(
lightBox.Min.X, lightBox.Min.X,
lightBox.Max.X, lightBox.Max.X,
lightBox.Min.Y, lightBox.Min.Y,
lightBox.Max.Y, lightBox.Max.Y,
0, -lightBox.Max.Z - 10f, // TODO: near clip plane needs scene AABB info to get rid of this magic value
lightBox.Max.Z - lightBox.Min.Z -lightBox.Min.Z
); );
var lightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection; var lightSpaceMatrix = SimpleDepthEffect.View * SimpleDepthEffect.Projection;