views:

57

answers:

2

I have set up FBOs (GL_FRAMEBUFFER_EXT, color and depth buffers) and my app is rendering a simple OpenGL 3D object (a 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.

   Code is given below (in brief) -

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

   ......
   ......
   // setup depth buffer
   glGenRenderbuffersEXT(1, &fbo_depth); // Generate one render buffer and store the ID in fbo_depth
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_depth); // Bind the fbo_depth render buffer

glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, window_width, window_height); // Set the render buffer storage to be a depth component, with a width and height of the window

glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo_depth); // Set the render buffer of this buffer to the depth buffer

   ....
   .....
  //set up FBO
  glGenFramebuffersEXT(1, &fbo); // Generate one frame buffer and store the ID in fbo
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); // Bind our frame buffer

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

GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); // Check that status of our generated frame buffer

if (status != GL_FRAMEBUFFER_COMPLETE_EXT) // If the frame buffer does not report back as complete
{
    std::cout << "Couldn't create frame buffer" << std::endl; // Output an error to the console
    exit(0); // Exit the application
}


    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

    ....
    ....

    glutSwapBuffers();
    }
A: 

You need to bind your FBO first, then call glFramebufferTexture2D and other FBO calls.

Also to avoid such problems, you need to check the framebuffer status using glCheckFramebufferStatus, binding the FBO first, it will tell you if the framebuffer is complete and ready to be rendered to.

Also, if you draw to a texture, you can get the texture data with glGetTexImage.

Matias Valdenegro
I am binding the FBOs. As I said I see the 3D object on the screen and it is working fine. I just cant get glReadPixels to work.
John Qualis
Any thing to keep in mind when using glGetTexImage?
John Qualis
Bind the texture, and unbind the FBO.
Matias Valdenegro
glGetTexImage succeeds but all the pixels are set to ff 00 00, 00 ff 00, 00 00 ff and repeat.
John Qualis
A: 

You are passing in pixels[i]. It looks suspect. What has pixels been declared as? I can't tell from what you posted. I would most expect to see something like

glReadPixels(0, 0, window_width, window_height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

or

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

but it all depends on what your intent for pixels array is.

Montdidier