OpenGL(4.2)片段处理&深度缓冲& imageLoadAndStore

时间:2012-03-29 13:15:34

标签: opengl graphics glsl

我有两次渲染渲染。在第一遍中,我使用FBO将一些不透明的几何体渲染成几个纹理。

在第二遍中,我再次渲染相同的几何体,并基于不同的几何属性(如对象,法线等),我使用imageStore()(image_load_and_store)将计算出的颜色值从第1遍写入某些纹理的特定纹素中

我希望这只发生在可见的碎片上(只有那些与第1遍的最终碎片颜色相对应)

所以我现在尝试的是从传递1获取GL_DEPTH_ATTACHMENT纹理并将其从传递2(也作为GL_DEPTH_ATTACHMENT)附加到fbo,然后在渲染传递2之前我设置

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

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

但它似乎不起作用 - 隐藏的片段也被处理并执行imageStore()(因为它们使用pass1中为可见片段计算的颜色,它们做错了)

知道为什么吗? imageStore或其他东西强制片段着色器执行?我可以以某种方式控制它吗?它是否必须与早期z做一些事情?

2 个答案:

答案 0 :(得分:3)

OpenGL规范定义片段着色器在深度测试之前执行。如果某些硬件首先执行深度测试,那么只有在交换机没有注意到行为变化的情况下才会这样做。

好吧,除非您只是告诉片段着色器在深度测试后执行,否则将此行放在片段着色器中:

layout(early_fragment_tests) in;

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

答案 1 :(得分:1)

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

如上所述,early-z仅仅是一种优化,不允许以任何方式改变行为。当片段的深度被拒绝时它不会改变输出,但是随着图像加载存储的出现,片段不再是唯一的输出,并且对于未通过深度测试的片段的着色器调用仍然可以写入成像。因此,在这种情况下,必须禁用early-z ,以保证一致的行为。您的编译器并不神奇地知道,当深度测试失败时您不想写入图像,因为它只会看到将某些内容写入图像的着色器,并且未在任何地方指定early-z。

您不会通过不使用深度纹理作为深度附件来执行自己的深度测试,而是将其作为纹理输入:

uniform sampler2D depth;

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