PDA

View Full Version : FBO render to texture and glReadPixels



John Qualis
10-16-2010, 06:30 AM
I have set up FBOs as given below and rendering a simple OpenGL 3D object (say rotating teapot) to texture with a NULL image. I am trying to capture pixel data using glReadPixels. I see the 3D object correctly on the screen. But glReadPixels gives junk data. I wonder where I am going wrong. Any help/pointers is appreciated.



void display()
{
glEnable(GL_TEXTURE_2D); // Enable texturing so we can bind our frame buffer texture
glEnable(GL_DEPTH_TEST); // Enable depth testing


// Initialize the FBO
int WIDTH=window_width;
int HEIGHT=window_height;

glGenTextures(1, &fbo_texture); // Generate one texture
glBindTexture(GL_TEXTURE_2D, fbo_texture); // Bind the texture fbo_texture

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, window_width, window_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); // Create a standard texture with the width and height of our window

// Setup the basic texture parameters
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glGenRenderbuffersEXT(1, &fbo_depth);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_depth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, WIDTH, HEIGHT);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo_depth );


glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_texture, 0); // Attach the texture fbo_texture to the color buffer in our frame buffer
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo_depth); // Attach the depth buffer fbo_depth to our frame buffer

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
GLenum status;
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status == GL_FRAMEBUFFER_COMPLETE_EXT)
std::cout << "Framebuffer is ready for rendering\n" << std::endl;


glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // Bind our frame buffer for rendering
glPushAttrib(GL_VIEWPORT_BIT | GL_ENABLE_BIT); // Push our glEnable and glViewport states
glViewport(0, 0, window_width, window_height); // Set the size of the frame buffer view port

glClearColor (0.0f, 0.0f, 1.0f, 1.0f); // Set the clear colour
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear the depth and colour buffers
glLoadIdentity(); // Reset the modelview matrix

glTranslatef(0.0f, 0.0f, -5.0f); // Translate back 5 units

glRotatef(rotation_degree, 1.0f, 1.0f, 0.0f); // Rotate according to our rotation_degree value

glutSolidTeapot(1.0f); // Render a teapot
glPopAttrib(); // Restore our glEnable and glViewport states

glReadPixels(0, 0, window_width, window_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels[i]);

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind our texture

//now display

glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations

glTranslatef(0.0f, 0.0f, -2.0f);

glBindTexture(GL_TEXTURE_2D, fbo_texture); // Bind our frame buffer texture

glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner


glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner


glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner


glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glColor3f(0.0f,1.0f,0.0f); //green

glEnd();

glutSwapBuffers();
}

carsten neumann
10-16-2010, 08:46 AM
I think you are missing a call to glReadBuffer() to select which color attachment to read from.

John Qualis
10-16-2010, 09:00 AM
I tried calling glReadBuffer(GL_COLOR_ATTACHMENT0_EXT) before glReadPixels. The call returns 0 (succeeds) but the data I see is all set to ff ff 00 00

mhagain
10-16-2010, 09:54 AM
ff ff 00 00 is your clear color, so the buffer you're reading has been cleared before you do the read. Try commenting out some of your glClear calls to get an idea for what's going on here.

You probably shouldn't be generating new texture and buffer objects during your display function either; just generate them once at startup then bind and use during display.