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\$
2
  • \$\begingroup\$ What do you mean by the planes? Updated the question btw \$\endgroup\$ Feb 2, 2014 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\$ Feb 2, 2014 at 20:53

1 Answer 1

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?

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .