After randomly playing around with the ShadowDist and BackupDistance I've managed to get a shadow map looking like this:
http://cl.ly/image/1y41393j232eIf not I'd be happy to know what I'm doing wrong, as this seems to be an issue not with the code but the settings.
I'm still not sure if this is a correct image that I should be getting for the shadowmap atlas but I'm going to assume so at the moment and continue implementing the actual shadow projection.
Doing this deferred just means that I have to render the shadows to a texture, that has been cleared white, right ? And afterwards multiply this by the lighting...?
Update: Well now this seems to look a lot better.
http://cl.ly/image/170r1c2L0y0a/Project%202012-11-27%2016-11-13-27.jpgWhat I did was invert the light direction. Not sure why MJP's light direction was already inverted there(?)
For completeness I'm going to post the function that constructs the light's view and projection matrix again:
void DirectionalLight::CalculateLightProjection(BaseCamera* camera, UINT &cascadeIdx,
const float &sMapSize)
{
const float CascadeSplits[4] = { 0.125f, 0.25f, 0.5f, 1.0f };
const float Bias = 0.005f;
const float ShadowDist = 0.2f;
const float BackupDistance = -20.0f;
// Get the 8 points of the view frustum in world space
XMFLOAT3 corner[8];
XMVECTOR frustumCornersWS[8];
camera->ExtractFrustumCorner(corner);
for(UINT i = 0; i < 8; i++)
{
frustumCornersWS[i] = XMLoadFloat3(&corner[i]);
}
float prevSplitDist = cascadeIdx == 0 ? 0.0f : CascadeSplits[cascadeIdx - 1] * ShadowDist;
float splitDist = CascadeSplits[cascadeIdx] * ShadowDist;
// Scale by the shadow view distance
for(UINT i = 0; i < 4; ++i)
{
XMVECTOR cornerRay = XMVectorSubtract(frustumCornersWS[i + 4], frustumCornersWS[i]);
XMVECTOR nearCornerRay = XMVectorScale(cornerRay, prevSplitDist);
XMVECTOR farCornerRay = XMVectorScale(cornerRay, splitDist);
frustumCornersWS[i + 4] = XMVectorAdd(frustumCornersWS[i], farCornerRay);
frustumCornersWS[i] = XMVectorAdd(frustumCornersWS[i], nearCornerRay);
}
// Calculate the centroid of the view frustum
XMVECTOR sphereCenterVec = XMVectorZero();
for(UINT i = 0; i < 8; ++i)
{
sphereCenterVec = XMVectorAdd(sphereCenterVec, frustumCornersWS[i]);
}
sphereCenterVec = XMVectorScale(sphereCenterVec, 1.0f / 8.0f);
// Calculate the radius of a bounding sphere
XMVECTOR sphereRadiusVec = XMVectorZero();
for(UINT i = 0; i < 8; ++i)
{
XMVECTOR dist = XMVector3Length(XMVectorSubtract(frustumCornersWS[i], sphereCenterVec));
sphereRadiusVec = XMVectorMax(sphereRadiusVec, dist);
}
float nearClip = camera->GetNearClip();
sphereRadiusVec = XMVectorRound(sphereRadiusVec);
const float sphereRadius = XMVectorGetX(sphereRadiusVec);
const float backupDist = sphereRadius + nearClip + BackupDistance;
// Get Position of the shadow camera
XMVECTOR shadowCameraPosVec = sphereCenterVec;
XMVECTOR backupDirVec = XMLoadFloat3(&this->direction);
backupDirVec = XMVectorScale(backupDirVec, backupDist);
shadowCameraPosVec = XMVectorAdd(shadowCameraPosVec, backupDirVec);
// Create Orthographic Projection
XMMATRIX orthoProj = XMMatrixOrthographicOffCenterLH(-sphereRadius, sphereRadius, -sphereRadius, sphereRadius,
nearClip, backupDist + sphereRadius);
// Create View Matrix
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 1.0f);
shadowCameraPosVec = XMVectorSetW(shadowCameraPosVec, 1.0f);
sphereCenterVec = XMVectorSetW(sphereCenterVec, 1.0f);
XMMATRIX lightView = XMMatrixLookAtLH(shadowCameraPosVec, sphereCenterVec, up);
// Create the rounding matrix, by projecting the world-space origin and determining
// the fractional offset in texel space
XMMATRIX shadowMatrix = lightView * orthoProj;
XMVECTOR shadowOrigin = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f);
shadowOrigin = XMVector4Transform(shadowOrigin, shadowMatrix);
shadowOrigin = XMVectorScale(shadowOrigin, sMapSize / 2.0f);
XMVECTOR roundedOrigin = XMVectorRound(shadowOrigin);
XMVECTOR roundOffset = XMVectorSubtract(roundedOrigin, shadowOrigin);
roundOffset = XMVectorScale(roundOffset, 2.0f / sMapSize);
roundOffset = XMVectorSetZ(roundOffset, 0.0f);
roundOffset = XMVectorSetW(roundOffset, 0.0f);
orthoProj.r[3] = XMVectorAdd(orthoProj.r[3], roundOffset);
shadowMatrix = XMMatrixMultiplyTranspose(lightView, orthoProj);
// Copy the data into the constant buffer
XMStoreFloat4x4(&this->lightTransformProperties.ViewProjection, shadowMatrix);
}