Nvidia显卡上的阴影粉刺

Posted

技术标签:

【中文标题】Nvidia显卡上的阴影粉刺【英文标题】:Shadow acne on Nvidia graphics card 【发布时间】:2014-07-05 18:00:51 【问题描述】:

我和一个合作伙伴正在使用 OpenGL 进行一个小型演示。我们正在做简单的阴影映射。他使用 ATI 和 Intel HD graphics 4000,一切正常。尽管我们使用相同的代码,但我使用 GTX 560 TI 并得到阴影粉刺。

当我移动时,整个阴影都在闪烁。要设置帧缓冲区的深度缓冲区,我们执行以下操作:

glBindTexture(GL_TEXTURE_2D,_t_depth->name());
  glTexImage2D(
    GL_TEXTURE_2D,0,
    GL_DEPTH_COMPONENT32,
    width,height,
    0, GL_DEPTH_COMPONENT, GL_FLOAT,0);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
  glBindTexture(GL_TEXTURE_2D,0);
  glFramebufferTexture(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,_t_depth->name(),0);

顶点着色器的相关部分是:

uniform mat4 u_lightspace_MVP;
layout(location=0) in vec3 v_position;
...
vec4 shadowcoord_x=u_lightspace_MVP*vec4(v_position,1.0);
shadowcoord_x/=shadowcoord_x.w;

片段着色器的相关部分是:

 if (texture(s_shadowMap,shadowcoord_x.xy).r>shadowcoord_x.z-0.0001)

我尝试了不同的偏差值,但要么不影响粉刺,要么根本没有阴影。我还尝试使用带有 textureProj() 和 texture() 的 sampler2DShadow 作为查找函数。似乎没有任何效果。这个问题不仅会影响阴影,还会影响同时使用阴影贴图的体积光照效果。 另一方面,使用 gl_ClipDistance 进行剪辑在我的 Nvidia 上运行良好,但在他的显卡上却不行。

【问题讨论】:

当您使用 sampler2DShadow 时,您是否将 glTexParameteri 切换为使用 GL_LINEAR 而不是 GL_NEAREST? 是的,我已经尝试过了。 OpenGL 似乎在阴影贴图上做了一些插值,虽然两个滤镜都选择了 GL_NEAREST。 好吧,GL_NEAREST 不适用于普通阴影贴图。原因是您的过滤深度,这实际上没有意义。如果您实现 PCF 阴影映射算法,那么 GL_LINEAR 是有意义的,因为您正在过滤深度测试的结果。它可能对您的情况有所帮助。我看不出你的代码有什么问题。 当我显示深度缓冲区时,它看起来很好,没有伪影或任何其他可能导致这种粉刺的东西。奇怪的是,它可以在 ATI 显卡上运行,即使在 Intel 上也可以正常运行。 您是否考虑过在片段着色器中进行透视分割和/或使用noperspective 插值?这可能会给您带来更一致的结果。 【参考方案1】:

经过进一步的反复试验,我终于摆脱了粉刺。我唯一要做的就是将阴影贴图的精度从 32 位减半到 16 位。初始化现在看起来像这样:

glBindTexture(GL_TEXTURE_2D,_t_depth->name());
  glTexImage2D(
    GL_TEXTURE_2D,0,
    GL_DEPTH_COMPONENT16,
    width,height,
    0, GL_DEPTH_COMPONENT, GL_FLOAT,0);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
  glBindTexture(GL_TEXTURE_2D,0);
  glFramebufferTexture(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,_t_depth->name(),0);

现在我还在片段着色器中使用 sampler2DShadow 和 textureProj() 进行深度测试,一切正常。 我仍然很好奇为什么它不能在我的 Nvidia 上使用 32 位但在 ATI 上。

【讨论】:

以上是关于Nvidia显卡上的阴影粉刺的主要内容,如果未能解决你的问题,请参考以下文章

哪些NVIDIA显卡支持CUDA技术

OpenGL 3.3 两个 GPU 上的两个不同结果 nVidia Optimus 与阴影映射

nvidia 940m这个显卡怎么样?

怎么更新NVIDIA

ubuntu 重启显卡报错 nvidia

ubuntu安装nvidia显卡驱动