Well, here's the code for the frustum creation. It's possible the issue is from convention differences between XNA (what the sample uses) and SharpDX (which is what we're using), but I wouldn't really know
public static void Draw()
{
LightDirection = Environment.SkyDome.SunLight.LightDirection;
Engine.Context.OutputMerger.SetTargets(depthStencil.DepthStencilView, depthMap);
Engine.Context.ClearRenderTargetView(depthMap, Color.White);
// Get corners of the main camera's bounding frustum
var viewMatrix = World.Camera.View;
frustumCornersWS = World.Camera.BoundingFrustum.GetCorners();
//frustumCornersVS = Vector3.Transform(frustumCornersWS, ref viewMatrix);
var vector = new Vector4[8];
Vector3.Transform(frustumCornersWS, ref viewMatrix, vector);
for(var i = 0; i < 8; i++)
{
frustumCornersVS[i] = new Vector3(vector[i].X, vector[i].Y, vector[i].Z);
}
for(var i = 0; i < 4; i++)
{
farFrustumCornersVS[i] = frustumCornersVS[i + 4];
}
// Calculate the cascade splits. We calculate these so that each successive
// split is larger than the previous, giving the closest split the most amount
// of shadow detail.
const float n = Splits;
const float near = 1;
var far = World.Camera.FarPlaneDistance;
splitDepths[0] = near;
splitDepths[Splits] = far;
const float splitConstant = 0.95f; //0.95f
for(var i = 1; i < splitDepths.Length - 1; i++)
{
splitDepths[i] = splitConstant * near * (float)Math.Pow(far / near, i / n) + (1.0f - splitConstant) * ((near + (i / n)) * (far - near));
}
// Render our scene geometry to each split of the cascade
for(var i = 0; i < Splits; i++)
{
var minZ = splitDepths[i];
var maxZ = splitDepths[i + 1];
lightCameras[i] = CalculateFrustum(minZ, maxZ);
RenderDepthMap(i);
}
Engine.Context.Rasterizer.SetViewports(Engine.Viewport);
RenderShadowMap();
}
private static OrthographicCamera CalculateFrustum(float minZ, float maxZ)
{
// Shorten the view frustum according to the shadow view distance
var cameraMatrix = World.Camera.World;
for(var i = 0; i < 4; i++)
splitFrustumCornersVS[i] = frustumCornersVS[i + 4] * (minZ / World.Camera.FarPlaneDistance);
for(var i = 4; i < 8; i++)
splitFrustumCornersVS[i] = frustumCornersVS[i] * (maxZ / World.Camera.FarPlaneDistance);
var vector = new Vector4[8];
Vector3.Transform(splitFrustumCornersVS, ref cameraMatrix, vector);
for(var i = 0; i < 8; i++)
{
frustumCornersWS[i] = new Vector3(vector[i].X, vector[i].Y, vector[i].Z);
}
// Position the shadow-caster camera so that it's looking at the centroid,
// and backed up in the direction of the sunlight
var viewMatrix = Matrix.LookAtRH(Vector3.Zero - (LightDirection*100), Vector3.Zero, new Vector3(0, 1, 0));
// Determine the position of the frustum corners in light space
Vector3.Transform(frustumCornersWS, ref viewMatrix, vector);
for(var i = 0; i < 8; i++)
{
frustumCornersLS[i] = new Vector3(vector[i].X, vector[i].Y, vector[i].Z);
}
// Calculate an orthographic projection by sizing a bounding box
// to the frustum coordinates in light space
var mins = frustumCornersLS[0];
var maxes = frustumCornersLS[0];
for(var i = 1; i < 8; i++)
{
mins = Vector3.Min(mins, frustumCornersLS[i]);
maxes = Vector3.Max(maxes, frustumCornersLS[i]);
}
if(toggleJitter)
{
// We snap the camera to 1 pixel increments so that moving the camera does not cause the shadows to jitter.
// This is a matter of integer dividing by the world space size of a texel
var diagonalLength = (frustumCornersWS[0] - frustumCornersWS[6]).Length();
diagonalLength += 2; //Without this, the shadow map isn't big enough in the world.
var worldsUnitsPerTexel = diagonalLength / (ShadowResolution * Splits);
var vBorderOffset = (new Vector3(diagonalLength, diagonalLength, diagonalLength) - (maxes - mins)) * 0.5f;
maxes += vBorderOffset;
mins -= vBorderOffset;
mins /= worldsUnitsPerTexel;
mins.X = (float)Math.Floor(mins.X);
mins.Y = (float)Math.Floor(mins.Y);
mins.Z = (float)Math.Floor(mins.Z);
mins *= worldsUnitsPerTexel;
maxes /= worldsUnitsPerTexel;
maxes.X = (float)Math.Floor(maxes.X);
maxes.Y = (float)Math.Floor(maxes.Y);
maxes.Z = (float)Math.Floor(maxes.Z);
maxes *= worldsUnitsPerTexel;
}
var lightCamera = new OrthographicCamera(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - nearClipOffset, -mins.Z);
lightCamera.SetViewMatrix(ref viewMatrix);
return lightCamera;
}