【问题标题】:Hardware PCF for Shadow Map using OpenGL使用 OpenGL 的阴影贴图的硬件 PCF
【发布时间】:2016-07-29 10:08:44
【问题描述】:

我在 GeForce GTX 750 下使用 OpenGL 4.3 创建阴影贴图。现在基本效果如下图所示,似乎是正确的: 为了消除块状效果,我尝试在着色器中手动执行 2x2 PCF。它导致以下结果,这似乎也是正确的: 对于加速,我想利用显卡提供的好处,它可以一次获取比较结果的线性过滤器。但是效果和上面的不一样。 更像是 OpenGL 对阴影的渲染进行线性过滤,而不是在 Shadow Map 上进行过滤 下面是我如何做硬件PCF: 我注意到为了使用硬件 PCF,必须做的基本两件事是:

  1. 使用shadow 类型的采样器,在我的例子中是samplerCubeShadow(我正在使用立方体贴图类型,因为我正在尝试创建点光源场景)。
  2. 设置比较模式和过滤类型,在我的例子中,是通过以下代码完成的:

    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
    

之后,我像这样在着色器中使用texture 函数(我使用texture 而不是textureProj 的原因是因为后者似乎不支持立方体贴图阴影纹理,因为它需要vec5 类型,显然还不支持):

vec4 posInLight4D = positionsInLight / positionsInLight.w;    // divided by the 4-th component)
vec3 texCoord = GetCubeMapTexCoord(posInLight4D.xy);    // get the texture coordinate in cube map texture. This can be assumed correct
float lightness = texture(shadowMapHardware, vec4(texCoord, posInLight4D.z));

但不幸的是,这给出了第三张图片中显示的结果。

据我了解,通过比较模式线性滤镜的设置,显卡会进行比较一个附近的 2x2 区域并线性插值结果并通过texture 函数返回。我想我已经完成了所有必要的部分,但我仍然无法获得第二张图片中显示的确切结果。

谁能给我任何关于我可能出错的建议?非常感谢。

ps:有趣的是:我尝试了textureGather函数,它只返回比较结果而不进行过滤,它给出了精确的结果,如第二张图所示。但这缺少自动过滤程序,显然它不是硬件 PCF 的完整版本。

【问题讨论】:

    标签: opengl shadow-mapping


    【解决方案1】:

    为了消除块状效果,我尝试在着色器中手动执行 2x2 PCF。它导致以下结果,这似乎也是正确的:

    OpenGL 规范没有规定在线性插值深度比较时要使用的特定算法。但是,它通常将其描述为:

    这个细节取决于实现,但r 应该 是 [0,1] 范围内的值,与比较次数成正比 通过或失败。

    这不是很受限制,当然也不需要您认为“正确”的输出。

    确实,actual PCF 与您建议的内容有很大不同。您似乎想要的仍然很块状;它只是不是 binary 块。您的算法没有在比较结果之间进行线性插值;您刚刚进行了 4 次最接近的比较并将它们平均在一起。

    NVIDIA 提供给您的是 PCD 实际上假定的样子:比较结果之间的线性插值,基于您的采样点。

    所以错误的是您的期望,而不是 NVIDIA。

    【讨论】:

    • 所以你的意思是通过平均比较结果,我不是在做 NVIDIA 执行的“线性插值”,对吧?我检查了你之前提供的材料,但它没有说明这个插值是如何完成的。你能告诉我更多的细节吗?谢谢。
    • @Narusaki:这是线性插值。它的工作原理就像在非比较情况下一样,只是它对后比较值进行插值。
    • 哦,我想我明白你的意思了:线性插值应该使用从“中心坐标”到四个“角坐标”的距离作为“权重”,而不仅仅是将四个值取平均值“角坐标”,在这种情况下,权重为 0.25。对吗?
    【解决方案2】:

    根据@Nicol 的回答,我想我误解了插值的含义。以下是我对着色器级插值的实现,它看起来与问题中的第二张图片完全相同:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      相关资源
      最近更新 更多