0

Background:
I am trying to draw primitives into the default window-system framebuffer object. I have three objects which correctly get rendered. Now, I want to generate my own framebuffer object to contain these same images, but have each object rendered in a flat unique color ID to be used for selection during run-time. The user will be presented with three objects, will select one of the objects by a mouse click, then the code will read a pixel in the framebuffer object to determine the color. Once the color has been read, the color of the object will be changed to indicate that it has been selected.

Problem:
For some reason, glBindFramebuffer(GL_FRAMEBUFFER, fbo); is giving me a GL_INCOMPLETE_DRAW_BUFFER after a call to glCheckFramebufferStatus(GL_FRAMEBUFFER). The code is attached. Maybe I'm not setting the framebuffer object up correctly? Or, maybe VMWare doesn't allow framebuffer objects? I would like to have some sanity check to ensure this is the correct way of doing framebuffer objects.

Code (hopefully just the relevant parts):

void initFrameBuffers()
{
    glGenRenderbuffers(NumRBOs, rbos);
    glBindRenderbuffer(GL_RENDERBUFFER, rbos[COLOR]);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, WIDTH, HEIGHT);
    glBindRenderbuffer(GL_RENDERBUFFER, rbos[DEPTH]);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WIDTH, HEIGHT);

    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);   // Causes the error
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbos[COLOR]);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbos[DEPTH]);

    glEnable(GL_DEPTH_TEST);

    // Re-enable the default window-system framebuffer for drawing
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}

void drawToFBO()
{
    // Load the user defined framebuffer object
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    glDrawBuffer(GL_COLOR_ATTACHMENT0);
    glViewport(0, 0, WIDTH, HEIGHT);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Draw into the user defined framebuffer object, not the default window-system FBO
    glBindVertexArray(vaos[CYLINDER]);
    glDrawArrays(GL_TRIANGLES, 0, cylinder.vertices.size());

    // Re-enable the default window-system framebuffer
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}

Now, I'm not sure if I need to do anything special before I call my initFrameBuffers method, but this is what I'm doing. My main function just makes a call to initFrameBuffers, then calls my init() method, which draws three objects into the default window-system FBO.

I have tried this same code in a newer version of Kubuntu, and it gives me a different error code: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT instead of GL_INCOMPLETE_DRAW_BUFFER. I'm definitely not sure on what is going on here. I'm reading through the red book eighth edition, and am following what they suggest, but cannot seem to get past getting my framebuffer to bind.

AivanF.
  • 1,134
  • 2
  • 23
  • 52
user1298780
  • 109
  • 1
  • 2
  • 4
  • Did you create a VAO before? I think it's required to use framebuffers. – subb May 27 '13 at 04:50
  • Try making calls to glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &w), etc. to see if the renderbuffers are being created properly. – Little Endian May 27 '13 at 05:15
  • 3
    glBindFramebuffer cannot give you completeness errors. So where *exactly* are you check for completeness? – Nicol Bolas May 27 '13 at 07:04
  • @subb: Yeah, in the init() method call, I generate my vertices, store them in a data structure containing a std::vector (for the vertices), std::vector normals (for the vertex normals), and std::vector colors (for the vertex colors only in the new framebuffer). The VAOs are generated in init() by calling glGenVertexArrays(NumVAOs, vaos);. Also, the VBOs are generated on the next line of code by calling glGenBuffers(NumVBOs, vbos); – user1298780 May 27 '13 at 13:24
  • @Nicol Bolas: Well look at that... it doesn't check for completeness of a framebuffer. I was checking for completeness after each gl* call within the initFrameBuffers() method by calling a checkErrors() function. This switched based on the result from a call to glCheckFramebufferStatus(GL_FRAMEBUFFER). Checking for the errors again after I bind my renderbuffer objects to the framebuffer object results in a GL_FRAMEBUFFER_COMPLETE return value. So the framebuffer is now setup with a color and depth renderbuffer, but why can't I draw in it? It always draws in the window-system framebuffer. – user1298780 May 27 '13 at 13:28
  • @user1298780 I just noticed that you are using GL_DRAW_FRAMEBUFFER as a target. Unless you want to use the glBlitFramebuffer function, you should use GL_FRAMEBUFFER. – subb May 27 '13 at 17:41
  • @subb: I actually was using glBlitFramebuffer to transfer the drawn vertices onto the default window-system framebuffer. It was a way to verify that the objects being drawn were going to appear correctly. – user1298780 May 28 '13 at 01:11
  • I posed the question of why I couldn't draw into my newly created frame buffer object. I believe I have this figured out. I can now correctly draw three objects in the FBO, render the same object over top of it in another buffer, then perform selections based on the pixel read from the FBO. I'm not really sure what changed, except that I was more conscious about where I was invoking glDrawBuffer, glReadBuffer, and paying more attention to which buffer was bound when the drawing routine was being invoked. I must have had a bad combination of bound buffers being read from and written to. – user1298780 May 28 '13 at 01:19

1 Answers1

1

As was pointed out, glBindFramebuffer(..) does not return a state indicating frame buffer completeness. I was using the call to glCheckFramebufferStatus(GL_FRAMEBUFFER) after each call within my initFrameBuffers() routine. However, I did not check the status after I was binding the render buffers to the frame buffer. If I would have done so, I would have seen that I was indeed setting the render and frame buffers up correctly.

Regarding usage of the frame buffer, I must have been leaving the window-system frame buffer attached whenever I was performing a draw, since every draw was not occurring within the FBO, but on the window-system frame buffer. After paying attention to where I was binding the FBOs and how I was calling glDrawBuffer and glReadBuffer, I seem to have gotten it correct. I can now render an object into the window-system frame buffer using Phong lighting then render the same object into the FBO using a solid color. Once the object has been rendered into the two buffers, I can use glReadPixels to determine when the user clicks on the object by performing a color look-up from within the FBO.

AivanF.
  • 1,134
  • 2
  • 23
  • 52
user1298780
  • 109
  • 1
  • 2
  • 4