CSM shadow errors when models are split

Posted by KaiserJohaan on Game Development See other posts from Game Development or by KaiserJohaan
Published on 2014-08-21T21:47:22Z Indexed on 2014/08/23 22:36 UTC
Read the original article Hit count: 326

Filed under:
|
|

I'm getting closer to fixing CSM, but there seems to be one more issue at hand.

At certain angles, the models will be caught/split between two shadow map cascades, like below.

first depth split

second depth split - here you can see the model is caught between the splits

How does one fix this? Increase the overlapping boundaries between the splits? Or is the frustrum erronous?

CameraFrustrum CalculateCameraFrustrum(const float fovDegrees, const float aspectRatio, const float minDist, const float maxDist, const Mat4& cameraViewMatrix, Mat4& outFrustrumMat)
{
    CameraFrustrum ret = { Vec4(1.0f, -1.0f, 0.0f, 1.0f), Vec4(1.0f, 1.0f, 0.0f, 1.0f), Vec4(-1.0f, 1.0f, 0.0f, 1.0f), Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
                           Vec4(1.0f, -1.0f, 1.0f, 1.0f), Vec4(1.0f, 1.0f, 1.0f, 1.0f), Vec4(-1.0f, 1.0f, 1.0f, 1.0f), Vec4(-1.0f, -1.0f, 1.0f, 1.0f), };

    const Mat4 perspectiveMatrix = PerspectiveMatrixFov(fovDegrees, aspectRatio, minDist, maxDist);
    const Mat4 invMVP = glm::inverse(perspectiveMatrix * cameraViewMatrix);

    outFrustrumMat = invMVP;

    for (Vec4& corner : ret)
    {
        corner = invMVP * corner;
        corner /= corner.w;
    }

    return ret;
}

Mat4 CreateDirLightVPMatrix(const CameraFrustrum& cameraFrustrum, const Vec3& lightDir)
{
    Mat4 lightViewMatrix = glm::lookAt(Vec3(0.0f), -glm::normalize(lightDir), Vec3(0.0f, -1.0f, 0.0f));

    Vec4 transf = lightViewMatrix * cameraFrustrum[0];
    float maxZ = transf.z, minZ = transf.z;
    float maxX = transf.x, minX = transf.x;
    float maxY = transf.y, minY = transf.y;
    for (uint32_t i = 1; i < 8; i++)
    {
        transf = lightViewMatrix * cameraFrustrum[i];

        if (transf.z > maxZ) maxZ = transf.z;
        if (transf.z < minZ) minZ = transf.z;
        if (transf.x > maxX) maxX = transf.x;
        if (transf.x < minX) minX = transf.x;
        if (transf.y > maxY) maxY = transf.y;
        if (transf.y < minY) minY = transf.y;
    }

    Mat4 viewMatrix(lightViewMatrix);
    viewMatrix[3][0] = -(minX + maxX) * 0.5f;
    viewMatrix[3][1] = -(minY + maxY) * 0.5f;
    viewMatrix[3][2] = -(minZ + maxZ) * 0.5f;
    viewMatrix[0][3] = 0.0f;
    viewMatrix[1][3] = 0.0f;
    viewMatrix[2][3] = 0.0f;
    viewMatrix[3][3] = 1.0f;

    Vec3 halfExtents((maxX - minX) * 0.5, (maxY - minY) * 0.5, (maxZ - minZ) * 0.5);

    return OrthographicMatrix(-halfExtents.x, halfExtents.x, halfExtents.y, -halfExtents.y, halfExtents.z, -halfExtents.z) * viewMatrix;
}

© Game Development or respective owner

Related posts about directx11

Related posts about shadows