A basic question concerning glReadPixels

Hi there,

i’m getting mad with glReadPixels and i don’t know what i do wrong…

i have a quiet complex program using a lot of 2d-textures with some of them renderd as frambuffers. Now i want to read pixels from some texture and the result i get is always 0.

What i do is currently this:

    glBindTexture      (GL_TEXTURE_2D,  buf->buf_Texture);
    
    int tb, at;
    glGetIntegerv      (GL_TEXTURE_BINDING_2D, &tb);                  
    glGetIntegerv      (GL_ACTIVE_TEXTURE,       &at);                  
    Debug             (2,"Active: " + tostr(at-GL_TEXTURE0)    + ((tb>0) ?"	Binding: " + tostr(tb) : ""));

    glPixelStorei      (GL_PACK_ALIGNMENT, 1) ;
    glReadPixels        (0,0, buf->buf_W, buf->buf_H, GL_RGB, GL_FLOAT, tArr);
    

    Debug             (2,
           tostr(tArr[96+0]) + " - " + tostr(tArr[96+1]) + " - " + tostr(tArr[96+2]) + "
" 
        + tostr(tArr[96+3]) + " - " + tostr(tArr[96+4]) + " - " + tostr(tArr[96+5]) + "
" 
        + tostr(tArr[96+6]) + " - " + tostr(tArr[96+7]) + " - " + tostr(tArr[96+8]) + "
" 
        + tostr(tArr[96+9]) + " - " + tostr(tArr[96+10]) + " - " + tostr(tArr[96+11]));

As you can see i have a lot of test-outputs, so i’m sure, the correct texture is bound. The same texture is used otherwhise later, so i’m sure, i’s not empty and there is almost no black pixel inside. But for all the red pixels the result is zero.

Any idea what is wrong??

Thanks for reading,

Frank

glReadPixels() doesn’t read pixels from a texture, but from a framebuffer (either a FBO or the default framebuffer).

If you want to read the entire contents of a texture, use glGetTexImage(). In OpenGL 4.5, you can use glGetTextureSubImage() to read a rectangular portion.

When reading from a FBO, bind the FBO to either GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER (a FBO bound to GL_DRAW_FRAMEBUFFER won’t affect glReadPixels()). If you’re reading a colour buffer, call glReadBuffer() with the appropriate GL_COLOR_ATTACHMENT* constant.

Okay, this explains a lot. Especiall some other effect i had when trying around with this problem, but…

As my class, which is refered by “buf” and that is used to organize my textures already has an existing framebuffer which had been created using “GL_FRAMEBUFFER” like this:

    if (!buf_FBO) {
        glGenFramebuffers       (1, &buf_FBO);
        glBindFramebuffer       (GL_FRAMEBUFFER, buf_FBO);
        glFramebufferTexture2D  (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buf_Texture, 0);
        
    }
    else glBindFramebuffer      (GL_FRAMEBUFFER, buf_FBO);
    
    if (depthMode == _MDT_Render3d)  CreateDepthBuffer   ();

    return                      buf_FBO;    

…i just have bound it again.

So my code is now:

    glBindTexture      (GL_TEXTURE_2D,  buf->buf_Texture);
    glBindFramebuffer  (GL_FRAMEBUFFER,  buf->buf_FBO);
 
    int tb, at;
    glGetIntegerv      (GL_TEXTURE_BINDING_2D, &tb);                  
    glGetIntegerv      (GL_ACTIVE_TEXTURE,       &at);                  
    Debug              (2,"Active: " + tostr(at-GL_TEXTURE0)    + ((tb>0) ?"	Binding: " + tostr(tb) : ""));
 
    glPixelStorei      (GL_PACK_ALIGNMENT, 1) ;
    glReadPixels       (0,0, buf->buf_W, buf->buf_H, GL_RGB, GL_FLOAT, tArr);
 
 
    Debug              (2,
           tostr(tArr[96+0]) + " - " + tostr(tArr[96+1]) + " - " + tostr(tArr[96+2]) + "
" 
        + tostr(tArr[96+3]) + " - " + tostr(tArr[96+4]) + " - " + tostr(tArr[96+5]) + "
" 
        + tostr(tArr[96+6]) + " - " + tostr(tArr[96+7]) + " - " + tostr(tArr[96+8]) + "
" 
        + tostr(tArr[96+9]) + " - " + tostr(tArr[96+10]) + " - " + tostr(tArr[96+11]));

Unfortunately the result is still zero.

I also tried to call “glFramebufferTexture2D” after “glBindFramebuffer”, but with the same result.

I’m not sure whether it matters in this instance, but in general a texture shouldn’t be bound to a texture unit while it’s also attached to a bound FBO.

Other things to try include:

[ul]
[li] Checking the return value from glGetError().
[/li][li] Retrieving the texture contents using glGetTexImage() to confirm whether it actually contains zeros.
[/li][li] Filling the buffer (tArr) with some non-zero value prior to calling glReadPixels() so you can distinguish between glReadPixels() returning zeros and it not returning anything.
[/li][/ul]

Okay, i get some result with glGetTexImage(), but…

maybe need some help anyway. Especially because of your question concerning “texture units attached to a bound FBO” I have the idea, that i do something wrong generally.

What i do in my application is, to chain some internal rendering-processes, by using the result of some of them as textures for others, before the result is rendered to the display. So my clsBuffer-object (each has control about one texture / FBO) generates FBOs and textures mostly parallel. What is wrong with this?

Also it would be good if i could get glReadPixels to work for other things. There are one or two functions, where i need it, to get a few pixels. Currently i use a workaround for these, but i was always wondering why i have to render them temporarily to a texture / fbo to get e result. The answer is, that i did not know that glReadPixels requires a framebuffer. But even if i use my existing FBO, i still get no result with glReadPixels.

By the way: Generally i’m still learning OpenGL, i’m hobby-brogrammer and not a native english-speaker. So it’s somtimes not easy for me to understand professional tutorials. For a long time i worked with quiet simple thechnics now and concentrated on the UI of my application. This is mostly finished, so now i have to learn more advanced OpenGL…

The one case where it’s definitely a problem is if the shader is able to read from a texture which is also bound to the current framebuffer. That results in undefined behaviour. Note that it doesn’t matter whether the shader actually reads from the texture, only whether it’s possible (i.e. if the texture is bound to a texture unit and that texture unit is accessible via a sampler uniform inside the shader).

Some other situations may require memory barriers between writing and reading to ensure that the read sees the data which was written.

The one case where it’s definitely a problem is if the shader is able to read from a texture which is also bound to the current framebuffer.

That’ not really, what i wrote, but in fact i do this also and it works for a long time now without problems. Maybe it might be a problem with other hardware…

Is there a correct way to do this?

Use different textures for input and output. If the intent is to incrementally update a texture, then you’d render the contents of the previous texture onto the new texture before rendering anything else.

Okay, this is not complicated. There is (surely) only one texture used as destination at once. So i have to make a copy of this single one before rendering onto it, if i want to use it as source also.

Thank you…

A framebuffer object can have up to GL_MAX_COLOR_ATTACHMENTS colour buffers; as of OpenGL 4.6, this value is required to be at least 8.

Yes. The precise constraints are given in §9.3 “Feedback Loops Between Textures and the Framebuffer” of the OpenGL 4.6 specification (similar language exists in any version supporting render-to-texture, but the section number may vary).

Hello again…

OpenGL 4.6

I have a Thinkpad with Intel HD4000 - so OpenGL 4.0 is the latest version i can use. But i’m still learning 3.0

The precise constraints are given in §9.3 “Feedback Loops Between Textures and the Framebuffer” of the OpenGL 4.6 specification

As already said: references are mostly written too complicated for my english-skills.

similar language exists in any version supporting render-to-texture

This might be one of my basic mistakes: Is there a way to rander to a texture without using a framebuffer? Somehow i thought this is the correct solution.

Best,
Frank

[QUOTE=art-ganseforth;1292632]
This might be one of my basic mistakes: Is there a way to rander to a texture without using a framebuffer? [/QUOTE]
No. Rendering to a texture requires using a FBO, although using a FBO doesn’t always involve textures (renderbuffers can be used instead).

I said “render to texture” rather than FBOs because I wasn’t certain whether the original FBO extension allowed textures (it does) or whether they were added later. The issue of feedback loops doesn’t apply to renderbuffers.