2
\$\begingroup\$

I'm doing shadow mapping for directional lights and I'm trying to get 8 corners of the camera frustrum as a bounding box for the geometry, but I have no idea how. The goal is like in the image below (from another source):

enter image description here

The purple lines represent the final bounding box I am trying to achieve.

From what I know, I am supposed to do use the inverse of the cameras view-projection matrix, like this I believe:

    Vec4 corners[8] = { 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),
                        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 inverseVPMatrix = glm::inverse(viewProjectionMatrix);
    for (uint32_t i = 0; i < 8; i++)
    {
        corners[i] = corners[i] * inverseVPMatrix;
        corners[i] /= corners[i].w;
    }
    float minX = corners[0].x, minY = corners[0].y, minZ = corners[0].z, maxX = corners[0].x, maxY = corners[0].y, maxZ = corners[0].z;
    for (uint32_t i = 0; i < 8; i++)
    {
        if (corners[i].x < minX)
            minX = corners[i].x;
        if (corners[i].x > maxX)
            maxX = corners[i].x;
        if (corners[i].y < minY)
            minY = corners[i].y;
        if (corners[i].y > maxY)
            maxY = corners[i].y;
        if (corners[i].z < minZ)
            minZ = corners[i].z;
        if (corners[i].z > maxZ)
            maxZ = corners[i].z;
    }

And the result would be the bounding box? But the resulting corners are all maybe at most [-3.0, 3.0], waaay too small.

The view/projection are calculated like this. The view/projection matrices have been working fine so far, so I do not believe the problem lies there, but still.

const Mat4 viewMatrix = camera.GetCameraTransform();
const Mat4 perspectiveMatrix = glm::perspective(mWindow.GetFOV(), mWindow.GetScreenWidth() / (float)mWindow.GetScreenHeight(), mRenderer->GetZNear(), mRenderer->GetZFar());


Mat4 Camera::Orientation() const
{
    Quaternion rotation;
    rotation = glm::angleAxis(mVerticalAngle, Vec3(1.0f, 0.0f, 0.0f));
    rotation = rotation * glm::angleAxis(mHorizontalAngle, Vec3(0.0f, 1.0f, 0.0f));

    return glm::toMat4(rotation);
}


Mat4 Camera::GetCameraTransform() const
{
    return Orientation() * glm::translate(Mat4(1.0f), -mTranslation);
}

Any pointers on what is wrong?

EDIT1: Camera standing at Vec3(0.0f, 3.0f, 0.0f), looking down -Z axis generates the following inverted viewPerspective matrix:

Mat4(-1.24f, 0.0f,   0.0f,   0.0f,
     0.0f,   0.7f,   0.0f    0.0f,
     0.0f,  -15.0f,  0.0f   -5.0f,
     0.0f,   15.0f,  -1,0f   5.0f)

I dont know if that helps?

\$\endgroup\$
  • \$\begingroup\$ What do you mean by the planes? Updated the question btw \$\endgroup\$ – KaiserJohaan Feb 2 '14 at 18:58
  • \$\begingroup\$ This should be the right approach, and your code looks correct to me. Try visualizing the corners it generates, and/or working through an example case by hand, to see where it's going wrong? \$\endgroup\$ – Nathan Reed Feb 2 '14 at 20:53
2
\$\begingroup\$

The answer was simple.

The order of multiplication was wrong - this is what it should've been:

corners[i] = inverseVPMatrix * corners[i];

I thought the order of vector/matrix multiplication didnt matter, but I guess it did... with the above, it works fine.

Now that I think about it, glm math library is column-major, so maybe that is why?

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.