这段代码是否正确,可以从Worldspace相机视锥中计算视图和投影矩阵?

时间:2018-09-22 04:42:44

标签: matrix shadow-mapping frustum

我正在尝试实现级联的阴影贴图。现在,我只有一个固定大小的级联,我想先让它工作,但是我被困了几天,而且我似乎不明白我要去哪里错了

我正在关注本教程: https://lwjglgamedev.gitbooks.io/3d-game-development-with-lwjgl/content/chapter26/chapter26.html

阴影框确实跟随视锥,但它以任意角度出现和消失,所以我怀疑投影矩阵会切掉侧面和深度。

代码:

    // Calculate view frustum points in world space

    const float NEAR_PLANE = 0.001f;
    const float FAR_PLANE  = 10.0f;

    const ENGINE::Entity* const camera = ENGINE::Resources::camera("camera2");
    const math::vec3& cameraWorldPosition = camera->getPosition();

    const math::vec3& cr = camera->getAxis(0); // camera X
    const math::vec3& cu = camera->getAxis(1); // camera Y
    const math::vec3& cf = camera->getAxis(2); // camera Z

    const math::vec3 nearPlaneCenter = cf * NEAR_PLANE;
    const math::vec3 farPlaneCenter  = cf * FAR_PLANE;

    const float range = 2.0f * tan(math::degrees_toRadians(65.0f / 2.0f));

    const float nearHeight = range * NEAR_PLANE;
    const float farHeight  = range * FAR_PLANE;
    const float nearWidth  = nearHeight * ENGINE::Window::getResolution();
    const float farWidth   = farHeight  * ENGINE::Window::getResolution();

    const math::vec3 farTopLeft     = cameraWorldPosition + farPlaneCenter  + cu * (farHeight  * 0.5f) - cr * (farWidth  * 0.5f);
    const math::vec3 farTopRight    = cameraWorldPosition + farPlaneCenter  + cu * (farHeight  * 0.5f) + cr * (farWidth  * 0.5f);
    const math::vec3 farBottomLeft  = cameraWorldPosition + farPlaneCenter  - cu * (farHeight  * 0.5f) - cr * (farWidth  * 0.5f);
    const math::vec3 farBottomRight = cameraWorldPosition + farPlaneCenter  - cu * (farHeight  * 0.5f) + cr * (farWidth  * 0.5f);

    const math::vec3 nearTopLeft    = cameraWorldPosition + nearPlaneCenter + cu * (nearHeight * 0.5f) - cr * (nearWidth * 0.5f);
    const math::vec3 nearTopRight   = cameraWorldPosition + nearPlaneCenter + cu * (nearHeight * 0.5f) + cr * (nearWidth * 0.5f);
    const math::vec3 nearBottomLeft = cameraWorldPosition + nearPlaneCenter - cu * (nearHeight * 0.5f) - cr * (nearWidth * 0.5f);
    const math::vec3 nearBottomRight= cameraWorldPosition + nearPlaneCenter - cu * (nearHeight * 0.5f) + cr * (nearWidth * 0.5f);

    // Create light ViewMatrix

    const math::vec3 cameraFrustumCenter  = cameraWorldPosition + cf * ((FAR_PLANE - NEAR_PLANE) * 0.5f);
    const math::vec3 currentLightPosition = cameraFrustumCenter + (math::vec3(0.7924f, 0.4121f, 0.4497f).normalize() * (FAR_PLANE - NEAR_PLANE));

    const math::vec3 lf = (cameraFrustumCenter - currentLightPosition).normalize(); // light Z
    const math::vec3 lr = math::cross(lf, math::vec3(0.0f, 1.0f, 0.0f));            // light X
    const math::vec3 lu = math::cross(lr, lf);                                      // light Y

    math::mat4 lightViewMtx;

    lightViewMtx[0][0] = lr.x;
    lightViewMtx[1][0] = lr.y;
    lightViewMtx[2][0] = lr.z;

    lightViewMtx[0][1] = lu.x;
    lightViewMtx[1][1] = lu.y;
    lightViewMtx[2][1] = lu.z;

    lightViewMtx[0][2] = -lf.x;
    lightViewMtx[1][2] = -lf.y;
    lightViewMtx[2][2] = -lf.z;

    lightViewMtx[3][0] = -dot(lr, currentLightPosition);
    lightViewMtx[3][1] = -dot(lu, currentLightPosition);
    lightViewMtx[3][2] =  dot(lf, currentLightPosition);

    // Calculate light projectionMatrix (Ortho)

    float minX =  9999999999.9f;
    float maxX = -9999999999.9f;
    float minY =  9999999999.9f;
    float maxY = -9999999999.9f;
    float minZ =  9999999999.9f;
    float maxZ = -9999999999.9f;

    const math::vec3 frustumCorners[8] =
    {
        farTopLeft, farTopRight, farBottomLeft, farBottomRight, nearTopLeft, nearTopRight, nearBottomLeft, nearBottomRight
    };

    for (int i = 0; i < 8; i++)
    {
        math::vec3 tmpVec = lightViewMtx * frustumCorners[i];

        minX = tmpVec.x < minX ? tmpVec.x : minX;
        maxX = tmpVec.x > maxX ? tmpVec.x : maxX;
        minY = tmpVec.y < minY ? tmpVec.y : minY;
        maxY = tmpVec.y > maxY ? tmpVec.y : maxY;
        minZ = tmpVec.z < minZ ? tmpVec.z : minZ;
        maxZ = tmpVec.z > maxZ ? tmpVec.z : maxZ;
    }

    math::mat4 lightProjection = math::ortho(minX, maxX, minY, maxY, minZ, maxZ);

    // Calculate light-space matrix (projection * view)

    m_LightSpaceMtx = lightProjection * lightViewMtx;

我可以确认“世界空间中的摄像机视锥面点”计算正确。绝对不是问题所在。

问题必须存在于light-viewmatrix计算或light-projectionMatrix中-但是,对我来说,我似乎正在按照本教程中的内容进行操作。

0 个答案:

没有答案