假设我有这个场景

我想从自定义片段着色器添加深度信息.
现在直观的做法是在没有启用深度测试但是使用glDepthMask(1)和glColorMask(0,0,0,0)的情况下在我的茶壶上绘制四边形.写一些片段gl_FragDepth并丢弃其他一些片段.
if ( gl_FragCoord.x < 100 )
gl_FragDepth = 0.1;
else
discard;
Run Code Online (Sandbox Code Playgroud)
出于某种原因,在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;
}
Run Code Online (Sandbox Code Playgroud)
这会写出一个完全透明的像素,其z值保持不变.
嗯,对我来说这听起来像是一个驱动程序错误——丢弃的片段不应该到达深度缓冲区。您可以将原始深度缓冲区绑定为纹理,使用 对其进行采样gl_FragCoord,然后将结果写回而不是使用discard。这会增加额外的纹理查找——但这可能是一个合适的解决方法。
编辑:来自GLSL 4.40 规范的第 6.4 节:
\n\n\n\n\n丢弃关键字仅允许在片段着色器中使用。它可以在片段着色器中使用,以放弃对当前片段的操作。该关键字导致片段被丢弃并且不会对任何缓冲区进行\n 更新。控制流退出着色器,并且当此退出不均匀时,后续隐式或显式导数是未定义的。它通常用在条件语句中,例如:
\n\n\n\n
if (intensity < 0.0) discard;片段着色器可以测试片段\xe2\x80\x99s\n alpha 值并根据该测试丢弃片段。但需要注意的是,覆盖率测试发生在片段着色器运行之后,并且覆盖率测试可以更改 alpha 值。如果
\n
(强调我的)
\n