I've been trying to get my cascaded shadow maps looking right for a while. I managed to fix the shimmering and most of the quantization artifacts, but for some reason the shadows still look really blocky. I'm using a resolution of 1024x1024. Here are images of the bounding boxes used for the orthographic matrices, the camera frustum, and the resulting shadows:
This is a snippet of the code I'm using to generate the bounds for the orthographic matrix:
for (int i = 0; i < numShadowCascades; i++) {
//transform camera frustum split corners to world space
tempShadowBounds[4 * i + 0] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+0], 1.0f); //upper left
tempShadowBounds[4 * i + 1] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+1], 1.0f); //upper right
tempShadowBounds[4 * i + 2] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+2], 1.0f); //bottom left
tempShadowBounds[4 * i + 3] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+3], 1.0f); //bottom right
tempShadowBounds[4 * i + 4] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+4], 1.0f); //next upper left
tempShadowBounds[4 * i + 5] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+5], 1.0f); //next upper right
tempShadowBounds[4 * i + 6] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+6], 1.0f); //next bottom left
tempShadowBounds[4 * i + 7] = cameraViewToWorld * glm::vec4(cascadedShadowBounds[4*i+7], 1.0f); //next bottom right
glm::vec3 frustumCenter = glm::vec3(0.0f);
for (int j = 4 * i; j < ((4 * i) + 8); j++) {
frustumCenter += tempShadowBounds[j];
}
frustumCenter /= 8.0f;
dirLightViews[i] = glm::lookAt(frustumCenter, frustumCenter - lightDir, glm::vec3(0.0f, 1.0f, 0.0f));
float maxX = std::numeric_limits<float>::lowest(); float maxY = maxX;
float maxZ = maxX;
float minX = std::numeric_limits<float>::max(); float minY = minX;
float minZ = minX;
using std::max; using std::min;
for (int j = 4 * i; j < ((4 * i) + 8); j++) {
glm::vec3 temp = dirLightViews[i] * glm::vec4(tempShadowBounds[j], 1.0f);
maxX = max(maxX, temp.x);
minX = min(minX, temp.x);
maxY = max(maxY, temp.y);
minY = min(minY, temp.y);
maxZ = max(maxZ, temp.z);
minZ = min(minZ, temp.z);
}
glm::mat4 cascadedOrtho = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);
cascadedShadowMatrices[i] = cascadedOrtho * dirLightViews[i];
}
The code is somewhat rough right now, but that's the gist of how I'm generating the bounding boxes. Another big problem is that you can see the transition between the shadow maps as you move the camera, and I'm not sure how to smooth that transition.
The seams seem hard to eliminate. On a side note why don't people divide the world space into directional light chunks where each shadow map is assigned a section of world space, as opposed to cascaded shadow maps? Or am I missing something?