C++ OpenGL/GLSL 4.5-在默认FBO中使用MRT

C++ OpenGL/GLSL 4.5-在默认FBO中使用MRT,c++,opengl,opengl-4,picking,C++,Opengl,Opengl 4,Picking,我正在使用MRT解决OpenGL4.5中的3D拾取问题。 (参考链接:) 根据我在网上找到的信息,我们通常在使用捷运时使用新的固定基地运营商。如果是这样,我应该在3D拾取期间对场景进行两次daw(3D拾取的新FBO和屏幕的默认FBO),这将是浪费时间 所以我想知道捷运是否可以用于默认的固定基地运营商,但我遇到了一些问题 这是我的密码 // apply the texture buffer attached to GL_COLOR_ATTACHMENT1. (GL_COLOR_ATTACHMENT

我正在使用MRT解决OpenGL4.5中的3D拾取问题。 (参考链接:)

根据我在网上找到的信息,我们通常在使用捷运时使用新的固定基地运营商。如果是这样,我应该在3D拾取期间对场景进行两次daw(3D拾取的新FBO和屏幕的默认FBO),这将是浪费时间

所以我想知道捷运是否可以用于默认的固定基地运营商,但我遇到了一些问题

这是我的密码

// apply the texture buffer attached to GL_COLOR_ATTACHMENT1. (GL_COLOR_ATTACHMENT0 is reserved for the screen ?)
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &m_pickingColorTexture);
glBindTexture(GL_TEXTURE_2D, m_pickingColorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, w, h, 0, GL_RGB, GL_FLOAT, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_pickingColorTexture, 0);
glDisable(GL_TEXTURE_2D);

// draw code. 
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
glDrawElements(........);

// fragment shader, output two kinds of things: frag_color0 for screen display, frag_color1 for 3D picking
 .......
layout (location = 0) out vec4 frag_color0; 
layout (location = 1) out vec4 frag_color1; 
 
void main() {
     frag_color0 = vec4(...);
     frag_color1 = vec4(...);
}

// query the result
glReadBuffer(GL_COLOR_ATTACHMENT1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, &pixelInfo);
当我最后查询GL_COLOR_附件1时,结果似乎是frag_color0而不是frag_color1

如果有人能帮我解决这个问题,我将不胜感激,谢谢

当我最后查询
GL\u COLOR\u附件1
时,结果似乎是
frag\u color0
而不是
frag\u color1

不,它不是,因为单一原因,没有FBO 0的
GL\u COLOR\u附件1
,因此您无法查询它。FBO 0是指窗口系统提供的帧缓冲区(通过windows上的pixelformat、X11/Unix上的visual或fbconfig以及其他特定于平台的方式指定)

此帧缓冲区可能有或可能没有深度缓冲区,可能有或可能没有模具缓冲区,可能有或可能没有(传统的、去种族化的)累积缓冲区,并且可能有以下颜色缓冲区:

  • GL\u BACK\u LEFT
  • GL\u BACK\u RIGHT
  • GL\u前\u左
  • GL\u前\u右
这是你能得到的最多的,而且只有当你的GPU和驱动程序支持3D立体渲染的“四缓冲区立体”模式时。在典型情况下,您只有两个:

  • GL\u BACK
    :绘制新帧的缓冲区
  • GL\u FRONT
    :当前显示在屏幕上的缓冲区
您无法在GL中更改任何这些缓冲区配置(您只能在设置连接GL上下文的窗口时影响此设置),并且无法将GL对象(纹理、renderbuffer)与默认帧缓冲区混合

如果在绑定FBO 0时调用此函数,这只会导致GL错误,否则将被忽略。以下情况也是如此:

因此,您要渲染的是glDrawBuffer的默认值,在典型情况下是
GL_BACK
,第二个着色器输出没有结果,您要读取的是默认情况下
glReadBuffer
的值,在典型情况下也是
GL_BACK

根据我在网上找到的信息,我们通常在使用捷运时使用新的固定基地运营商

您在网上找到的信息是正确的。对于OpenGL中的MRT,您需要设置自定义FBO,并且不能与FBO 0中的缓冲区共享它。(从技术上讲,这不是严格意义上的事实,您仍然可以使用FBO 0设置MRT,并使用诸如
{GL_FRONT,GL_BACK}
之类的绘图缓冲区,或者如果您有一个支持立体声的GPU,您甚至可以(错误地)使用
{GL_BACK_LEFT,GL_BACK_RIGHT}
。但是这些的实际使用案例非常有限)

如果是这样,我应该在3D拾取期间绘制两次场景(3D拾取的新FBO和屏幕的默认FBO),这将是浪费时间


事实并非如此。您仍然可以使用MRT将其渲染到一些自定义FBO中,并且之后只需将一个颜色附件添加到FBO 0的
GL\u BACK
缓冲区。

非常感谢!glBlitFramebuffer——我找到了这个函数并解决了这个问题。我从你那里学到了很多,谢谢~
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_pickingColorTexture, 0);
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
[...]
glReadBuffer(GL_COLOR_ATTACHMENT1);