FBO 深度缓冲区为红色

Posted

技术标签:

【中文标题】FBO 深度缓冲区为红色【英文标题】:FBO depth buffer is red 【发布时间】:2016-12-03 21:45:39 【问题描述】:

我的影子系统无法正常工作。 我使用以下代码生成我的 FBO:

int frameBuffer = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
GL11.glDrawBuffer(GL11.GL_NONE);
GL11.glReadBuffer(GL11.GL_NONE);

int texture = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT16, WIDTH, HEIGHT, 0,
GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, (ByteBuffer) null);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, texture, 0);

GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());

我的实体在我的默认渲染器(输出 vec4)中渲染得很好。 我的阴影着色器代码很简单:

#version 430
layout(location = 0) out float fragmentdepth;

void main(void)
    fragmentdepth =  gl_FragCoord.z;

我尝试在不使用任何 FBO 的情况下输出 vec4(1.0),并且一切正常,因此我的计算是正确的,我的着色器代码也应该可以正常工作。

我的绘图调用如下所示:

GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
renderShadows();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
renderAllItems();
Display.sync(FPS_CAP);
Display.update();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(0.2f,0.1f,0.1f , 1f);

当我调用“renderAllItems();”时我还在右上角渲染了一个四边形,它应该显示我的深度纹理。但我看到的只是一个红色的四边形。 不应该是黑/白并显示一些东西吗?

【问题讨论】:

“我的影子系统无法正常工作。” -> “我的影子系统无法正常工作。” 深度缓冲区不是任何颜色,它存储深度。虽然它是一个单独的组件,但可以解释为您想要的任何颜色......通常确实会变成红色通道。 "不应该是黑/白显示什么吗?" 你渲染成“黑/白”吗? 不,我没有。但是我怎样才能告诉我的程序渲染黑/白呢?只输出一个 vec4(color.r,color.r,color.r,1.0) ?是的,我知道它存储深度。我只是用颜色来表明我的着色器工作正常。 【参考方案1】:
GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, texture, 0);

这会将纹理附加到帧缓冲区对象的深度附件。

layout(location = 0) out float fragmentdepth;

那是user-defined output from a fragment shader。用户定义的输出映射到片段颜色,which get written 映射到 FBO 的颜色附件,而不是深度附件。

片段的深度是写入深度附件的内容。在 FS 中,这就是 built-in gl_FragDepth output。但是,您没有理由写信给它。不写的话会自动填上gl_FragCoord.z

确实,如果您只想渲染深度,shouldn't even have a fragment shader。

【讨论】:

在没有片段着色器的情况下渲染时,您是否有此行为的规范参考?我发现的唯一一件事是“如果没有用于顶点或片段着色器阶段的活动程序,则顶点和/或片段处理的结果将是未定义的”。由于gl_FragDepth 是片段处理的结果,这并不能告诉我它会在这种情况下定义。 天哪,它有效! :) 谢谢你,尼可波拉斯。我刚刚删除了片段着色器中的所有内容,并将显示纹理更改为显示黑色/白色。非常感谢你 !! :) @RetoKoradi: "因为gl_FragDepth 是片段处理的结果" 这没关系,因为:"如果活动片段着色器没有静态地为gl_FragDepth,那么光栅化过程中生成的深度值将被管道的后续阶段使用。”如果没有片段着色器,则它不能分配给gl_FragDepth。因此,使用了光栅化过程中生成的深度值。 @RetoKoradi:另外,还有这个:“片段着色器确定片段的颜色值,也可以修改或替换它们指定的深度值。”请注意,它并没有说 FS “确定”深度值,只是说它可以“修改或替换”它。

以上是关于FBO 深度缓冲区为红色的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL(FBO)中的普通后台缓冲区+渲染到深度纹理

我可以避免将模板缓冲区从 FBO 传送到后台缓冲区吗?

GLSL 共享深度缓冲区似乎不起作用

将opengl主帧缓冲区复制到fbo

带有模板缓冲区 FBO 的延迟渲染器

在 GLSL 中检索 FBO 数据