Fragment shader rendering to off-screen frame buffer - opengl

In a Qt based application I want to execute a fragment shader on two textures (both 1000x1000 pixels).
I draw a rectangle and the fragment shader works fine.
But, now I want to renderer the output into GL_AUX0 frame buffer to let the result read back and save to a file.
Unfortunately if the window size is less than 1000x1000 pixels the output is not correct. Just the window size area is rendered onto the frame buffer.
How can I execute the frame buffer for the whole texture?

The recommended way to do off-screen processing is to use Framebuffer Objects (FBO). These buffers act similar the render buffers you already know, but are not constrained by the window resolution or color depths. You can use the GPGPU Framebuffer Object Class to hide low-level OpenGL commands and use the FBO right away. If you prefer doing this on your own, have a look at the extension specification.

Related

OpenGL: Is it supported to render into an FBO in one context, then use the FBO's texture in another?

I have the following OpenGL setup for troubleshooting frame buffer issues:
I render a cube into a frame buffer.
I use the target texture from this frame buffer to draw a textured quad, which displays the cube in my viewport.
This works OK when both stages of the process are done in the same context, but breaks if stage 1 is done in a different context to stage 2 (note that these contexts are both shared and both on the same thread). In this case, I only ever see the cube displayed when I resize my viewport (which recreates my frame buffer). The cube is sometimes corrupted or fragmented, which leads me to believe that all I'm seeing is parts of memory that were used by the texture before it was resized, and that nothing is ever displayed properly.
The reason I have to have this setup is that in my actual application I'm using Qt OpenGL widgets, which are forced to use their own individual contexts, so I have to render my scene in its own dedicated context and then copy it to the relevant viewports using shareable OpenGL resources. If I don't do this, I get errors caused by VAOs being bound/used in other contexts.
I've tried the following unsuccessful combinations (where the primary context is where I use the texture to draw the quad, and the secondary context where the "offscreen" rendering of the cube into the frame buffer takes place):
Creating the frame buffer, its render buffer and its texture all in the secondary context.
Creating the frame buffer and the render buffer in the secondary context, creating the texture in the primary context, and then attaching the texture to the frame buffer in the secondary context.
Creating the frame buffer, its render buffer and two separate textures in the secondary context. One of these textures is initially attached to the frame buffer for rendering. Once the rendering to the frame buffer is complete, the first texture is detached and the second one attached. The previously attached texture containing the content of the rendering is used with the quad in the primary context.
In addition, I can't use glBlitFramebuffer() as I don't have access to the frame buffer the QOpenGLWidget uses in the application (as far as I've tried, QOpenGLWidget::defaultFramebufferObject() returns 0 which causes glBlitFramebuffer to give me errors).
The only way I have managed to get the rendering to work is to use a QOpenGLFrameBuffer and call takeTexture() when I want to use the texture with the quad. However, doing it this way means that the QOpenGLFrameBuffer creates itself a new texture and I have to destroy the old one once I've used it, which seems very inefficient.
Is there anything I can do to solve this problem?
I've got a project that uses a texture like that. You need to call glFinish() after drawing and before using the texture from QOpenGLFramebufferObject::texture(). That was our problem on some of the OSes.

Render to window framebuffer and FBO to save full scale texture image

I would like to save the output of my image processing OpenGL shader program to an image file and also display the result on the screen. I know how to save the window framebuffer using glReadPixels(). However, the resolution of the screen is smaller than the dimensions of the image.
If I render to an FBO, do I need to call glDrawArrays() again after saving and unbinding the FBO to see the results on the screen? Or is it possible to tell the window framebuffer to render from the FBO without having to run the shader program a second time?
To save the rendered image in the RBO, you can read the pixels directly by setting which buffer OpenGL will read the pixels from by calling glReadBuffer. In your particular case, setting the read buffer to GL_COLOR_ATTACHMENT<i> should do the trick. See the glDrawBuffer man page for details.
In order to display the image in the FBO: yes, you will need to make an additional rendering pass to copy the FBO's image into the default frame buffer. You an either bind the FBO as a texture, and render geometry, as you suggest, to get the image on the screen, or, you may be able to use glBlitFramebuffer to simplify the copying and image filtering.
If I render to an FBO, do I need to call glDrawArrays() again after saving and unbinding the FBO to see the results on the screen?
You should use glBlitFramebuffer (...), the purpose of this function is to copy one framebuffer (read buffer) to another (draw buffer). Provided you are not doing something unusual like drawing into an integer texture attachment then your FBO's draw buffer should be compatible with your default framebuffer (window).
There are some additional caveats related to the filter method and the type of image you are copying (e.g. depth buffers cannot use linearly interpolation), but since you are discussing "full scale" here, I imagine you are interested in GL_NEAREST anyway.

What is faster? Framebuffer color attachment or full screen texture quad?

I want to draw fullscreen frames of a sequence, and switch between them fast. I saw that I could attach multiply color attachments to a framebuffer.
I'm wondering if it could be far cheaper to use renderbuffer attachments instead of the current textured quads method.
How can I switch between attachments by the way? Is there a maximum number of attachments?
I want to draw fullscreen frames of a sequence, and switch between them fast.
Drawing images always means uploading the data to a texture and drawing a quad using that texture. Look into Pixel Buffer Objects to implement asynchronous data upload and glTexStorage (OpenGL-4.2 feature) for how to bolt the memory layout down.
I saw that I could attach multiply color attachments to a framebuffer.
The framebuffers this applies to are off-screen framebuffer objects, and not the on screen framebuffer. I.e. this won't help you in any way.

Blend FBO onto default framebuffer

To clarify, when I say 'default framebuffer' I mean the one provided by the windowing system and what ends up on your monitor.
To improve my rendering speeds for a CAD app, I've managed to separate out the 3D elements from the Qt-handled 2D ones, and they now each render into their own FBO. When the time comes to get them onto the screen, I blit the 3D FBO onto the default FB, and then I want to blend my 2D FBO on top of it.
I've gotten to the blitting part fine, but I can't see how to blend my 2D FBO onto it? Both FBOs are identical in size and format, and they are both the same as the default FB.
I'm sure it's a simple operation, but I can't find anything on the net - presumably I'm missing the right term for what I am trying to do. Although I'm using Qt, I can use native OpenGL commands without issue.
A blit operation is ultimately a pixel copy operation. If you want to layer one image on top of another, you can't blit it. You must instead render a full-screen quad as a texture and use the proper blending parameters for your blending operation.
You can use GL_EXT_framebuffer_blit to blit contents of the framebuffer object to the application framebuffer (or to any other). Although, as the spec states, it is not possible to use blending:
The pixel copy bypasses the fragment pipeline. The only fragment
operations which affect the blit are the pixel ownership test and
the scissor test.
So any blending means to use fragment shader as suggested. One fullscreen pass with blending should be pretty cheap, I believe there is nothing to worry about.
use shader to read back from frame buffer. this is OpenGL ES extension, not support by all hardware.
https://www.khronos.org/registry/gles/extensions/EXT/EXT_shader_framebuffer_fetch.txt

Is it possible to save the current viewport and then re draw the saved viewport in OpenGL and C++ during the next draw cycle?

I want to know if I can save a bitmap of the current viewport in memory and then on the next draw cycle simply draw that memory to the viewport?
I'm plotting a lot of data points as a 2D scatter plot in a 256x256 area of the screen and I could in theory re render the entire plot each frame but in my case it would require me to store a lot of data points (50K-100K) most of which would be redundant as a 256x256 box only has ~65K pixels.
So instead of redrawing and rendering the entire scene at time t I want to take a snapshot of the scene at t-1 and draw that first, then I can draw updates on top of that.
Is this possible? If so how can I do it, I've looked around quite a bit for clues as to how to do this but I haven't been able to find anything that makes sense.
What you can do is render the scene into a texture and then first draw this texture (using a textured full-screen quad) before drawing the additional points. Using FBOs you can directly render into a texture without any data copies. If these are not supported, you can copy the current framebuffer (after drawing, of course) into a texture using glCopyTex(Sub)Image2D.
If you don't clear the framebuffer when rendering into the texture, it already contains the data of the previous frame and you just need to render the additional points. Then all you need to do to display it is drawing the texture. So you would do something like:
render additional points for time t into texture (that already contains the data of time t-1) using an FBO
display texture by rendering textured full-screen quad into display framebuffer
t = t+1 -> step 1.
You might even use the framebuffer_blit extension (which is core since OpenGL 3.0, I think) to copy the FBO data onto the screen framebuffer, which might even be faster than drawing the textured quad.
Without FBOs it would be something like this (requiring a data copy):
render texture containing data of time t-1 into display framebuffer
render additional points for time t on top of the texture
capture framebuffer into texture (using glCopyTexSubImage2D) for next loop
t = t+1 -> step 1
You can render to texture the heavy part. Then when rendering the scene, render that texture, and on top the changing things.