Является ли этот фрагмент кода правильным для расчета матриц вида и проекции по усеченной камере мирового пространства? - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь реализовать каскадные карты теней.На данный момент у меня есть только один каскад фиксированного размера, я хочу, чтобы это сначала сработало, но я застрял на несколько дней, и мне кажется, я не понимаю, в чем дело.

IСледую этому уроку: 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 - все же, мне кажется, что я делаю именно то, чтов учебнике.

...