【问题标题】:How can I "add" Depth information to the main frame buffer如何将深度信息“添加”到主帧缓冲区
【发布时间】:2014-04-04 19:32:06
【问题描述】:

假设我有这个场景

我想从定制的片段着色器中添加深度信息。

现在要做的直观的事情是在我的茶壶上绘制一个四边形,而不启用深度测试,但使用 glDepthMask(1) 和 glColorMask(0, 0, 0, 0)。写入一些片段 gl_FragDepth 并丢弃一些其他片段。

if ( gl_FragCoord.x < 100 )
    gl_FragDepth = 0.1;
else
    discard;

由于某种原因,在 NVidia Quadro 600 和 K5000 上,它按预期工作,但在 NVidia K3000M 和 Firepro 上(不记得是哪一个),我丢弃的片段覆盖的所有区域都被赋予了深度值四边形。

我不能不修改丢弃的片段深度值吗?

编辑我找到了解决问题的方法。事实证明,正如 Andon M. Coleman 和 Matt Fishman 指出的那样,我启用了 early_fragment_test,但不是因为我启用了它,而是因为我使用了 imageStore、imageLoad。

在我不得不解决这个问题的时间很少的情况下,我只是在“添加深度通道”之前将当前深度缓冲区的内容复制到纹理。将其分配给统一的 sampler2D。这是我的着色器中的代码:

if ( gl_FragCoord.x < 100 )
    gl_FragDepth = 0.1;
else
{
    gl_FragDepth = texture( depthTex, gl_PointCoord ).r;
    color = vec4(0.0,0.0,0.0,0.0);
    return;
}

这会写入一个完全透明的像素,其 z 值不变。

【问题讨论】:

  • 您使用的是什么 OpenGL 版本?
  • 这个问题可能和早z测试有关——在这种情况下,shader写入的深度值没有影响,甚至丢弃的片段也可能写入深度缓冲区(这在硬件方面非常有意义,因为测试和 Z 缓冲区更新通常是原子条件内存更新,而不是两个单独的步骤)。然而,一个实现应该表现得好像只有在您启用它时才使用早期 z 测试(它可能在“安全情况”下也使用它们,在这种情况下,片段着色器中不会发生丢弃和深度写入。)。跨度>
  • 如果你说的是“early_fragment_tests”,它是没有启用的。我有另一个程序需要这个功能,但不是这个特定的。
  • 您没有使用图像加载/存储,是吗?这隐含地启用了早期片段测试。
  • 嗯,真的。我在将片段累积到链表中的过程中启用了早期片段测试。但是在我写入深度缓冲区的过程中,我只使用 imageLoad 方法加载该链表。我不知道这会隐含地启用早期片段测试。

标签: opengl glsl


【解决方案1】:

嗯,对我来说这听起来像是一个驱动程序错误——丢弃的片段不应该到达深度缓冲区。您可以将原始深度缓冲区绑定为纹理,使用gl_FragCoord 对其进行采样,然后将结果写回而不是使用discard。这会增加额外的纹理查找——但它可能是一个合适的解决方法。

编辑:来自GLSL 4.40 Specification 的第 6.4 节:

discard 关键字只允许在片段着色器中使用。有可能 在片段着色器中使用以放弃对当前的操作 分段。此关键字导致片段被丢弃并且 no 将更新任何缓冲区。控制流退出着色器,并且 随后的隐式或显式 当此出口不均匀时,导数是未定义的。它会 通常在条件语句中使用,例如:

if (intensity &lt; 0.0) discard;

片段着色器可以测试片段的 alpha 值并根据该测试丢弃片段。然而,它 需要注意的是,覆盖测试发生在片段着色器之后 运行,覆盖测试可以改变alpha值。如果

(强调我的)

【讨论】:

  • 是的,这就是我认为我需要做的,感谢您的回答。我将编写一个简单的程序来重现该问题,以确认它是驱动程序错误。我真的很想看看规范中的哪个位置说,当深度掩码为 1 时,丢弃的片段不应写入深度。
  • 因此我们可以推断,即使深度掩码为 1 且深度测试“始终”,深度值也不应更新。两家不同的显卡制造商在他们的驱动程序中编写相同的错误似乎仍然很奇怪。
  • 问题出现在 K3000M Windows 7 和 Windows 8.1 的 Firepro 卡上。目前所有可用的最新驱动程序。答案足够好,我将其确认为解决方案。即使那不是我想读的:)
  • 很抱歉 :( 我也遇到了一些笔记本电脑 CPU 上的着色器问题。我有一个旧的 ATI Radeon 卡不能正确处理帧缓冲区对象。
  • 毕竟不是驱动问题。检查我对帖子所做的编辑。
【解决方案2】:

发布一个单独的答案,因为我在 OpenGL 规范中发现了一些新信息:

如果启用了早期片段测试,则由 片段着色器没有效果。此外,深度缓冲区、模板 缓冲区和遮挡查询样本计数可能会更新,即使 在片段着色器之后将被丢弃的片段或样本 由于每个片段的操作(例如 alpha-to-coverage 或 alpha 测试。

您是否启用了早期片段测试?更多信息:Early Fragment Test

【讨论】:

  • 不,我没有启用早期片段测试,也许我应该写一个简单的例子并发布整个代码来澄清。起初我有它,然后我把我的程序分成两遍。
  • 检查我在帖子中所做的编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-12
  • 1970-01-01
  • 1970-01-01
  • 2020-07-13
  • 1970-01-01
  • 1970-01-01
  • 2018-05-12
相关资源
最近更新 更多