级联shadowmapping问题与拆分距离

我正在做级联的阴影映射,我有问题。 从相机位置开始,分割为[camPos,6],[camPos + 6,12],[camPos + 12,18]和[camPos + 18,100]。 “mSplitDistance”variables是每个分割的相机位置+ splitFarDistance(在相机空间中)。 所以,站在0.0f的世界位置,往下看-Z,值将是[-6,-12,-18,-100],然后转身向下看Z + [6,12,18,100]

阴影映射只是在最后一个分割从18到100准确; 那里阴影performance如预期。 在前三个分组中,有时是准确的,有时是完全错误的。

我正在使用延迟渲染,所以我只是绘制一个四分之一,然后去每个片段的片段,并从那里提取世界位置/法线/等。

我怀疑在照明片段着色器中有一些错误。 这里是:

#version 430 layout(std140) uniform; const float DEPTH_BIAS = 0.00005; uniform UnifDirLight { mat4 mVPMatrix[4]; // the bias * crop * projection* view matrices for the directional light float mSplitDistance[4]; vec4 mLightColor; vec4 mLightDir; vec4 mGamma; vec2 mScreenSize; } UnifDirLightPass; layout (binding = 2) uniform sampler2D unifPositionTexture; layout (binding = 3) uniform sampler2D unifNormalTexture; layout (binding = 4) uniform sampler2D unifDiffuseTexture; layout (binding = 6) uniform sampler2DArrayShadow unifShadowTexture; out vec4 fragColor; void main() { vec2 texcoord = gl_FragCoord.xy / UnifDirLightPass.mScreenSize; vec3 worldPos = texture(unifPositionTexture, texcoord).xyz; // world position; in world space vec3 normal = normalize(texture(unifNormalTexture, texcoord).xyz); vec3 diffuse = texture(unifDiffuseTexture, texcoord).xyz; int index = 3; if (worldPos.z > UnifDirLightPass.mSplitDistance[0]) index = 0; else if (worldPos.z > UnifDirLightPass.mSplitDistance[1]) index = 1; else if (worldPos.z > UnifDirLightPass.mSplitDistance[2]) index = 2; vec4 projCoords = UnifDirLightPass.mVPMatrix[index] * vec4(worldPos, 1.0); projCoords.w = projCoords.z - DEPTH_BIAS; projCoords.z = float(index); float visibilty = texture(unifShadowTexture, projCoords); float angleNormal = clamp(dot(normal, UnifDirLightPass.mLightDir.xyz), 0, 1); fragColor = vec4(diffuse, 1.0) * visibilty * angleNormal * UnifDirLightPass.mLightColor; } 

任何想法可能是错的? 我怀疑这可能是我select索引的方式的一些问题,但我还没有弄清楚。

编辑:截图显示的问题。 前三个显示阴影映射在不同的距离上起伏,第四个显示最后的分割,它按预期工作

http://img.ufgame.com/opengl/image.png

http://img.ufgame.com/opengl/image.png

http://img.ufgame.com/opengl/image.png

http://img.ufgame.com/opengl/image.png

编辑2:添加更多的截图与debugging

颜色显示farDistance(红色,绿色,蓝色,白色) http://img.ufgame.com/opengl/image.png http://img.ufgame.com/opengl/1_color.png¨

在上面的分裂看起来不错,但注意阴影仍然是如何切除的…而立方体上没有阴影?

http://img.ufgame.com/opengl/image.png http://img.ufgame.com/opengl/2_color.png

EDIT3:

下面我如何创建用于生成阴影贴图的光VPmatrix(然后在传递给着色器之前将其乘以偏置matrix)

 Mat4 CreateDirLightVPMatrix(const CameraFrustrum& cameraFrustrum, const Vec3& lightDir) { const Vec3 lightDirx = glm::normalize(lightDir); const Vec3 perpVec1 = glm::normalize(glm::cross(lightDirx, Vec3(0.0f, 0.0f, 1.0f))); const Vec3 perpVec2 = glm::normalize(glm::cross(lightDirx, perpVec1)); Mat4 lightViewMatrix(Vec4(perpVec1, 0.0f), Vec4(perpVec2, 0.0f), Vec4(lightDirx, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 1.0f)); Vec4 transf = lightViewMatrix * cameraFrustrum[0]; // cameraFrustrum is a std::array<Vec4, 8> and 0-3 is near-points and 4-7 are far points of the frustrum float maxZ = cameraFrustrum[0].z, minZ = cameraFrustrum[0].z; for (uint32_t i = 1; i < 8; i++) { transf = lightViewMatrix * cameraFrustrum[i]; if (cameraFrustrum[i].z > maxZ) maxZ = cameraFrustrum[i].z; if (cameraFrustrum[i].z < minZ) minZ = cameraFrustrum[i].z; } const Mat4 mvp = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, maxZ, minZ) * lightViewMatrix; float maxX = -1000.0f, minX = 1000.0f; float maxY = -1000.0f, minY = 1000.0f; for (uint32_t i = 0; i < 8; i++) { transf = mvp * cameraFrustrum[i]; if (cameraFrustrum[i].x > maxX) maxX = cameraFrustrum[i].x; if (cameraFrustrum[i].x < minX) minX = cameraFrustrum[i].x; if (cameraFrustrum[i].y > maxY) maxY = cameraFrustrum[i].y; if (cameraFrustrum[i].y < minY) minY = cameraFrustrum[i].y; } float scaleX = 2.0f / (maxX - minX); float scaleY = 2.0f / (maxY - minY); float offsetX = -0.5f * (maxX + minX) * scaleX; float offsetY = -0.5f * (maxY + minY) * scaleY; Mat4 cropMatrix(1.0f); cropMatrix[0][0] = scaleX; cropMatrix[1][1] = scaleY; cropMatrix[3][0] = offsetX; cropMatrix[3][1] = offsetY; return cropMatrix * glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, maxZ, minZ) * lightViewMatrix; } 

任何提示都非常感谢

我有类似的问题,你的。 而且我认为你在两个地方可能会出现问题:

  1. 光线不佳的投影matrix。 你应该预览每个级联,并检查阴影图是否正常。 在我的情况下,通过轻视matrix变换框的截锥体后,z轴上的变换框位置是错误的,在远距离阴影图是空白的。 为了解决这个问题,我在min.z(min.z- = camera.near())和min.z(max.z- = camera.far ())。 这给了我每个级联适当的范围。
  2. 坏分裂距离。 即使它看起来确实可能是错的。 在你的截图中,你只能看到阴影不好的场景或者有着彩色分割的场景。 为了得到更多的结论,最好是将最终的片断乘以(或添加)split的颜色。 它可以告诉你更多什么是真正的问题。 我不知道你的解决scheme是否好,但我用这里介绍的方法。 所以我用主摄像机投影matrix乘以每个平截面的远平面,并将其与深度缓冲区内容进行比较。

希望是明确的(我很难解释,理论上不好),并会帮助:)