我一直在使用深度纹理在OpenGL中进行阴影映射。深度纹理很好,我可以将其映射到场景上,但是在对象的背面有一些奇怪的伪像:



我的问题是什么引起的

我正在使用的片段着色器非常简单(为简单起见,我将颜色去除了,以防您想知道为什么这里没有蓝色):

in vec4 vShadowCoord;

uniform sampler2DShadow shadowMap;

out vec4 fragColor;

void main()
{
    float bias = 0.005;
    float visibility = 1.0;
    if (texture(shadowMap, vec3(vShadowCoord.xy, vShadowCoord.z / vShadowCoord.w)) < (vShadowCoord.z - bias) / vShadowCoord.w)
        visibility = 0.25;

    fragColor = vec4(visibility);
}


编辑:根据要求,最小工作示例屏幕截图,仅使用上述代码(无颜色)。



评论

您可以确认显示的代码(去掉蓝色的代码)是否还会造成伪影吗?如果您缩小了代码的范围,则从缩小的代码中显示图像将有助于排除任何无关的细节并突出显示问题。

是的,确实如此,我想我要在其中截取带有颜色的屏幕截图,否则它看起来会更加难看:)

我可以理解,但是由于这是您寻求帮助的丑陋之处,因此,如果您还提供了与代码匹配的屏幕截图,则您更有可能看到该问题。

很公平。我添加了一个额外的屏幕截图。

您是否尝试过在偏见中玩得更多?

#1 楼

此问题看起来像标准阴影贴图痤疮伪像。另外,您的照明公式不完整或不正确。光线不应影响法线背对的面。这也意味着使用适当的方程式,球体的“暗”面不应有任何痤疮伪影。

痤疮伪影有三种来源:


第一个痤疮来源是阴影贴图精度。确保阴影投射光的近平面和远平面尽可能紧密。可以对靠近平面之前的所有对象进行煎饼处理,因为它们的确切深度并不重要。
第二个痤疮源是阴影贴图分辨率。对于定向光,您应该使用至少3个1024x1012级联绘制级联阴影贴图,以实现约100-200m的阴影距离。很难用一个具有均匀投影的阴影贴图覆盖相似的阴影距离。
第三种痤疮源是像PCF这样的宽阴影贴图滤镜,因为在宽内核上使用单个深度深度比较值是不够的。修复它的方法有很多,但没有一种是健壮的。

总而言之,具有一些级联和一些偏差调整的紧密的平截头体足以使一般情况起作用(定向光) 。通过禁用阴影过滤来开始调整,并且仅在基本阴影贴图足够健壮时才进行过滤调整。

除了恒定的深度偏差(您当前使用的)之外,您还应该添加坡度深度偏差和最大坡度深度偏差。两者都可以在阴影贴图渲染期间实现为渲染状态或着色器代码。斜率深度偏差只是一个用点(normal,lightDir)缩放的魔术偏差值。

还有一些其他有趣的方法,其中大多数都在出色的演示中实现:Matt Pettineo-“阴影技术”。


阴影贴图渲染期间的翻转剔除(以粉刺代替彼得的平移)。
法线偏移阴影贴图确实会解决偏斜问题,但在着色过程中必须具有顶点法线。
基于方差的方法(ESM,VSM,EVSM)可以完全消除偏斜问题,但还有其他缺点(漏光和/或性能)问题)。