i'm trying to implement Cascaded Shadow mapping using opengl but i got some problems.
i start by dividing my view frustum to three splits and for each split it has a
1- near
2- far
3- corners (corners of the frustum of this specific split in world space)
4- depth map (2D Texture with dimensions of 1024 * 1024)
and for each split i start with calculating its corners as follows and with these corners in world space i calculate frustum center that i will be using to calculate light view matrix.
float width = float(mRenderer->GetGame()->GetWidth());
float height = float(mRenderer->GetGame()->GetHeight());
mProjMatrix = glm::perspective(glm::radians(90.0f), (float)width / (float)height, mNear, mFar);
mViewMatrix = mRenderer->GetView();
glm::mat4 viewProj = mProjMatrix * mViewMatrix;
glm::vec3 frustumCorners[8] =
{
glm::vec3(-1.0f, 1.0f, -1.0f),
glm::vec3(1.0f, 1.0f, -1.0f),
glm::vec3(1.0f, -1.0f, -1.0f),
glm::vec3(-1.0f, -1.0f, -1.0f),
glm::vec3(-1.0f, 1.0f, 1.0f),
glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(1.0f, -1.0f, 1.0f),
glm::vec3(-1.0f, -1.0f, 1.0f),
};
for (int i = 0; i < 8; ++i)
{
glm::vec4 inversePoint = glm::inverse(viewProj) * glm::vec4(frustumCorners[i], 1.0f);
mCorners[i] = glm::vec3(inversePoint / inversePoint.w);
}
for (int i = 0; i < 8; ++i)
{
mFrustumCenter += mCorners[i];
}
mFrustumCenter /= 8.0f;
after i have the frustum center of this specific split i need to figure out the light view matrix that i will be using to render the scene (between near and far of the split) and i do that as follows.
mRenderer->GetLightDirection() = {0.0f, 20.0f, -1.0f}
glm::vec3 lightDir = glm::normalize(mRenderer->GetLightDirection());
glm::vec3 lightPos = mFrustumCenter + lightDir;
mLightView = glm::lookAt(lightPos, mFrustumCenter , glm::vec3(0.0f, 1.0f, 0.0f));
and finally the last thing i do is calculating the orthographic matrix of the light using the split frustum corners after i transform them into light space with the light view matrix i calculated the previous step.
for (int i = 0; i < 8; ++i)
{
mCorners[i] = glm::vec3(mLightView * glm::vec4(mCorners[i], 1.0f));
}
float minX = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::min();
float minY = std::numeric_limits<float>::max();
float maxY = std::numeric_limits<float>::min();
float minZ = std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::min();
for (int i = 0; i < 8; ++i)
{
minX = std::min(minX, mCorners[i].x);
maxX = std::max(maxX, mCorners[i].x);
minY = std::min(minY, mCorners[i].y);
maxY = std::max(maxY, mCorners[i].y);
minZ = std::min(minZ, mCorners[i].z);
maxZ = std::max(maxZ, mCorners[i].z);
}
mLightProj = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);
when i run my program i have my shadow working correctly
but when i move the camera back until the floor enter the range of the second split instead of using the second split shadow it disappears but when i start to move the camera up and down the shadow appears again so i think the problem is in calculating light view matrix but i couldn't figure it out.
these are the ranges of my splits
near-> far
0.1 -> 30.0
0.1 -> 50.0
0.1 -> 1000.0