问题描述
所以我一直在尝试使用定向光在我的引擎中重新实现阴影贴图,但到目前为止我必须为我的进度添加阴影(看看我在那里做了什么?)。
我在前一次提交中使用过它,但重构了我的引擎,我正在尝试重做一些阴影映射。不会说我在绘制阴影方面是最好的,所以我想我会尝试寻求一些帮助。
基本上我的问题似乎源于光空间矩阵的计算(似乎很多人都有同样的问题)。最初我有一个硬编码的投影矩阵和像这样的光的简单视图矩阵
void ZLight::UpdateLightspaceMatrix()
{
// …
if (type == ZLightType::Directional) {
auto lightDir = glm::normalize(glm::eulerAngles(Orientation()));
glm::mat4 lightV = glm::lookAt(lightDir,glm::vec3(0.f),WORLD_UP);
glm::mat4 lightP = glm::ortho(-50.f,50.f,-50.f,-100.f,100.f);
lightspaceMatrix_ = lightP * lightV;
}
// …
}
然后将其作为着色器统一传递未经修改,我将顶点世界空间位置乘以它。几个月前,这是有效的,但最近我在引擎上进行了重构,它不再显示任何内容。阴影贴图的输出看起来像这样
而且我的场景没有显示任何阴影,至少在重要的地方没有
除此之外,经过数小时的搜索帖子和文章,了解如何在任何给定时间为包含场景内容的光实现动态视锥体,我还实现了一个基于将相机视锥体转换为光空间的简单解决方案,使用 NDC 立方体并使用逆相机 VP 矩阵对其进行变换,并根据结果计算边界框,将其传递给 glm::ortho 以制作光的投影矩阵
void ZLight::UpdateLightspaceMatrix()
{
static std::vector <glm::vec4> ndcCube = {
glm::vec4{ -1.0f,-1.0f,1.0f },glm::vec4{ 1.0f,glm::vec4{ -1.0f,1.0f,1.0f }
};
if (type == ZLightType::Directional) {
auto activeCamera = Scene()->ActiveCamera();
auto lightDir = normalize(glm::eulerAngles(Orientation()));
glm::mat4 lightV = glm::lookAt(lightDir,WORLD_UP);
lightspaceRegion_ = ZAABBox();
for (const auto& corner : ndcCube) {
auto invVPMatrix = glm::inverse(activeCamera->ProjectionMatrix() * activeCamera->ViewMatrix());
auto transformedCorner = lightV * invVPMatrix * corner;
transformedCorner /= transformedCorner.w;
lightspaceRegion_.minimum.x = glm::min(lightspaceRegion_.minimum.x,transformedCorner.x);
lightspaceRegion_.minimum.y = glm::min(lightspaceRegion_.minimum.y,transformedCorner.y);
lightspaceRegion_.minimum.z = glm::min(lightspaceRegion_.minimum.z,transformedCorner.z);
lightspaceRegion_.maximum.x = glm::max(lightspaceRegion_.maximum.x,transformedCorner.x);
lightspaceRegion_.maximum.y = glm::max(lightspaceRegion_.maximum.y,transformedCorner.y);
lightspaceRegion_.maximum.z = glm::max(lightspaceRegion_.maximum.z,transformedCorner.z);
}
glm::mat4 lightP = glm::ortho(lightspaceRegion_.minimum.x,lightspaceRegion_.maximum.x,lightspaceRegion_.minimum.y,lightspaceRegion_.maximum.y,-lightspaceRegion_.maximum.z,-lightspaceRegion_.minimum.z);
lightspaceMatrix_ = lightP * lightV;
}
}
结果是我的场景(任何地方都没有阴影)和下面的阴影贴图的输出相同
我一遍又一遍地检查了光空间矩阵的计算,并尝试了数十次调整值,包括使用 glm::lookAt 函数的各种 lightV 矩阵,但我从未得到所需的输出。
更多参考,这是我的阴影顶点着色器
#version 450 core
#include "Shaders/common.glsl" //! #include "../common.glsl"
layout (location = 0) in vec3 position;
layout (location = 5) in ivec4 boneIDs;
layout (location = 6) in vec4 boneWeights;
layout (location = 7) in mat4 instanceM;
uniform mat4 P_lightSpace;
uniform mat4 M;
uniform mat4 Bones[MAX_BOnes];
uniform bool rigged = false;
uniform bool instanced = false;
void main()
{
vec4 pos = vec4(position,1.0);
if (rigged) {
mat4 boneTransform = Bones[boneIDs[0]] * boneWeights[0];
boneTransform += Bones[boneIDs[1]] * boneWeights[1];
boneTransform += Bones[boneIDs[2]] * boneWeights[2];
boneTransform += Bones[boneIDs[3]] * boneWeights[3];
pos = boneTransform * pos;
}
gl_Position = P_lightSpace * (instanced ? instanceM : M) * pos;
}
我的软阴影实现
float PCFShadow(VertexOutput vout,sampler2D shadowMap) {
vec3 projCoords = vout.FragPosLightSpace.xyz / vout.FragPosLightSpace.w;
if (projCoords.z > 1.0)
return 0.0;
projCoords = projCoords * 0.5 + 0.5;
// PCF
float shadow = 0.0;
float bias = max(0.05 * (1.0 - dot(vout.Fragnormal,vout.FragPosLightSpace.xyz - vout.FragPos.xzy)),0.005);
for (int i = 0; i < 4; ++i) {
float z = texture(shadowMap,projCoords.xy + poissondisk[i]).r;
shadow += z < (projCoords.z - bias) ? 1.0 : 0.0;
}
return shadow / 4;
}
...
...
float shadow = PCFShadow(vout,shadowSampler0);
vec3 color = (ambient + (1.0 - shadow) * (diffuse + specular)) + materials[materialIndex].emission;
FragColor = vec4(color,albd.a);
以及我的相机视图和投影矩阵获取器
glm::mat4 ZCamera::ProjectionMatrix()
{
glm::mat4 projectionMatrix(1.f);
auto scene = Scene();
if (!scene) return projectionMatrix;
if (cameraType_ == ZCameraType::Orthographic)
{
float zoomInverse_ = 1.f / (2.f * zoom_);
glm::vec2 resolution = scene->Domain()->Resolution();
float left = -((float)resolution.x * zoomInverse_);
float right = -left;
float bottom = -((float)resolution.y * zoomInverse_);
float top = -bottom;
projectionMatrix = glm::ortho(left,right,bottom,top,-farClippingPlane_,farClippingPlane_);
}
else
{
projectionMatrix = glm::perspective(glm::radians(zoom_),(float)scene->Domain()->Aspect(),nearClippingPlane_,farClippingPlane_);
}
return projectionMatrix;
}
glm::mat4 ZCamera::ViewMatrix()
{
return glm::lookAt(Position(),Position() + Front(),Up());
}
一直在尝试各种小的变化,但我仍然没有得到正确的阴影。不知道我在这里做错了什么。我得到的最接近的是在光空间矩阵计算中将 lightspaceRegion_ 边界缩放 10 倍(仅在 X 和 Y 中),但阴影仍然不正确。
相机的近剪裁平面和远剪裁平面设置为合理的值(分别为 0.01 和 100.0),相机缩放为 45.0 度,scene→Domain()→Aspect()
仅返回帧缓冲区分辨率的宽度/高度纵横比。我的阴影贴图分辨率设置为 2048x2048。
这里的任何帮助将不胜感激。如果我遗漏了任何重要的代码或信息,请告诉我。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)