gpt4 book ai didi

c++ - 级联阴影贴图无法按预期工作

转载 作者:行者123 更新时间:2023-12-02 10:27:52 28 4
gpt4 key购买 nike

我正在尝试使用 opengl 实现级联阴影映射,但我遇到了一些问题。
我首先划分我的视锥体三分 并且对于每个拆分它都有一个
1-近
2-远
3- 角(世界空间中这个特定分割的平截头体的角)
4- 深度图(2D 纹理,尺寸为 1024 * 1024)
对于每个拆分,我从计算其 开始角落 如下和这些世界空间的角落我计算截头体中心我将使用到 计算光照 View 矩阵。

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));
最后我做的最后一件事是计算 光的正交矩阵使用 平截头体角 在我将它们转换为 之后光空间使用光 View 矩阵,我计算了上一步。
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
这些是我的 split 范围
近->远
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);
光正交投影矩阵的近和应该等于 split 截头体的近,远应该等于最近角和最远角(z轴)之间的距离

关于c++ - 级联阴影贴图无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63530325/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com