Search code examples
openglopengl-es-2.0opengl-3

Porting OpenGL ES Framebuffer to OpenGL


I got the following code working perfectly fine on iOS and Android:

unsigned int depth_texture = 0,
             framebuffer = 0;

glGenTextures( 1, &depth_texture );
glBindTexture( GL_TEXTURE_2D, depth_texture );

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

glTexImage2D( GL_TEXTURE_2D,
              0,
              GL_DEPTH_COMPONENT,
              256,
              256,
              0,
              GL_DEPTH_COMPONENT,
              GL_UNSIGNED_INT,
              NULL );

glBindTexture( GL_TEXTURE_2D, 0 );

glGenFramebuffers( 1, &framebuffer );

glBindFramebuffer( GL_FRAMEBUFFER, framebuffer );

glFramebufferTexture2D( GL_FRAMEBUFFER,
                        GL_DEPTH_ATTACHMENT,
                        GL_TEXTURE_2D,
                        depth_texture,
                        0 );

unsigned int type = glCheckFramebufferStatus( GL_FRAMEBUFFER );

if( type == GL_FRAMEBUFFER_COMPLETE )
{ printf( "Complete!" ); }
else
{ printf( "Error!" ); }

Now I'm porting this code to OpenGL Desktop (2.1 and up) and it refuses to work. I always get the error GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER. The only way I found to make it work is to specify a COLOR_ATTACHMENT (which would fix the draw buffer error). I read the GL glFrameBuffer docs, and I cannot comprehend why the code above wouldn't work. All I want to is to render ONLY the depth into a texture... Am I missing something?


Solution

  • If you don't want to render to any color buffers, you need a call that specifies that:

    glDrawBuffer(GL_NONE);
    

    This is per framebuffer state, so it needs to be called while the FBO is bound.

    If you miss this, you will get the error you're seeing, as specified for the error conditions under "Framebuffer Completeness" in the OpenGL 3.3 spec:

    The value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE must not be NONE for any color attachment point(s) named by DRAW_BUFFERi.

    {FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER}

    The default draw buffer for FBOs is GL_COLOR_ATTACHMENT0, so this error condition applies if you don't have an attachment for GL_COLOR_ATTACHMENT0, and leave the draw buffer at the default.

    To avoid the very similar GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER error condition, you will also need to set the read buffer to GL_NONE:

    glReadBuffer(GL_NONE);
    

    These error conditions are not listed in any OpenGL ES spec, as far as I could find. So the glDrawBuffer() call is not needed there.

    It gets stranger still: Checking all the desktop OpenGL specs starting at 3.0, where FBOs were introduced, the error condition is listed in the specs for 3.1, 3.2, 3.3, and 4.0. It was not in 3.0, and even more interestingly, it is gone in 4.1 and later. As pointed out by @derhass in a comment, this was part of the ARB_ES2_compatibility extension that became core in OpenGL 4.1.

    Memorize this, and you can show off at the next OpenGL trivia night. If there is such a thing. :)