15

I am using an Android device running Froyo supporting OpenGL ES 1.1 and OpenGL ES 2.0

I want to render the depth buffer to a texture. Having seen a number of examples for OpenGL, OpenGL ES on other platforms (including iPhone) I have tried a number of FBO configurations.

I seem to be able to get an FBO set-up with a colour texture but every time I attach a depth texture it fails.

My current code is based on this example but creating a colour texture as well instead of setting draw and read buffers to none.

Is there a simple example of configuring an OpenGL ES FBO on Android to render depth to a texture? Alternatively is there a document describing what is and is not supported?


Thanks for the comments - I specifically needed a solution for ES 1.1, if it could be found and work on Android. I also want to look at ES 2 - I am not sure I understand the idea of packing the depth information into colour buffer - do you have a reference I can look at to understand the idea better?

Regarding code - my source is barely different from the link I posted above. The Framebuffer status is that it is not complete.


Thanks for the fragment shader suggestion - I get the idea now. Will look at that if I can't get another solution working. My ideal is to get depth and colour at the same time - don't really want to render colour and depth separately if I can help it.

ToolmakerSteve
  • 18,547
  • 14
  • 94
  • 196
Graham
  • 321
  • 1
  • 2
  • 7
  • 1
    Without being able to comment directly on Android's support for depth buffer attachment (and hence being unable to supply an actual answer), if you are willing to rely on ES 2.0 then a workaround is to pack depth information into a colour buffer and then unpack it at the relevant moment. The homogenous depth is always in the range 0 to 1 so a fixed point scheme isn't too problematic. – Tommy Oct 28 '10 at 10:11
  • You should post code. When it fails, what does it mean? It generates a GL error? What's is the Framebuffer status? – Dr. Snoopy Oct 29 '10 at 14:20
  • To pack the depth into a colour buffer you simply make a fragment shader that writes the Z position of a fragment out into the colour channel. If you're using Windows and want an example, download RenderMonkey and have a play with it, I'm pretty sure that one of the examples do this. – Gareth Davidson Nov 24 '10 at 11:40

2 Answers2

17

OK, an answer of sorts. Got this to work on Android 2.2 with OpenGL ES 2:

    // Create a frame buffer
    glGenFramebuffers( 1, &(frame_buffer ) );

    // Generate a texture to hold the colour buffer
    glGenTextures(1, &(colour_texture) );
    glBindTexture(GL_TEXTURE_2D, colour_texture);
    // Width and height do not have to be a power of two
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
            pixelWidth, pixelHeight,
            0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    // Probably just paranoia
    glBindTexture(GL_TEXTURE_2D, 0);

    // Create a texture to hold the depth buffer
    glGenTextures(1, &(depth_texture) );
    glBindTexture(GL_TEXTURE_2D, depth_texture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
            pixelWidth, pixelHeight,
            0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glBindTexture(GL_TEXTURE_2D, 0);        

    glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer);

    // Associate the textures with the FBO.

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                    GL_TEXTURE_2D, colour_texture, 0);

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

    // Check FBO status.    
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if ( status == GL_FRAMEBUFFER_COMPLETE )
    {
        // Success
    }

Pretty trivial really, follow the OpenGL ES2 manual and do everything in the right order.

Tried this with OpenGL ES 1.1, adding OES to the required function calls and _OES to the constants since frame buffer objects is an extension. Any attempt to attach a depth texture to the frame buffer results in an incomplete frame buffer object.

So at the moment my conclusion is that this doesn't work with OpenGL ES 1.1 on Android, but it clearly does work with ES 2.2.

If anyone has a solution for ES 1.1 it would be interesting to see it.

Graham
  • 321
  • 1
  • 2
  • 7
  • 1
    When it comes to ES 1.1 I have found examples that use the renderbuffer for depth, not a texture. – NebulaFox Dec 23 '10 at 18:51
  • 1
    Note that on Lollipop+, may need to first create a GL Context, and make it current, before any offscreen GL code - otherwise all GL calls give an error code. Before Lollipop, the framework's internal context was active when app code was called. (Not an issue for onscreen GL, because at the time the view is attached to the display, a context is created for you.) I'm still trying to find some easy way to create that context... – ToolmakerSteve Jan 03 '17 at 22:30
0

Rendering to a depth texture isn't supported on many devices. You'll need to attach a renderbuffer for your depth buffer.

rbgrn
  • 304
  • 2
  • 6
  • 1
    Thanks - that is useful to know. Can you provide some code or a link for how "to attach a renderbuffer for your depth buffer"? (Without such detail, this would be better as a comment on the existing answer, rather than a separate answer.) – ToolmakerSteve Jan 03 '17 at 18:55