【问题标题】:Small artifacts with simple hard shadow mapping technique using OpenGL and GLSL使用 OpenGL 和 GLSL 的简单硬阴影映射技术的小工件
【发布时间】:2014-10-02 23:26:22
【问题描述】:

由于我使用的纹理颜色深沉(这些伪影不可见),我以前从未见过的硬阴影有一种奇怪的行为。以下是我使用 3 种不同阴影贴图分辨率时遇到的问题的一些屏幕截图:

1) 阴影贴图 160 * 120

如你所见,立方体表面有一种牙齿。

这是从灯光位置看场景的视图:

这是阴影贴图:

2) 阴影贴图 640 * 480

分辨率越高,伪影就越不明显,因为阴影贴图带来了更高的精度。

这是从灯光位置看场景的视图:

这是阴影贴图:

我尝试了更高的其他分辨率。当然,伪影越来越小,但如果你放大表面,它们仍然可见。

这是我在第二遍中在片段着色器中使用的代码:

[...]

uniform sampler2DShadow ShadowSampler[MAX_LIGHT_COUNT];

[...]

float GetDynamicShadowBias(vec3 normalDir_cs, vec3 lightDir_cs)
{
    float cosTheta = clamp(dot(normalDir_cs, lightDir_cs), 0.0f, 1.0f);
    float bias = 0.005f * tan(acos(cosTheta));

    return (clamp(bias, 0.0f, 0.01f));
}

float GetBiased_Hard_ShadowFactor(vec3 normalDir, vec3 lightDir, int idx)
{    
    if (ShadowCoords[idx].w > 0.0f)
    {
        float bias = GetDynamicShadowBias(normalDir, lightDir);

        float LightToOccluderClipDist = texture(
            ShadowSampler[idx], ShadowCoords[idx].xyz/ShadowCoords[idx].w);

        float LightToVertexClipDist = (ShadowCoords[idx].z - bias)/ShadowCoords[idx].w;

        if (LightToOccluderClipDist < LightToVertexClipDist)
            return (0.0f);
    }
    return (1.0f);
}

所以我想知道是否可以移除立方体边缘的这些伪影。我试图在没有真正成功的情况下使用阴影偏差(有关信息,我在第一遍(填充深度纹理)期间使用 FRONT_FACE 剔除)。

【问题讨论】:

    标签: opengl glsl shader fragment-shader shadow-mapping


    【解决方案1】:

    这里发生了两件事。一是这是标准阴影贴图的限制。因为任何给定对象的阴影将占用地图中可能较少数量的像素,所以当您将该地图投射到场景中时,这些部分可能会被重新放大,并且您会得到锯齿。

    似乎正在发生的第二件事是你的阴影基本上是 1 位,它似乎出现了。他们要么是黑色的,要么是白色的。如果您在创建地图时以某种方式对地图进行抗锯齿处理(比如超级采样或其他技术),它会不太明显(尽管根据我的经验它不会完全消失)。

    有一些基于经典阴影贴图的技术。一个是来自 SIGGRAPH 2013 的 Subpixel Shadow Mapping。(有 some other shadow papers that year, too。)我最近还看到了通过 GLSL 实时实现的光线投射阴影。 (抱歉,找不到链接!如果我能找到它,我会稍后发布。)

    【讨论】:

    • 感谢您的解释。就我而言,我只想谈论立方体上的工件,而不是平面上的工件(立方体边缘的“牙齿”)。这些碎片不应该在阴影中。是否有任何技术(偏移或其他)来去除立方体边缘的这些伪影?
    • 实际上一个好的解决方案应该是使用抗锯齿。我已经实现了像 PCF 技术这样的技术。但在我的问题中,我只想知道是否可以用硬阴影而不是软阴影去除伪影。感谢您的帮助!
    • 同样的问题。这样想:你的阴影贴图的分辨率是有限的。获取阴影贴图中的每个像素,并从 4 个角和中心的每一个向场景投射一条光线。在某些时候,您可能最终会得到一个阴影贴图像素,该像素将一个或两个角投影到立方体上,并将其他角和中心投影到平面上。立方体的那部分最终会处于阴影中,因为在阴影贴图中只有一个像素可以覆盖它,并且它被认为是阴影,因为中心光线击中了平面,而不是立方体。
    • 好的,感谢您的解释。因此,使用硬阴影映射算法这种行为是合乎逻辑的。有没有解决方案来删除它们属于你?我尝试使用顶点(在光空间中)偏移但没有成功。在此先感谢。
    猜你喜欢
    • 2014-12-11
    • 2015-02-04
    • 2013-12-27
    • 2015-01-17
    • 2014-01-16
    • 2014-05-17
    • 1970-01-01
    • 2015-02-23
    • 2013-06-30
    相关资源
    最近更新 更多