2012-03-29 67 views
2

我有一个两遍渲染。在第一遍中,我使用FBO将一些不透明的几何体渲染成多个纹理。我使用imageStore()(image_load_and_store())将传递1中计算出的colorvalues写入一些纹理的特定纹理元素中。imageStore()(image_load_and_store(image_load_and_store) )OpenGL(4.2)片段处理和深度缓冲&imageLoadAndStore

我想但是(这个只发生了明显的碎片只有那些对应于通1)的最终fragmentcolors

所以我现在尽量是从通1把GL_DEPTH_ATTACHMENT质地和其附加到fbo从传球2(也作为GL_DEPTH_ATTACHMENT),然后在传球2之前我设置

glClearColor(0,0,0,1); 
glClear(GL_COLOR_BUFFER_BIT); 
glDepthMask(false); 
glEnable(GL_DEPTH_TEST); 
glDepthFunc(GL_LEQUAL); 
...render my scene... 

我希望片段着色器(它使用imageStore())仅对那些在第一遍中可见的片段执行(因为它是我渲染过的同一场景,同样在第二遍中)。

但它似乎没有工作 - 隐藏的片段被处理过,并执行imageStore()(和,因为他们使用PASS1计算可见片段的颜色,他们做了错误的事情)

知道为什么? imageStore或其他东西是否强制碎片处理器执行?我能以某种方式控制它吗?它是否必须用early-z做些事情?

回答

3

OpenGL规范定义了片段着色器之前执行深度测试。如果某些硬件首先执行深度测试,那么只有在交换机未发现行为变化的情况下才会执行此操作。

好吧,除非你只是告诉片段着色器的深度测试后执行,通过把此行的片段着色器:

layout(early_fragment_tests) in; 

这是shader_image_load_store的一部分,原因很明显。

+0

是的,这对我很有用,避免做我自己的深度测试。这在所有卡上的行为都一样吗?即它是否强迫早期z或它只是允许早期z? – Mat 2012-03-29 17:00:14

+0

@Mat:你知道,在你键入的时候,你可能已经到了[GL注册表](http://www.opengl.org/registry/),打开了[shader_image_load_store](http: //www.opengl.org/registry/specs/ARB/shader_image_load_store.txt)链接,并搜索“early_fragment_tests”。 – 2012-03-29 17:02:08

+3

不是真的 - 因为我没有这些东西流过我的虚荣,所以我可能不知道如何有效地搜索。不过谢谢,我回答了我的问题 – Mat 2012-03-29 19:21:16

1

由于early-z只是一个不需要完成的优化工具,我猜这是完全有效的行为。

如前所述,early-z是一种单纯的优化,不允许以任何方式改变行为。当片段get的深度被拒绝时,它不改变输出,但随着图像加载存储的出现,片段不再是唯一的输出,并且对深度测试失败的片段的着色器调用仍然可以写入成图像。因此,在这种情况下,早期z 将被禁用,以确保一致的行为。你的编译器不会奇迹般地知道,当深度测试失败时,你不想写入图像,因为它只看到着色器将某些东西写入图像,而早期的z不在任何地方指定。

你不会得到各地执行自己的深度测试,通过不使用深度纹理深度的附件,而是作为纹理输入:

uniform sampler2D depth; 

void main() 
{ 
    if(gl_FragCoord.z > texture(depth, gl_FragCoord.xy/textureSize(depth)) 
     discard; 
    ... 
} 
+0

你是对的,如果我使用imageStore,那么早期的z被禁用,这是我的问题。但是,我找到了一种方法来重新启用它,并通过将'layout(early_fragment_tests)'行放在'' – Mat 2012-03-29 15:43:54