Hi all, last weeks I've been trying to get my tight fit shadow frustums for CSM to work, but no luck so far. According to the articles I used as inspiration, plus a lot of debugging, the math seems OK. One thing I couldn't explain yet, is why the final corners in worldspace seemed orientated around 0 0 0 in worldspace, instead of the primary camera position. Any idea what I might be doing wrong?
CR_MATRIX4X4 lightTransformMat = CMathHelper::CreateViewMatrix(CR_VECTOR3(0.0f), light->GetDirection(), camera.mBaseUp, nullptr);
const std::vector<CR_VECTOR2> &cascades = mEntityAdminPtr->GetRendererSettings().GetCSMCascades();
for(size_t i=0;i<light->mShadowCascadeIndices.size();++i)
{
// 1 + 2: find the 8 viewfrustum corners in WorldSpace
CAMERA_PROJECTION projProps = primaryCam->GetProjectionSettings();
projProps.NearPlane = cascades[i].x;
projProps.FarPlane = cascades[i].y;
CCCamera *cascadeCamera = mEntityAdminPtr->GetComponent<CCCamera>(light->mShadowCascadeIndices[i]);
cascadeCamera->mFrustum.mCornersWorldspace = CMathHelper::GetViewFrustumCorners(primaryCamTransform->GetPos(), primaryCam->mAxis, projProps);
CR_VECTOR3 centroid = CMathHelper::Vec3Center(cascadeCamera->mFrustum.mCornersWorldspace);
// 3: transforms 8 corners to lightspace
std::vector<CR_VECTOR3> frustumCornersL(8);
for(size_t j=0;j<8;++j)
{
frustumCornersL[j] = CMathHelper::TransformVec3Coord(cascadeCamera->mFrustum.mCornersWorldspace[j], lightTransformMat);
}
// 4: calculate AABB in lightspace, min/max XYZ
CR_AABB lightspaceAABB = CMathHelper::GetAABBFromFrustum(frustumCornersL);
// 5. Find near plane center in lightspace
CR_VECTOR3 nearPlaneCenter = lightspaceAABB.Center;;
nearPlaneCenter.z = lightspaceAABB.Min.z;
// 6. Transform near plane center back to worlspace
CR_MATRIX4X4 invLightTransformMat = CMathHelper::MatrixInverse(lightTransformMat);
nearPlaneCenter = CMathHelper::TransformVec3Coord(nearPlaneCenter, invLightTransformMat);
cascadeCamera->mFrustum.mNearPlaneCenter = nearPlaneCenter; // for debug drawing
// 7. Transform view frustum from world to lightspace, with correct position
CR_MATRIX4X4 newLightTransformMat = CMathHelper::CreateViewMatrix(nearPlaneCenter, centroid, camera.mBaseUp, nullptr);
std::vector<CR_VECTOR3> frustumCornersW(8);
for(size_t w=0;w<8;++w)
{
frustumCornersW[w] = CMathHelper::TransformVec3Coord(cascadeCamera->mFrustum.mCornersWorldspace[w], newLightTransformMat);
}
// 8. create the final bounding box for projection
CR_AABB finalAABB = CMathHelper::GetAABBFromFrustum(frustumCornersW);
CAMERA_PROJECTION orthoBox;
orthoBox.SetOrthographic(finalAABB.Max.x - finalAABB.Min.x, finalAABB.Max.y - finalAABB.Min.y, finalAABB.Min.z, finalAABB.Max.z);
cascadeCamera->SetProjection(orthoBox);
// VIEW MATRIX
CCTransform *cascadeTransform = mEntityAdminPtr->GetComponent<CCTransform>(light->mShadowCascadeIndices[i]);
cascadeTransform->SetPos(nearPlaneCenter);
cascadeTransform->SetLookAt(centroid);
}