使用 OpenGL 的阴影贴图的硬件 PCF

Hardware PCF for Shadow Map using OpenGL

我在 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);
    

之后我在shader中使用了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函数,只returns比较结果,不做过滤,它给出了准确结果如第二张图所示。但这缺少自动过滤程序,显然它不是硬件PCF的完整版本。

To erase the blocky-effect, I've tried to do a 2x2 PCF manually in the shader. It leads to the following result, which also seems to be correct:

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

The details of this are implementation-dependent, but r should be a value in the range [0,1] which is proportional to the number of comparison passes or failures.

这不是很受限制,它当然不需要您看到的输出 "correct"。

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

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

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

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