polyclick
polyclick

Reputation: 2703

How to read pixels from a rendered texture in OpenGL ES

I'm trying to read pixels from a texture which was generated on the fly (RTT, Render To Texture). I'm taking this snapshot by implementing Apple's suggested method listed here.

This works fine for the "default" colorbuffer which gets presented to the screen but I can't get this to work for the pixels that were written to the texture.

I'm having trouble with these lines:

// Bind the color renderbuffer used to render the OpenGL ES view
// If your application only creates a single color renderbuffer which is already bound at this point,
// this call is redundant, but it is needed if you're dealing with multiple renderbuffers.
// Note, replace "_colorRenderbuffer" with the actual name of the renderbuffer object defined in your class.
glBindRenderbufferOES(GL_RENDERBUFFER_OES, _colorRenderbuffer);

// Get the size of the backing CAEAGLLayer
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

The problem is that I don't have a colorbuffer because I'm rendering into a texture.

Here's how I create my texture:

void Texture::generate()
{
    // Create texture to render into
    glActiveTexture(unit);
    glGenTextures(1, &handle);
    glBindTexture(GL_TEXTURE_2D, handle);

    // Configure texture
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

Here's how I link it to the FBO used for rendering into:

void Texture::attachToFrameBuffer(GLuint framebuffer)
{
    this->framebuffer = framebuffer;

    // Attach texture to the color attachment of the provided framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle, 0);
}

As you can see, I don't really have a _colorRenderbuffer where I can bind to in the first place. I first thought that binding to the framebuffer and then executing Apple's code would do the trick but backingWidth and backingHeight don't give me the resolution of my texture (2048x2048) but the resolution of my scene (320x320). So I guess I'm missing something here.

Upvotes: 2

Views: 10492

Answers (1)

Christian Rau
Christian Rau

Reputation: 45948

Befor you can render into a texture, it needs to have some internal storage, so you need to call glTexImage2D at some point before rendering into it (probably passing NULL as image data, thus just allocating the texture image).

but backingWidth and backingHeight don't give me the resolution of my texture

Why do you want to retrieve those values anyway (of course those retrieval functions won't work since they work on a renderbuffer as their names suggest). You already know it, since it was you who created the texture (see above).

Once you rendered into the texture you can just call glReadPixels as you would do to capture the normal screen, since your texture is now the framebuffer, so reading pixels from the framebuffer reads the pixels from the texture (of course the FBO has to still be bound when calling that glReadPixels).

That's actually the only way to read back any texture data in ES, which doesn't have glGetTexImage, but since you just rendered into it anyway this is absolutely no problem.

Upvotes: 1

Related Questions