我有两次渲染渲染。在第一遍中,我使用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做一些事情?
答案 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;
...
}