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