阴影贴图产生不正确的结果
Shadow Map Produces Incorrect Results
我正在尝试将阴影映射实现到我的延迟渲染管道中,但我 运行 遇到了一些实际生成阴影贴图的问题,然后对像素进行阴影处理 – 我认为应该进行阴影处理的像素根本不是。
我有一个方向灯,它是我引擎中的 'sun'。我已经为照明设置了延迟渲染,到目前为止它工作正常。我再次将场景渲染为阴影贴图的深度 FBO,使用以下代码生成视图矩阵:
glm::vec3 position = r->getCamera()->getCameraPosition(); // position of level camera
glm::vec3 lightDir = this->sun->getDirection(); // sun direction vector
glm::mat4 depthProjectionMatrix = glm::ortho<float>(-10,10,-10,10,-10,20); // ortho projection
glm::mat4 depthViewMatrix = glm::lookAt(position + (lightDir * 20.f / 2.f), -lightDir, glm::vec3(0,1,0));
glm::mat4 lightSpaceMatrix = depthProjectionMatrix * depthViewMatrix;
然后,在我的光照着色器中,我使用以下代码来确定像素是否在阴影中:
// lightSpaceMatrix is the same as above, FragWorldPos is world position of the texekl
vec4 FragPosLightSpace = lightSpaceMatrix * vec4(FragWorldPos, 1.0f);
// multiply non-ambient light values by ShadowCalculation(FragPosLightSpace)
// ... do more stuff ...
float ShadowCalculation(vec4 fragPosLightSpace) {
// perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// vec3 projCoords = fragPosLightSpace.xyz;
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// Get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(gSunShadowMap, projCoords.xy).r;
// Get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
// Check whether current frag pos is in shadow
float bias = 0.005;
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
// Ensure that Z value is no larger than 1
if(projCoords.z > 1.0) {
shadow = 0.0;
}
return shadow;
}
但是,这并不能真正让我得到我想要的东西。这是阴影后输出的屏幕截图,以及在 Photoshop 中半成品转换为图像的阴影贴图:
渲染输出
阴影贴图
由于定向光是我的着色器中唯一的光,阴影贴图的渲染似乎非常接近正确,因为 perspective/direction 大致匹配。然而,我不明白的是为什么 none 个茶壶实际上最终会在其他茶壶上投下阴影。
对于我可能做错了什么的任何指示,我将不胜感激。我认为我的问题要么在于光 space 矩阵的计算(我不确定如何正确计算它,给定一个移动的相机,以便更新视野中的东西,)或在我确定延迟渲染器正在着色的纹素是否在阴影中的方式。 (FWIW,我从深度缓冲区确定世界位置,但我已经证明这个计算是正确的。)
感谢您的帮助。
调试影子问题可能很棘手。让我们从几点开始:
如果仔细观察渲染图,您实际上会在左上角的一个花盆上看到阴影。
尝试旋转太阳,这通常有助于查看光变换矩阵是否存在任何问题。从您的输出来看,太阳似乎非常水平,可能不会在此设置上投射阴影。 (另一个角度可能会显示更多阴影)
看来您正在正确计算矩阵,但请尝试将 glm::ortho(-10,10,-10,10,-10,20) 中的最大深度缩小到紧密贴合您的场景。如果深度太大,你会失去精度,阴影会有伪影。
为了进一步可视化问题出在哪里,请尝试从此处输出阴影贴图查找的结果:
closestDepth = texture(gSunShadowMap, projCoords.xy).r
如果阴影贴图投影正确,那么您就知道深度比较存在问题。希望这对您有所帮助!
我正在尝试将阴影映射实现到我的延迟渲染管道中,但我 运行 遇到了一些实际生成阴影贴图的问题,然后对像素进行阴影处理 – 我认为应该进行阴影处理的像素根本不是。
我有一个方向灯,它是我引擎中的 'sun'。我已经为照明设置了延迟渲染,到目前为止它工作正常。我再次将场景渲染为阴影贴图的深度 FBO,使用以下代码生成视图矩阵:
glm::vec3 position = r->getCamera()->getCameraPosition(); // position of level camera
glm::vec3 lightDir = this->sun->getDirection(); // sun direction vector
glm::mat4 depthProjectionMatrix = glm::ortho<float>(-10,10,-10,10,-10,20); // ortho projection
glm::mat4 depthViewMatrix = glm::lookAt(position + (lightDir * 20.f / 2.f), -lightDir, glm::vec3(0,1,0));
glm::mat4 lightSpaceMatrix = depthProjectionMatrix * depthViewMatrix;
然后,在我的光照着色器中,我使用以下代码来确定像素是否在阴影中:
// lightSpaceMatrix is the same as above, FragWorldPos is world position of the texekl
vec4 FragPosLightSpace = lightSpaceMatrix * vec4(FragWorldPos, 1.0f);
// multiply non-ambient light values by ShadowCalculation(FragPosLightSpace)
// ... do more stuff ...
float ShadowCalculation(vec4 fragPosLightSpace) {
// perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// vec3 projCoords = fragPosLightSpace.xyz;
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// Get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
float closestDepth = texture(gSunShadowMap, projCoords.xy).r;
// Get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
// Check whether current frag pos is in shadow
float bias = 0.005;
float shadow = (currentDepth - bias) > closestDepth ? 1.0 : 0.0;
// Ensure that Z value is no larger than 1
if(projCoords.z > 1.0) {
shadow = 0.0;
}
return shadow;
}
但是,这并不能真正让我得到我想要的东西。这是阴影后输出的屏幕截图,以及在 Photoshop 中半成品转换为图像的阴影贴图:
由于定向光是我的着色器中唯一的光,阴影贴图的渲染似乎非常接近正确,因为 perspective/direction 大致匹配。然而,我不明白的是为什么 none 个茶壶实际上最终会在其他茶壶上投下阴影。
对于我可能做错了什么的任何指示,我将不胜感激。我认为我的问题要么在于光 space 矩阵的计算(我不确定如何正确计算它,给定一个移动的相机,以便更新视野中的东西,)或在我确定延迟渲染器正在着色的纹素是否在阴影中的方式。 (FWIW,我从深度缓冲区确定世界位置,但我已经证明这个计算是正确的。)
感谢您的帮助。
调试影子问题可能很棘手。让我们从几点开始:
如果仔细观察渲染图,您实际上会在左上角的一个花盆上看到阴影。
尝试旋转太阳,这通常有助于查看光变换矩阵是否存在任何问题。从您的输出来看,太阳似乎非常水平,可能不会在此设置上投射阴影。 (另一个角度可能会显示更多阴影)
看来您正在正确计算矩阵,但请尝试将 glm::ortho(-10,10,-10,10,-10,20) 中的最大深度缩小到紧密贴合您的场景。如果深度太大,你会失去精度,阴影会有伪影。
为了进一步可视化问题出在哪里,请尝试从此处输出阴影贴图查找的结果:
closestDepth = texture(gSunShadowMap, projCoords.xy).r
如果阴影贴图投影正确,那么您就知道深度比较存在问题。希望这对您有所帮助!