我正在尝试使用opengl实现级联阴影映射,但遇到了一些问题。
我开始通过将我的视锥体至3个分割并为每个分割它具有
1-近
2-远
3-拐角(在世界空间这一特定分割的平截头体的角部)
4-深度图(2D纹理1024尺寸* 1024)
并为每个分割我启动与计算其角如下,并与这些在世界空间的角落我计算平截头体中心,我将用来计算光视图矩阵。
float width = float(mRenderer->GetGame()->GetWidth());
float height = float(mRenderer->GetGame()->GetHeight());
mProjMatrix = glm::perspective(glm::radians(90.0f), (float)width / (float)height, mNear, mFar);
mViewMatrix = mRenderer->GetView();
glm::mat4 viewProj = mProjMatrix * mViewMatrix;
glm::vec3 frustumCorners[8] =
{
glm::vec3(-1.0f, 1.0f, -1.0f),
glm::vec3(1.0f, 1.0f, -1.0f),
glm::vec3(1.0f, -1.0f, -1.0f),
glm::vec3(-1.0f, -1.0f, -1.0f),
glm::vec3(-1.0f, 1.0f, 1.0f),
glm::vec3(1.0f, 1.0f, 1.0f),
glm::vec3(1.0f, -1.0f, 1.0f),
glm::vec3(-1.0f, -1.0f, 1.0f),
};
for (int i = 0; i < 8; ++i)
{
glm::vec4 inversePoint = glm::inverse(viewProj) * glm::vec4(frustumCorners[i], 1.0f);
mCorners[i] = glm::vec3(inversePoint / inversePoint.w);
}
for (int i = 0; i < 8; ++i)
{
mFrustumCenter += mCorners[i];
}
mFrustumCenter /= 8.0f;
在获得此特定拆分的视锥中心之后,我需要找出将用于渲染场景的光视图矩阵(在拆分的近处与远端之间),然后按以下步骤进行操作。
mRenderer-> GetLightDirection()= {0.0f,20.0f,-1.0f}
glm::vec3 lightDir = glm::normalize(mRenderer->GetLightDirection());
glm::vec3 lightPos = mFrustumCenter + lightDir;
mLightView = glm::lookAt(lightPos, mFrustumCenter , glm::vec3(0.0f, 1.0f, 0.0f));
最后,我要做的最后一件事是在使用前一步骤计算出的光视图矩阵将它们转换为光空间后,使用平截头锥体角计算光的正交矩阵。
for (int i = 0; i < 8; ++i)
{
mCorners[i] = glm::vec3(mLightView * glm::vec4(mCorners[i], 1.0f));
}
float minX = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::min();
float minY = std::numeric_limits<float>::max();
float maxY = std::numeric_limits<float>::min();
float minZ = std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::min();
for (int i = 0; i < 8; ++i)
{
minX = std::min(minX, mCorners[i].x);
maxX = std::max(maxX, mCorners[i].x);
minY = std::min(minY, mCorners[i].y);
maxY = std::max(maxY, mCorners[i].y);
minZ = std::min(minZ, mCorners[i].z);
maxZ = std::max(maxZ, mCorners[i].z);
}
mLightProj = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);
当我运行程序时,我的阴影可以正常工作
但是当我将摄像机移回直到地板进入第二个拆分的范围而不是使用第二个拆分阴影时,它消失了,但是当我开始上下移动摄像机时,阴影又出现了,所以我认为问题在于计算光视图矩阵,但我不知道。
这些是我的拆分范围->
远
0.1-> 30.0
0.1-> 50.0
0.1-> 1000.0
好吧,我发现我没有正确放置灯光,所以这个片段
glm::vec3 lightDir = glm::normalize(mRenderer->GetLightDirection());
glm::vec3 lightPos = mFrustumCenter + lightDir;
mLightView = glm::lookAt(lightPos, mFrustumCenter , glm::vec3(0.0f, 1.0f, 0.0f));
应该
glm::vec3 lightDir = glm::normalize(mRenderer->GetLightDirection());
glm::vec3 lightPos = mFrustumCenter + lightDir * (mFar - mNear);
mLightView = glm::lookAt(lightPos, mFrustumCenter , glm::vec3(0.0f, 1.0f, 0.0f));
我应该在另一个方向上移动光位置,其大小等于当前分体平截头体的近端和远端之间的差。
还有这个片段
float minX = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::min();
float minY = std::numeric_limits<float>::max();
float maxY = std::numeric_limits<float>::min();
float minZ = std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::min();
for (int i = 0; i < 8; ++i)
{
minX = std::min(minX, mCorners[i].x);
maxX = std::max(maxX, mCorners[i].x);
minY = std::min(minY, mCorners[i].y);
maxY = std::max(maxY, mCorners[i].y);
minZ = std::min(minZ, mCorners[i].z);
maxZ = std::max(maxZ, mCorners[i].z);
}
mLightProj = glm::ortho(minX, maxX, minY, maxY, minZ, maxZ);
应该
float minX = std::numeric_limits<float>::max();
float maxX = std::numeric_limits<float>::min();
float minY = std::numeric_limits<float>::max();
float maxY = std::numeric_limits<float>::min();
float minZ = std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::min();
for (int i = 0; i < 8; ++i)
{
minX = std::min(minX, mCorners[i].x);
maxX = std::max(maxX, mCorners[i].x);
minY = std::min(minY, mCorners[i].y);
maxY = std::max(maxY, mCorners[i].y);
minZ = std::min(minZ, mCorners[i].z);
maxZ = std::max(maxZ, mCorners[i].z);
}
mLightProj = glm::ortho(minX, maxX, minY, maxY, near, maxZ - minZ);
正交投影矩阵的近点和远点应等于平截锥体的近点,远点应等于最近角和最远角(z轴)之间的距离
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句