People‎ > ‎John Stavrakakis‎ > ‎John's blog‎ > ‎

Using ColorBuffer and DepthBuffer from OpenGL

posted 5 Mar 2012, 20:18 by John Stavrakakis   [ updated 5 Mar 2012, 20:19 ]
If you ever have a need for both colour buffer and depth buffer, than this might interest you.

In the simplest way, you could render all your objects to screen and simply use glReadPixels:

    GLint viewport[4];

    glGetIntegerv(GL_VIEWPORT, viewport);

    int imgsize = viewport[2] * viewport[3];

    unsigned char *pixmap = (unsigned char*)malloc(sizeof(unsigned char) * imgsize * 4);

    glReadPixels(0, 0, viewport[2], viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, pixmap);

    ...

    unsigned char *depthmap = (unsigned char*)malloc(sizeof(unsigned char) * imgsize * 1);

    glReadPixels(0, 0, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, depthmap);


Then operate on the memory of pixmap and depthmap at your leisure. 

If you find that you could do most operations on the GPU, then it is worth using textures to avoid heavy read back operations. Frame buffer objects are the best way to approach this. For most purposes, the depth buffer is unimportant for read back, this is where a RenderBuffer object is defined and used to store the depth without letting the programmer deal with it.

    GLuint rboId[1];

    GLuint fboId[1];    

    GLuint textureId[1];

    // texture created here

    glGenTextures(1, textureId);

    ...

    

    // create a renderbuffer object to store depth info

    glGenRenderbuffersEXT(1, rboId);

    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rboId[0]);

    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,

                             width, height);

    

    // create a framebuffer object

    glGenFramebuffersEXT(1, fboId);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId[0]);

    

    // attach the texture to FBO color attachment point

    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,

                              GL_TEXTURE_2D, textureId[0], 0);

    

    // attach the renderbuffer to depth attachment point

    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,

                                 GL_RENDERBUFFER_EXT, rboId[0]);

    

    check_fbo_status(); // see if everything is ok

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind


To obtain both the colour and the depth, simply create two textures with the appropriate parameters (as in glReadPixels read back) and skip the render buffer construction. Instead of attaching the render buffer object to the FBO for depth, use the texture name instead.

    GLuint rboId[1];

    GLuint fboId[1];    

    GLuint textureId[2];


    // texture created here

    glGenTextures(2, textureId);

    ... // parameters for color buffer texture

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,

                 GL_RGBA, GL_UNSIGNED_BYTE, 0);

    ... // parameters for depth texture

    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, width, height, 0

                 GL_DEPTH_COMPONENT, GL_FLOAT, 0);

    

    // create a framebuffer object

    glGenFramebuffersEXT(1, fboId);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId[0]);

    

    // attach the texture to FBO color attachment point

    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,

                              GL_TEXTURE_2D, textureId[0], 0);

    

    // Attach the texture to FBO depth attachment point  

    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, 

                              GL_TEXTURE_2D, textureId[1], 0);

    

    check_fbo_status(); // see if everything is ok

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind



To use it all, swap the framebuffer to FBO, and restore it (0) when done.

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId[0]); // bind

    

    render();

    

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // Unbind

    


Comments