Search code examples
openglframebufferfbo

Write to OpenGL multiple renderbuffer failed


Not sure what is the problem, it failed to read the pixels when writing to multiple renderbuffer. Here is the code:

setup code:

// gen framebuffer object
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

// gen renderbuffer 0
glGenRenderbuffers(1, &rbo_color0);
glBindRenderbuffer(GL_RENDERBUFFER, rbo_color0);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo_color0);

// gen renderbuffer 1
glGenRenderbuffers(1, &rbo_color1);
glBindRenderbuffer(GL_RENDERBUFFER, rbo_color1);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RED_INTEGER, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rbo_color1);

// gen depth buffer
glGenRenderbuffers(1, &rbo_depth);
glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_depth);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

render and read pixel code:

// setup shader and uniforms...
// bind framebuffer and clear color/depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glEnable(GL_DEPTH_TEST);
glClearColor(0.f, 0.f, 0.f, 0.1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

const GLuint buffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, buffers);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, (void*)0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, data);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(x, y, 1, 1, GL_RED_INTEGER, GL_INT, (int*)(data) + 4);
glBindVertexArray(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

I used layout qualifier in the shader for the outputs, shouldn't be any problems there. So I think probably there is something wrong the the buffer setup or render code. I've succeed in reading the pixels when there is only one renderbuffer(rbo_color0). The main difference is:

  1. no generation code for renderbuffer1;
  2. use glDrawBuffer(rbo_color0) when rendering;
  3. the format of rbo_color0 is GL_RGBA(double checked the format setting in corresponding glRenderbufferStorage/glReadBuffer calls, no problem here);
  4. no read pixel call for rbo_color1.

Any helps?


Solution

  • GL_RED_INTEGER is not a proper internal format, as it can be used for the 2nd parameter of glRenderbufferStorage. A proper enumerator constant for the internal format would be GL_R32I.
    See OpenGL 4.6 API Compatibility Profile Specification; 8.26. TEXTURE IMAGE LOADS AND STORES; page 334

    If you would check for OpenGL erros (glGetError), then you would get an INVALID_ENUM error.

    Change the render buffer storage specification, to solve the issue:

    glRenderbufferStorage(GL_RENDERBUFFER, GL_R32I, w, h); 
    

    Note, you should check the framebuffer completeness by glCheckFramebufferStatus:

    GLenum fb_status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
    if ( fb_status != GL_FRAMEBUFFER_COMPLETE )
    {
      // error handling
    }