I put your code between the viewProj and the finalMat compute:
proj = Matrix::OrthographicOffCenter(-1, 1, -1, 1, min.z, max.z); viewProj = view * proj * cropMat; Vector3 shadowOrigin = Vector3::Transform(Vector3::Zero, viewProj); shadowOrigin *= shadowHalfSize; Vector2 roundedOrigin = Vector2(Helpers::MathHelper::Round(shadowOrigin.x), Helpers::MathHelper::Round(shadowOrigin.y)); Vector2 rounding = roundedOrigin - Vector2(shadowOrigin.x, shadowOrigin.y); rounding /= ((float)shadowSize * 0.5f); Matrix roundMatrix = Matrix::Translate(rounding.x, rounding.y, 0.0f); viewProj *= roundMatrix; finalMat = viewProj * textureMat;
I think it works, because the static meshes' shadow is not flickering (I think
This can be solved by the bounding sphere instead of light AABB?
EDIT:
I read your post, and I understand that we need a fix size for the projection (this kills the flickering when rotating the camera) and a little round to texels (which kills the flickering when the camera moves). So I rewrite my code based on your code and the idea:
ComputeFrustumCorners();
// spheres for each split
Vector3 sphereCenter;
for (int i = 0; i < NUM_CORNERS; i++)
{
sphereCenter += frustumCorners[i];
}
sphereCenter /= NUM_CORNERS;
float sphereRadius = Vector3::Distance(sphereCenter, frustumCorners[0]);
float nearClip = 1.0f;
float backupDist = 10.0f + sphereRadius + nearClip;
Vector3 camPos = sphereCenter - light->direction * backupDist;
view = Matrix::LookAt(camPos, sphereCenter, Vector3::Up);
float bounds = sphereRadius * 2.0f;
float farClip = backupDist + sphereRadius;
proj = Matrix::Orthographic(bounds, bounds, nearClip, farClip);
viewProj = view * proj;
// round to texel
origin = Vector3::Transform(Vector3::Zero, viewProj);
origin *= shadowHalfSize;
originRounded.x = Helpers::MathHelper::Round(origin.x);
originRounded.y = Helpers::MathHelper::Round(origin.y);
rounding.x = originRounded.x - origin.x;
rounding.y = originRounded.y - origin.y;
rounding /= shadowHalfSize;
roundingMatrix = Matrix::Translate(rounding.x, rounding.y, 0.0f);
viewProj *= roundingMatrix;
// compute final components
finalMat = viewProj * textureMat;
viewFrustum->Update(viewProj);
Is this code correct? If it is, there are some problem: my character (which moves with the camera) still flickering and the "backupDist" is really game and eyeposition relevant, so I can't hardcode it.
Or am I doing something wrong?