简体   繁体   中英

OpenGL/GLSL 4.5 - using MRT in the default FBO

I'm using MRT to resolve the 3D picking problem in OpenGL 4.5. (Reference link: http://ogldev.atspace.co.uk/www/tutorial29/tutorial29.html )

According to the information I found online, we generally apply a new FBO when using the MRT. If so, I should daw the scene twice during 3D picking (the new FBO for 3D picking, and the default FBO for the screen), which would be a waste of time.

So I was wondering if the MRT could be used in the default FBO, but I run into some problems.

Here's my code.

// 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);

When I query the GL_COLOR_ATTACHMENT1 at last, the result seems to be the frag_color0 instead of frag_color1.

I would be very appreciated if somebody could help me to resolve the problem, thanks!

When I query the GL_COLOR_ATTACHMENT1 at last, the result seems to be the frag_color0 instead of frag_color1 .

No, it is not, for the single reason that there is no GL_COLOR_ATTACHMENT1 for FBO 0 , so you cannot query it. FBO 0 refers to the window-system provided framebuffer (specified via the pixelformat on windows, the visual or fbconfig on X11/Unix and other platform-specific means).

This framebuffer might or might not have a depth buffer, might or might not have a stencil buffer, might or might not have a (legacy, depracated) accumulation buffer and might have the following color buffers :

  • GL_BACK_LEFT
  • GL_BACK_RIGHT
  • GL_FRONT_LEFT
  • GL_FRONT_RIGHT

That's the most you can get, and that is only if your GPU and drivers support the "quadbuffer stereo" mode for 3D stereoscopic rendering. In the typical case, you will only have two:

  • GL_BACK : the buffer where you draw the new frame
  • GL_FRONT : the buffer which is currently presented on the screen.

You cannot change any of these buffer configurations from within the GL (you can only influence this when setting up the window you connect your GL context to), and there is no way to mix GL objects (textures, renderbuffer) with the default framebuffer

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_pickingColorTexture, 0);

If you call this while FBO 0 is bound, this just results in a GL error and is otherwise ignored. The same is the case for these:

 GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; glDrawBuffers(2, buffers); [...] glReadBuffer(GL_COLOR_ATTACHMENT1);

So what you're rendering to is what the default for glDrawBuffer is, which is GL_BACK in the typical case, your second shader output is ending up nowhere, and what you're reading back is what glReadBuffer is by default, and that is also GL_BACK in the typical case.

According to the information I found online, we generally apply a new FBO when using the MRT.

The information you found online is correct. For MRT in OpenGL, you need to set up a custom FBO, and can't share it with the buffers from FBO 0. (Technically, this is not strictly true, you still can set up MRT with FBO 0 with draw buffers like {GL_FRONT, GL_BACK} or if you have a GPU with stereo support, you could even (mis)-use {GL_BACK_LEFT,GL_BACK_RIGHT} . But the practical use cases for these are quite limited).

If so, I should draw the scene twice during 3D picking (the new FBO for 3D picking, and the default FBO for the screen), which would be a waste of time.

That doesn't have to be the case. You still can render it with MRT into some custom FBO, and only blit one color attachment to FBO 0's GL_BACK buffer afterwards.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM