Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/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 http://developer.meego.com/api/1.2/opengles-2.0/glTexImage2D.html), 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.

    http://www.rojtberg.net/348/powervr-sgx-530-does-not-support-depth-textures/

    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);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
    // Remove artifact on the edges of the shadowmap
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    
    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,
                     GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
    
        // Attach the depth texture to FBO depth attachment point
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
                               GL_TEXTURE_2D, *depthTextureId, 0);
    }
    else
    {
        // 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 =
    GLSL_VERSION_STRING
    "precision highp float;\n"
    "\n"
    "attribute vec3 in_coord;\n"
    "uniform mat4 mvp_matrix;\n"
    "\n"
    "void main()\n"
    "{\n"
    " gl_Position = mvp_matrix * vec4(in_coord, 1.0);\n"
    "}\n";

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

    Shaders using the shadow map: see http://fabiensanglard.net/shadowmapping/index.php#c5t_form

    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