级联的阴影贴图无法正常工作

问题描述

我正在尝试使用opengl实现级联阴影映射,但是遇到了一些问题。

我首先将我的视图视锥体划分为三个分割,每个分割都有一个

1-附近
2远
3个角(在世界空间中这种特定的平截头体的角落)
4-深度图(尺寸为1024 * 1024的2D纹理)

对于每个拆分,我首先按如下方式计算其,并根据世界空间中的这些,我计算出视锥中心用于计算光视图矩阵。

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,glm::vec3(-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;

在获得此特定拆分的视锥中心之后,我需要弄清楚将用于渲染场景的 light view matrix (在近远之间)的分裂),我这样做如下。
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,0.0f));

最后,我要做的最后一件事是在将它们转换为 light space 空间后,使用平截头体角来计算正交光矩阵 >使用光视图矩阵,我计算了上一步。

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); 

当我运行程序时,我的阴影可以正常工作

enter image description here

但是当我向后移动摄像机直到地板进入第二个分割的范围而不是使用第二个分割阴影时,它消失了,但是当我开始上下移动摄像机时,阴影又出现了,所以我认为问题是在计算光视图矩阵时,但我无法弄清楚。

enter image description here

这些是我的拆分范围
near-> far
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,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,near,maxZ - minZ);

光正交投影矩阵的近点和远点应等于平截锥体的近点,远点应等于最近角和最远角(z轴)之间的距离

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...