high resolution snapshot in opengl with framebuffer - opengl

i am using opengl to set texture to 3d object.then snapshot and blend it other picture.
i wanna to high resolution snapshot(3000*1500 px). is it possible in opengl?
my code is:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawScene();
DrawText();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
if (g_fboSamples > 0)
{
// Multisample rendering so copy the pixel data in the multisample
// color render buffer image to the FBO containing the offscreen
// texture image.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, g_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, g_fboResolveTarget);
glBlitFramebufferEXT(0, 0, g_fboWidth, g_fboHeight,
0, 0, g_fboWidth, g_fboHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
// At this point we now have our scene fully rendered to our offscreen
// texture 'g_offscreenTexture'. This is where you would perform any
// post processing to the offscreen texture.
// Finally to display the offscreen texture to the screen we draw a screen
// aligned full screen quad and attach the offscreen texture to it.
BYTE* pixels = new BYTE[ 3 *g_fboWidth*g_fboHeight];
//glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, g_fboWidth, g_fboHeight, GL_RGB, GL_UNSIGNED_BYTE, pixels);
bitmap.create(g_fboWidth, g_fboHeight);
bitmap.setPixels(pixels,g_fboWidth, g_fboHeight,3);
bitmap.flipVertical();
bitmap.saveBitmap("test.png");
glViewport(0, 0, g_windowWidth, g_windowHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawFullScreenQuad();
//g_fboWidth= 2732, g_fboHeight=1536 , g_windowWidth=683 and g_windowHeight=384
test.png:
http://i.imgur.com/1MKySdV.jpg

It looks like your viewport in the framebuffer is to small. Call glViewport(g_fboWidth, g_fboHeight).

Related

Using glTexImage2D to render to texture, blank result. (Dreamcast GLdc)

I am trying to create a quick render to texture example using GLdc, a OpenGL implementation for the Sega Dreamcast. I have verified that both my Texture and Framebuffer Object are complete, yet the texture resulting from the framebuffer only has 1 white dot in it.
First, I generate an empty texture and prepare it to be written to.
func genTextures(){
glGenTextures(1, &renderedTexture[0]);
glBindTexture(GL_TEXTURE_2D, renderedTexture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smaller than texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
Next, I generate an FBO and bind the new texture we just created to it.
func genFBO() {
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, renderedTexture[0], 0);
}
At this point the FBO and the Texture should both be considered complete. The main loop is structured something like this:
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
genTextures();
genFBO();
while(1) {
if(check_start())
break;
// I checked here for FBO and Texture completeness, both return True.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // bind to the FBO
DrawGLScene(); // Draw our cube to the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // back to default
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
ReSizeGLScene(640,480);
DrawGLUI(); //Draw the quad with the framebuffers texture
}
return 0;
}
Here are the two functions that draw geometry:
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f); // move 5 units into the screen.
glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis
glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis
glRotatef(zrot,0.0f,0.0f,1.0f); // Rotate On The Z Axis
glBindTexture(GL_TEXTURE_2D, texture[0]); // choose the texture to use.
glBegin(GL_QUADS); // begin drawing a cube
// Draw my textured cube, works fine.
glEnd(); // done with the polygon.
xrot+=1.5f; // X Axis Rotation
yrot+=1.5f; // Y Axis Rotation
zrot+=1.5f; // Z Axis Rotation
glKosSwapBuffers();
}
void DrawGLUI(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, renderedTexture[0]);
glBegin(GL_QUADS);
//glColor3f(1.0f, 0.0f, 0.0);
glTexCoord2f(0.0, 0.0); glVertex2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex2f(0.0, 1.0);
glEnd();
glEnable(GL_DEPTH_TEST);
ReSizeGLScene(640,480);
glFlush();
}
The result is
Where I would like to have the cube rendered to a texture then that texture applied to the quad in the upper right corner...
The size of the viewport must be adjusted to the size of the framebuffer with glViewport when the framebuffer is switched:
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glViewport(0, 0, 128, 128);
// [...]
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glViewport(0, 0, 640, 480);
// [...]

How to draw from a Multisampled buffer to default frame buffer

I am trying to render from a multisampled framebuffer to a default frame buffer.
first i enable multisampling with these commands.
glfwWindowHint(GLFW_SAMPLES, 4);
glEnable(GL_MULTISAMPLE);
Than i create a multisampled buffer
unsigned int fboMsaaId, rboDepthId;
unsigned int MsaaTexture;
// Generate texture
glGenTextures(1, &MsaaTexture);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 800, 600, false);
// create a multisample buffer
glGenFramebuffers(1, &fboMsaaId);
glGenRenderbuffers(1, &rboDepthId);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH24_STENCIL8, 800, 600);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, MsaaTexture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,rboDepthId);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
In the render loop.
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboMsaaId);
glDrawBuffer(GL_BACK);
glBlitFramebuffer(0, 0, 800, 600, 0, 0, 800, 600, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glfwSwapBuffers(window);
glfwPollEvents();
}
If i render into the default framebuffer i am able to see the drawn object but when i blit from multisampled frame buffer to default frame buffer nothing is drawn on the screen.
What you want to do is make it so that the default framebuffer is not multisampled. That is, you want to blit from a multisampled framebuffer to a non-multisampled framebuffer.
Yes, it is legal to blit between two multisampled framebuffers, but this is only legal if they have the same sample count. And while you did request a 4-sampled default framebuffer, the default framebuffer is not entirely under your control. Implementations get to play fast-and-loose as to how many samples a default framebuffer gets.
So it's best to avoid this possibility altogether and use a non-multisampled default framebuffer.

Render FFmpeg AVFrame as OpenGL texture?

I'm attempting to to render a jpeg image (1024x1024 pixels) in the form of an FFmpeg AVFrame as a texture in OpenGL. What I get instead is something that appears as a 1024x1024 dark green quad:
The code to render the AVFrame data in OpenGL is shown below. I have convinced myself that the raw RGB data held within the FFmpeg AVFrame data is not solely dark green.
GLuint g_texture = {};
//////////////////////////////////////////////////////////////////////////
void display()
{
// Clear color and depth buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); // Operate on model-view matrix
glEnable(GL_TEXTURE_2D);
GLuint texture = g_texture;
glBindTexture(GL_TEXTURE_2D, texture);
// Draw a quad
glBegin(GL_QUADS);
glVertex2i(0, 0); // top left
glVertex2i(1024, 0); // top right
glVertex2i(1024, 1024); // bottom right
glVertex2i(0, 1024); // bottom left
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glFlush();
}
/* Initialize OpenGL Graphics */
void initGL(int w, int h)
{
glViewport(0, 0, w, h); // use a screen size of WIDTH x HEIGHT
glEnable(GL_TEXTURE_2D); // Enable 2D texturing
glMatrixMode(GL_PROJECTION); // Make a simple 2D projection on the entire window
glOrtho(0.0, w, h, 0.0, 0.0, 100.0);
glMatrixMode(GL_MODELVIEW); // Set the matrix mode to object modeling
//glTranslatef( 0, 0, -15 );
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the window
}
//////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
std::shared_ptr<AVFrame> apAVFrame;
if (!load_image_to_AVFrame(apAVFrame, "marble.jpg"))
{
assert(false);
return 1;
}
// From here on out, the AVFrame is RGB interleaved
// and is sized to 1,024 x 1,024 (power of 2).
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowSize(1060, 1060);
glutInitWindowPosition(0, 0);
glutCreateWindow("OpenGL - Creating a texture");
glGenTextures(1, &g_texture);
//glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, g_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, apAVFrame->width,
apAVFrame->height, 0, GL_RGB, GL_UNSIGNED_BYTE,
apAVFrame->data[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* We will use linear interpolation for magnification filter */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* We will use linear interpolation for minifying filter */
initGL(1060, 1060);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
Environment:
Ubuntu 18.04
GCC v8.2
EDIT: As per #immibis' suggestion below, it all works when I change the rendering of the quad to:
// Draw a quad
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2i(0, 0); // top left
glTexCoord2f(1, 0);
glVertex2i(1024, 0); // top right
glTexCoord2f(1, 1);
glVertex2i(1024, 1024); // bottom right
glTexCoord2f(0, 1);
glVertex2i(0, 1024); // bottom left
glEnd();
You forgot to give your vertices texture coordinates, so all the pixels on your screen are reading the same pixel from the texture. (The top-left, or wherever the default texture coordinates are)
Use glTexCoord2f before glVertex2i to set the texture coordinates for the vertex. They go from 0 on the top/left of the texture, to 1 on the bottom/right, so the corners of the texture are 0,0, 1,0, 1,1 and 0,1.

Rendering a second pass yields a different result

Currently I'm trying to render multiple passes with different shaders in a simple OpenGL application. Here's my (simplified) code:
void InitScene()
{
glViewport(0, 0, mWindowWidth, mWindowHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, mWindowWidth, mWindowHeight, 0, -1, 1);
mFramebufferName = CreateFrameBuffer(mWindowWidth, mWindowHeight);
}
void DrawScene()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
if(drawDirectlyToScreen)
{
// This works fine, image will fill the whole screen
// Directly draw to the screen
DrawFullScreenQuad();
}
else
{
// This does not work. The image from the first pass will only be a small quadrat
// Draw to frame buffer instead of screen
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
DrawFullScreenQuad();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Get ready for second pass
BindFrameBufferTextureAndActivateAnotherShader();
// Now draw to the screen
DrawFullScreenQuad();
}
glPopMatrix();
}
void DrawFullScreenQuad()
{
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, mWindowHeight, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(mWindowWidth, mWindowHeight, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(mWindowWidth, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
glEnd();
}
void CreateFrameBuffer(int width, int height)
{
// Generate and bind the frame buffer
mFramebufferName = 0;
glGenFramebuffers(1, &mFramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
// Create and bind the render texture
glGenTextures(1, &mSecondPassRenderTexture);
glBindTexture(GL_TEXTURE_2D, mSecondPassRenderTexture);
// Give an empty image to OpenGL ( the last "0" )
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
// Set "mSecondPassRenderTexture" as colour attachement #0
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mSecondPassRenderTexture, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers
}
When rendering only one pass everything is fine. The image covers the whole screen. When rendering with two passes, the resulting image will only cover a small square area in the top left corner of the screen (see the attached images).
The problem seems to come from the first pass. The texture created in that pass is already wrong (i.e. the image is only in the corner, the rest of the texture is black). The second pass then works correctly (i.e. the broken texture is drawn correctly to the whole screen).
So my question is: why does my call to DrawFullScreenQuad() yield different results when
Rendering to the screen directly
Rendering to a frame buffer (which has the same size as the window)

OpenGL depth buffer or depth test does not work when rendering with a shared context

I have a very specific OpenGL setup where the 3D geometry in the scene does not render. There is some depth-related state in the OpenGL context that illudes me.
This is in a production engine at work where we added shared context support with multiple window contexts. We are doing the rendering to a framebuffer object owned by the shared context, then blitting the color attachment renderbuffer to a window using a different context.
The clear color is showing in the resulting blit to the window, but not the 3D scene geometry itself, so we know the framebuffer and renderbuffer objects are at least partially correct.
To illustrate, I refactored a sample from the LearnOpenGL website to illustrate my bug. It shows up there as well, so I am clear this is something I am missing.
Here is the GitHub project where I made three commits to a working framebuffer sample so that it rendered to the framebuffer using a shared context and then blits the result: Framebuffer Shared Context Experiment
Here is most of the source code that produces the buggy result. I snipped a few sections that went unchanged.
// glfw dummy window creation
// --------------------
GLFWwindow* dummy = NULL;
#if USE_SHARED_CONTEXT
dummy = glfwCreateWindow(1, 1, "Dummy", NULL, NULL);
if (dummy == NULL)
{
std::cout << "Failed to create dummy GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(dummy);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, dummy);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwShowWindow(window);
#if !USE_SHARED_CONTEXT
glfwMakeContextCurrent(window);
#endif
// <snip creation of shared resources>
// <snip creation of un-shared vertex array>
// framebuffer configuration
// -------------------------
unsigned int framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
#if 1
// create a color attachment render buffer
unsigned int Colorbuffer;
glGenRenderbuffers(1, &Colorbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer); // now actually attach it
#else
// create a color attachment texture
unsigned int textureColorbuffer;
glGenTextures(1, &textureColorbuffer);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorbuffer, 0);
#endif
// create a renderbuffer object for depth and stencil attachment (we won't be sampling these)
unsigned int rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo); // now actually attach it
// now that we actually created the framebuffer and added all attachments we want to check if it is actually complete now
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// <snip timing and input>
#if USE_SHARED_CONTEXT
// use shared context because that is what is holding our framebuffer and vao.
// -----
glfwMakeContextCurrent(dummy);
#endif
// render
// ------
// bind to framebuffer and draw scene as we normally would to color texture
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)
// make sure we clear the framebuffer's content
glClearColor(1.0f, 0.1f, 0.1f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// following render is unchanged
shader.use();
glm::mat4 model;
glm::mat4 view = camera.GetViewMatrix();
glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
// cubes
glBindVertexArray(cubeVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, cubeTexture);
model = glm::translate(model, glm::vec3(-1.0f, 0.0f, -1.0f));
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
model = glm::mat4();
model = glm::translate(model, glm::vec3(2.0f, 0.0f, 0.0f));
shader.setMat4("model", model);
glDrawArrays(GL_TRIANGLES, 0, 36);
// floor
glBindVertexArray(planeVAO);
glBindTexture(GL_TEXTURE_2D, floorTexture);
shader.setMat4("model", glm::mat4());
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
#if 1
#if USE_SHARED_CONTEXT
// use window context for presentation via blit.
// -----
glfwMakeContextCurrent(window);
// temorary framebuffer for visible window since framebuffers are not shared
// -------------------------
unsigned int readFramebuffer;
glGenFramebuffers(1, &readFramebuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, Colorbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, SCR_WIDTH, SCR_HEIGHT);
glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Colorbuffer);
#endif
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST);
#if USE_SHARED_CONTEXT
glDeleteFramebuffers(1, &readFramebuffer);
#endif
#else
// now bind back to default framebuffer and draw a quad plane with the attached framebuffer color texture
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST); // disable depth test so screen-space quad isn't discarded due to depth test.
// clear all relevant buffers
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
glClear(GL_COLOR_BUFFER_BIT);
screenShader.use();
glBindVertexArray(quadVAO);
glBindTexture(GL_TEXTURE_2D, textureColorbuffer); // use the color attachment texture as the texture of the quad plane
glDrawArrays(GL_TRIANGLES, 0, 6);
#endif
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// <snip epilog>
You can toggle the USE_SHARED_CONTEXT compile-time switch to remove the little bit of code that renders using a shared context.
I was missing a call to glViewport for the shared render context.
The value of the Viewport was defaulted to (0, 0) -> (width, height) for the context used by the visible window. The shared render context had been defaulted to (0, 0) -> (1, 1) because I used a width and height of 1 for the non-visible GLFW window.