我在 GeForce GTX 750 下使用 OpenGL 4.3 来创建阴影贴图。现在基本效果如下图所示,似乎是正确的: 为了消除 block 状效果,我尝试在着色器中手动执行 2x2 PCF。它导致以下结果,这似乎也是正确的: 为了加速,我想利用显卡提供的好处,它可以一次获取比较结果的线性滤波器。但效果却和上面的不一样。 它更像是OpenGL线性地过滤阴影的渲染,而不是在Shadow Map上过滤: 下面是我做硬件PCF的方法: 我注意到为了使用硬件 PCF 必须完成两件事,它们是:
- 使用
shadow
类型采样器,在我的例子中是samplerCubeShadow
(我使用立方体贴图类型,因为我正在尝试创建点光源场景)。 设置比较模式和过滤类型,在我的例子中,是通过以下代码完成的:
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/