我正在尝试实现级联的阴影贴图。现在,我只有一个固定大小的级联,我想先让它工作,但是我被困了几天,而且我似乎不明白我要去哪里错了
我正在关注本教程: 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中-但是,对我来说,我似乎正在按照本教程中的内容进行操作。