opengl - 使用 OpenGL 进行阴影贴图的硬件 PCF

标签 opengl shadow-mapping

我在 GeForce GTX 750 下使用 OpenGL 4.3 来创建阴影贴图。现在基本效果如下图所示,似乎是正确的: enter image description here 为了消除 block 状效果,我尝试在着色器中手动执行 2x2 PCF。它导致以下结果,这似乎也是正确的: enter image description here 为了加速,我想利用显卡提供的好处,它可以一次获取比较结果的线性滤波器。但效果却和上面的不一样。 它更像是OpenGL线性地过滤阴影的渲染,而不是在Shadow Map上过滤: enter image description here 下面是我做硬件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 区域,线性插值结果,并通过纹理函数将其返回。我想我已经完成了所有必要的部分,但我仍然无法得到第二张图所示的确切结果。

任何人都可以给我任何关于我可能出错的地方的建议吗?非常感谢。

ps:有趣的是:我尝试了textureGather函数,它只返回比较结果,但不进行过滤,并且它给出了准确的结果,如第二张图所示。但这缺少自动过滤程序,显然它不是硬件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.

这并不是很严格,而且它当然不需要您认为“正确”的输出。

确实,actual PCF与你所建议的你想要的有很大不同。你似乎想要的东西仍然很 block 状;它只是不是二进制 block 。您的算法没有在比较结果之间进行线性插值;您只需进行 4 个最接近的比较,然后将它们平均起来。

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

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

关于opengl - 使用 OpenGL 进行阴影贴图的硬件 PCF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38628256/

相关文章:

opengl - 来自高度图的法线图

c++ - 阴影贴图OpenGL阴影并不总是绘制,并且绘制光源位置的位置

opengl - 阴影贴图着色器

opengl - 计算球体的顶点法线

c++ - 为什么我的二十面体画不出来?

opengl - OpenGL/OpenGLES 中的帧缓冲区纹理行为

c++ opengl将模型坐标转换为世界坐标以进行碰撞检测

javascript - three.js:如何让透明的png Sprite 转换和接收阴影?

android - OpenGL 阴影贴图在对象上的阴影不正确

opengl - 2D 阴影贴图