fixing CSM gaps
parent
a55e33f9a9
commit
314b308840
|
@ -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.
|
@ -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 inc = 1.0 / 1024.0;
|
||||||
|
|
||||||
|
float shadowFactor = 0;
|
||||||
|
for (int row = -1; row <= 1; row++)
|
||||||
|
{
|
||||||
|
for (int col = -1; col <= 1; col++)
|
||||||
|
{
|
||||||
float closestDepth;
|
float closestDepth;
|
||||||
if (shadowCascadeIndex == 0)
|
if (shadowCascadeIndex == 0)
|
||||||
{
|
{
|
||||||
closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy).r;
|
closestDepth = SAMPLE_TEXTURE(shadowMapOne, projectionCoords.xy + float2(row, col) * inc).r;
|
||||||
}
|
}
|
||||||
else if (shadowCascadeIndex == 1)
|
else if (shadowCascadeIndex == 1)
|
||||||
{
|
{
|
||||||
closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy).r;
|
closestDepth = SAMPLE_TEXTURE(shadowMapTwo, projectionCoords.xy + float2(row, col) * inc).r;
|
||||||
}
|
}
|
||||||
else if (shadowCascadeIndex == 2)
|
else if (shadowCascadeIndex == 2)
|
||||||
{
|
{
|
||||||
closestDepth = SAMPLE_TEXTURE(shadowMapThree, projectionCoords.xy).r;
|
closestDepth = SAMPLE_TEXTURE(shadowMapThree, projectionCoords.xy + float2(row, col) * inc).r;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
closestDepth = SAMPLE_TEXTURE(shadowMapFour, projectionCoords.xy).r;
|
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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
24
Renderer.cs
24
Renderer.cs
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,8 +269,6 @@ namespace Kav
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue