Important: Please read the Qt Code of Conduct -

OpenGL ES 2.0 & the Depth Buffer/Texture

  • I'm currently in the process of implementing shadow mapping for my OpenGL app and ran across this depth buffer issue - according to the OpenGL ES 2.0 specs (both PowerVR and, a texture format GL_DEPTH_COMPONENT is not supported. However I tried and it does compile for Harmattan. Didn't yet run it to see whether there is an error. Any experiences on this? I really dislike the idea of having to pack the depth values into a RGBA texture.

    • Matti

  • It would appear that the SGX 530, at least, does not.

    Which would be sad since the performance I'm getting out of a RGBA packed depth texture is not very good. I'll check with glGetString() later. The most modern phones seem to support the extension (ref google) so I guess it's worth implementing even if mine doesnt .)

  • Well, welcome to OpenGL world. :)

    I hope you will survive extension hell. :)

  • Well, the device seems to have extensions GL_OES_depth_texture, GL_OES_depth24, GL_OES_texture_float etc. which would hint that this should work. However if I try to pass GL_DEPTH_COMPONENT as the format, glTexImage2D() fails - well, this is what the OpenGL ES 2.0 spec does say, after all, GL_DEPTH_COMPONENT is not among the supported choices.

    I tried creating a RGBA texture and was able to attach it to a FBO as GL_DEPTH_ATTACHMENT using glFramebufferTexture2D() and everything goes fine on paper. Rendering / reading that texture doesnt really work like with a depth texture (which I have working on the desktop build very nicely).

    Such a shame.

  • See kids, this is what happens when you don't read the documentation :) Changing the <type> parameter to GL_UNSIGNED_INT did the trick. I'll share the code so maybe the next guy is spared the hassle:

    Creating the FBO:

    @bool GLController::CreateDepthTextureAndFBO(GLuint* fboId,
    GLuint* depthTextureId,
    GLuint* renderBuffer,
    int width, int height)
    // Create a framebuffer object
    glGenFramebuffers(1, fboId);
    glBindFramebuffer(GL_FRAMEBUFFER, *fboId);

    // Create a render buffer
    glGenRenderbuffers(1, renderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, *renderBuffer);
    // Create a texture for storing the depth
    glGenTextures(1, depthTextureId);
    glBindTexture(GL_TEXTURE_2D, *depthTextureId);
    // Remove artifact on the edges of the shadowmap
    Debug("glGetError() 0 = 0x%x", glGetError());
    if ( m_hasDepthTextureExtension )
        // We'll use a depth texture to store the depths in the shadow map
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0,
        // Attach the depth texture to FBO depth attachment point
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                               GL_TEXTURE_2D, *depthTextureId, 0);
        // We'll use a RGBA texture into which we pack the depth info
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        // Attach the RGBA texture to FBO color attachment point
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                               GL_TEXTURE_2D, *depthTextureId, 0);
        // Allocate 16-bit depth buffer
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
        // Attach the render buffer as depth buffer - will be ignored
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                                  GL_RENDERBUFFER, *renderBuffer);
    // check FBO status
    GLenum fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if ( fboStatus != GL_FRAMEBUFFER_COMPLETE )
        Debug("FBO not complete: 0x%x", fboStatus);
        return false;
    // Go back to using the default frame buffer
    glBindFramebuffer(GL_FRAMEBUFFER, DefaultFramebufferId);
    return true;


    Shaders for rendering the depth:

    @const char* DepthShadowMapVertexShader =
    "precision highp float;\n"
    "attribute vec3 in_coord;\n"
    "uniform mat4 mvp_matrix;\n"
    "void main()\n"
    " gl_Position = mvp_matrix * vec4(in_coord, 1.0);\n"

    const char* DepthShadowMapFragmentShader =
    "precision highp float;\n"
    "void main()\n"

    Shaders using the shadow map: see

    Cheers to Fabian Sanglard +others for help and ideas on this issue.

    • Matti

  • Happy to see it works! :)

  • I have a question.
    In case with m_hasDepthTextureExtension == true.
    Do I need attach render buffer?

    Because in another case glCheckFramebufferStatus may return error incomplete framebuffer, right?

Log in to reply