Separate Frame Buffer and Depth Buffer in OpenGL - opengl

In DirectX you are able to have separate render targets and depth buffers, so you can bind a render target and a depth buffer, do some rendering, remove the depth buffer and then do more rendering using the old depth buffer as a texture.
How would you go about this in opengl? From my understanding, you have a framebuffer object that contains both the color buffer(s) and an optional depth buffer. I don't think I can bind several framebuffer objects at the same time, would I have to recreate the framebuffer object every time it changes(probably several times a frame)? How do normal opengl programs do this?

A Framebuffer Object is nothing more than a series of references to images. These can be images in Textures (such as a mipmap layer of a 2D texture) or Renderbuffers (which can't be used as textures).
There is nothing stopping you from assembling an FBO that uses a texture's image for its color buffer and a texture's image for its depth buffer. Nor is there anything stopping you from later (so long as you're not rendering to that FBO while doing this) sampling from the texture as a depth texture. The FBO does not suddenly own these images exclusively or something.
In all likelihood, what has happened is that you've misunderstood the difference between an FBO and OpenGL's Default Framebuffer. The default framebuffer (ie: the window) is unchangeable. You can't take it's depth buffer and use it as a texture or something. What you do with an FBO is your own business, but OpenGL won't let you play with its default framebuffer in the same way.

You can bind multiple render targets to a single FBO, which should to the trick. Also since OpenGL is a state machine you can change the binding and number of targets anytime it is required.

Related

Copy entire cubemap texture from framebuffer

glFramebufferTexture allows one to bind an entire cubemap as a color attachment for layered rendering. In turn, glReadBuffer then allows one to bind said entire cubemap as a read buffer.
I want to render a scene to the non-zero mip levels of a cubemap texture. I'm using layered rendering to render not to one face, but to the entire thing in one go. However, the shader used for this uses the 0th mip level of that same texture. Since I don't think I can expose the texture to a shader and to a framebuffer attachment at the same time, I'm rendering to a different texture and copying the contents of that texture to my original texture's desired mip level.
Right now I'm doing this with a pass-through shader, which is pretty slow since it's layered rendering thus uses a geometry shader, and it would be better to use an API function. However, glCopyTexSubImage2D only allows cubemap faces, and neither it nor glCopyTexSubImage3D seem to accept cubemaps as input. Apart from 4.5-specific functions such as glCopyTextureSubImage3D, is there any way to retrieve an entire cubemap from the framebuffer into a cubemap texture ? I'm also aware that glCopyImageSubData exists, but something at the feature level of glFramebufferTexture is preferrable (so 3.2).

How to render color and depth in multisample texture?

In order to implement "depth-peeling", I render my OpenGL scene in to a series of framebuffers each equipped with a rgba color texture and depth texture. This works fine if I don't care about anti-aliasing. If I do, then it seems the correct thing to do is enable GL_MULTISAMPLING and use a GL_TEXTURE_2D_MULTISAMPLE instead of GL_TEXTURE_2D. But I'm confused about which other calls need to be replaced.
In particular, how should I adapt my framebuffer construction to use glTexImage2DMultisample instead of glTexImage2D?
Do I need to change the calls to glFramebufferTexture2D beyond using GL_TEXTURE_2D_MULTISAMPLE instead of GL_TEXTURE_2D?
If I'm rendering both color and depth into textures, do I need to make a call to glRenderbufferStorageMultisample?
Finally, is there some glBlit* that I need to do in addition to setting up textures for the framebuffer to render into?
There are many related questions on this topic, but none of the solutions I found seem to point to a canonical tutorial or clear example putting all these together.
While I have only used multisampled FBO rendering with renderbuffers, not textures, the following is my understanding.
Do I need to change the calls to glFramebufferTexture2D beyond using GL_TEXTURE_2D_MULTISAMPLE instead of GL_TEXTURE_2D?
No, that's all you need. You create the texture with glTexImage2DMultisample(), and then attach it using GL_TEXTURE_2D_MULTISAMPLE as the 3rd argument to glFramebufferTexture2D(). The only constraint is that the level (5th argument) has to be 0.
If I'm rendering both color and depth into textures, do I need to make a call to glRenderbufferStorageMultisample?
Yes. If you attach a depth buffer to the same FBO, you need to use a multisampled renderbuffer, with the same number of samples as the color buffer. So you create your depth renderbuffer with glRenderbufferStorageMultisample(), passing in the same sample count you used for the color buffer.
Finally, is there some glBlit* that I need to do in addition to setting up textures for the framebuffer to render into?
Not for rendering into the framebuffer. Once you're done rendering, you have a couple of options:
You can downsample (resolve) the multisample texture to a regular texture, and then use the regular texture for your subsequent rendering. For resolving the multisample texture, you can use glBlitFramebuffer(), where the multisample texture is attached to the GL_READ_FRAMEBUFFER, and the regular texture to the GL_DRAW_FRAMEBUFFER.
You can use the multisample texture for your subsequent rendering. You will need to use the sampler2DMS type for the samplers in your shader code, with the corresponding sampling functions.
For option 1, I don't really see a good reason to use a multisample texture. You might just as well use a multisample renderbuffer, which is slightly easier to use, and should be at least as efficient. For this, you create a renderbuffer for the color attachment, and allocate it with glRenderbufferStorageMultisample(), very much like what you need for the depth buffer.

Renderbuffer or texture object after fragment shader?

I am working on openGL ES2.0 and glsl and I have a question about FBO.
I pass two textures on my openGL ES2.0 code and through glsl shader, particularly fragment shader, I subtract two textures and make a binary image, just like opencv treshold function. My question is that I am not sure if I should use Renderbuffer or texture object for my FBO. I have to choose one since I can only use 1 color attachment (due to restriction of openGL ES2.0). Since the output image after my fragment shader will be a binary image (black or white), shouldn't it be Renderbuffer object?
A texture is a series of images which can be read from (via normal texturing means) and rendered into via FBOs. A renderbuffer is an image that can only be rendered into.
You should use a renderbuffer for images that you will only use as a render target. If you need to sample from it later, you should use a texture.

Normal back buffer + render to depth texture in OpenGL (FBOs)

Here's the situation: I have a texture containing some depth values. I want to render some geometry using that texture as the depth buffer, but I want the color to be written to the normal framebuffer (i.e., the window's framebuffer).
How do I do this? I tried creating an FBO and only binding a depth texture to it (GL_DEPTH_COMPONENT) but that didn't work; none of the colors showed up.
No you can't. The FBO you are rendering to may be either a main framebuffer or an off-screen one. You can't mix them in any way.
Instead, I would suggest you to render to a color renderbuffer and then do a simple blitting operation into the main framebuffer.
Edit-1.
Alternatively, if you already have depth in the main FB, you can first blit your depth and then render to a main FB, thus saving video memory on the additional color renderbuffer.
P.S. Blitting is done via glBlitFramebuffer. In order to make it work you should setup GL_READ_FRAMEBUFFER, GL_DRAW_FRAMEBUFFER and glDrawBuffer() for each of them.

Blitting multisampled FBO with multiple color attachments in OpenGL

I have a frame buffer object in an OpenGL program with multiple colour attachments, and am trying to upgrade it to a multisampled FBO.
As I understand it, a multisampled FBO is only able to use render buffers, specifically ones created using glRenderbufferStorageMultisampleEXT. If I want something rendered to this FBO in a texture, I need to create a second FBO with textures for its attachments, then blit the multisampled FBO to the regular FBO using glBlitFramebufferEXT.
The very, very sparse examples I've seen assume a single colour attachment. What do I do when I want to blit multiple colour attachments?
From the EXT_framebuffer_blit specification
12) Should we add support for multiple ReadBuffers, so that
multiple color buffers may be copied with a single call to BlitFramebuffer?
Resolved: No, we considered this but the behavior is awkward
to define and the functionality is of limited use.
From the arb_framebuffer_object specification (which superscedes the EXT_ version)
When the color buffer is transferred, values are taken from the read
buffer of the read framebuffer and written to each of the draw buffers
of the draw framebuffer, just as with CopyPixels.
So... It's pretty clear that you resolve only from a single color buffer per blit.
To do multiple ones, you need to do a Blit for each buffer, changing your READ_BUFFER for each buffer you want to blit, and select the corresponding draw buffer of the draw framebuffer.
You can create a new Fbo and assign the renderbuffer in slot 1 to it at slot 0. Then bind for reading and blit from that to your final destination Fbx.
i.e. An Fbo can be created purely for binding an existing renderbuffer that was written to by another Fbo. An Fbo doesn't actually own the buffers that are connected to it so multiple Fbx can be bound to the same textures/renderbuffers(though not at the same time).
// Render to Fbo0
Fbo0 : [ColorBuffer0, ColorBuffer1, DethBuffer]
// Bind another fbo with ColorBuffer1 at slot 0 for reading
Fbo1 : [ColorBuffer1]
// blit Fbo0 ColorBuffer0 > Fbo2 Texture0
Fbo0 : [ColorBuffer0, ColorBuffer1, DethBuffer] => Fbo2 : [Texture0]
//blit Fbo1 ColorBuffer1 (bound at slot0) > Fbo3 Texture1 (bound at slot0)
Fbo1 : [ColorBuffer1] => Fbo3 : [Texture1]