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
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.