Every other frame is completely black..

I am using a barebones OpenGL app without a display. I am just using glReadPixels to get the rendered image.

I am dumping the result of glReadPixels after each frame is drawn, but the problem is that every other frame is completely black. This is fixed if I call glClear twice before drawing anything. Can anyone tell me what’s causing this problem? Thanks.

Source [runs in linux]:


#include <stdio.h>
#include <stdlib.h>

#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glu.h>

Display *dpy;
Window root;
GLint att[] = { GLX_RGBA, true, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo *vi;
GLXContext glc;

GLsizei width = 24;
GLsizei height =24;
GLfloat aspect = (float)width/height;
GLubyte *pixels;

void setup()
{
    dpy = XOpenDisplay(NULL);

    if ( !dpy ) {
        printf("
	cannot connect to X server

");
        exit(0);
    }

    root = DefaultRootWindow(dpy);
    vi = glXChooseVisual(dpy, 0, att);

    if (!vi) {
        printf("
	no appropriate visual found

");
        exit(0);
    }

    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    glXMakeCurrent(dpy, root, glc);

    printf("vendor: %s
", (const char*)glGetString(GL_VENDOR));

    pixels = new GLubyte[3*(width+1)*(height+1)+3];

    glViewport(0,0,width,height);
}

void draw()
{
    float degrees = 0;

    // Render some frames
    for (int i=0; i<4; i++)
    {
        glClear(GL_COLOR_BUFFER_BIT);
        //glClear(GL_COLOR_BUFFER_BIT); // uncommenting this fixes the problem...

        // Set Projection
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0, aspect, 0.1,1000);

        // Set ModelView
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        glTranslatef(0,0,-3);
        glRotatef(degrees,0,0,1);

        // draw Square
        glBegin(GL_QUADS);
        glVertex3d(0,1,0);
        glVertex3d(1,0,0);
        glVertex3d(0,-1,0);
        glVertex3d(-1,0,0);
        glEnd();

        // get pixels
        glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,(void*)pixels);
        
        // print buffer to terminal using ascii characters
        int count = 0;
        for(int y=0;y<height;y++)
        {
            for(int x=0;x<width;x++)
                printf("%02x", pixels[count+=3] & 0xFF);
            puts("");
        }
        puts("");
        
        // increase rotation
        degrees += 10;
    }
}

int main(int argc, const char* argv[]){
    setup();
    draw();
    return 0;
}

Output:
Notice that every other frame is completely black.


vendor: NVIDIA Corporation
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
0000000000000000000000ffff0000000000000000000000
00000000000000000000ffffffff00000000000000000000
0000000000000000ffffffffffffff000000000000000000
00000000000000ffffffffffffffff000000000000000000
000000000000ffffffffffffffffffff0000000000000000
00000000ffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffffff000000000000
0000ffffffffffffffffffffffffffffffff000000000000
0000ffffffffffffffffffffffffffffffffff0000000000
000000ffffffffffffffffffffffffffffffffff00000000
00000000ffffffffffffffffffffffffffffffff00000000
00000000ffffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffff000000000000
000000000000ffffffffffffffffffff0000000000000000
00000000000000ffffffffffffffff000000000000000000
00000000000000ffffffffffffff00000000000000000000
0000000000000000ffffffff000000000000000000000000
000000000000000000ffff00000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
00000000000000000000000000ffffff0000000000000000
000000000000000000ffffffffffffff0000000000000000
0000000000ffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffff00000000000000
00000000ffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffff000000000000
0000000000ffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffff00000000000000
000000000000ffffffffffffff0000000000000000000000
000000000000ffffff000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

Output after adding two glClear calls before drawing:


vendor: NVIDIA Corporation
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
00000000000000000000ffff000000000000000000000000
000000000000000000ffffffff0000000000000000000000
0000000000000000ffffffffffff00000000000000000000
00000000000000ffffffffffffffff000000000000000000
000000000000ffffffffffffffffffff0000000000000000
0000000000ffffffffffffffffffffffff00000000000000
00000000ffffffffffffffffffffffffffff000000000000
000000ffffffffffffffffffffffffffffffff0000000000
0000ffffffffffffffffffffffffffffffffffff00000000
0000ffffffffffffffffffffffffffffffffffff00000000
000000ffffffffffffffffffffffffffffffff0000000000
00000000ffffffffffffffffffffffffffff000000000000
0000000000ffffffffffffffffffffffff00000000000000
000000000000ffffffffffffffffffff0000000000000000
00000000000000ffffffffffffffff000000000000000000
0000000000000000ffffffffffff00000000000000000000
000000000000000000ffffffff0000000000000000000000
00000000000000000000ffff000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
0000000000000000000000ffff0000000000000000000000
00000000000000000000ffffffff00000000000000000000
0000000000000000ffffffffffffff000000000000000000
00000000000000ffffffffffffffff000000000000000000
000000000000ffffffffffffffffffff0000000000000000
00000000ffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffffff000000000000
0000ffffffffffffffffffffffffffffffff000000000000
0000ffffffffffffffffffffffffffffffffff0000000000
000000ffffffffffffffffffffffffffffffffff00000000
00000000ffffffffffffffffffffffffffffffff00000000
00000000ffffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffff000000000000
000000000000ffffffffffffffffffff0000000000000000
00000000000000ffffffffffffffff000000000000000000
00000000000000ffffffffffffff00000000000000000000
0000000000000000ffffffff000000000000000000000000
000000000000000000ffff00000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
00000000000000000000000000ffff000000000000000000
0000000000000000000000ffffffff000000000000000000
000000000000000000ffffffffffffff0000000000000000
00000000000000ffffffffffffffffff0000000000000000
00000000ffffffffffffffffffffffff0000000000000000
0000ffffffffffffffffffffffffffffff00000000000000
0000ffffffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffffff000000000000
000000ffffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffffff0000000000
00000000ffffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffffffff00000000
0000000000ffffffffffffffffffffffffffffff00000000
000000000000ffffffffffffffffffffffff000000000000
000000000000ffffffffffffffffff000000000000000000
000000000000ffffffffffffff0000000000000000000000
00000000000000ffffffff00000000000000000000000000
00000000000000ffff000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
00000000000000000000000000ffffff0000000000000000
000000000000000000ffffffffffffff0000000000000000
0000000000ffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffff00000000000000
000000ffffffffffffffffffffffffffff00000000000000
00000000ffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffff000000000000
00000000ffffffffffffffffffffffffffff000000000000
0000000000ffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffffffff0000000000
0000000000ffffffffffffffffffffffff00000000000000
000000000000ffffffffffffff0000000000000000000000
000000000000ffffff000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000

It work correctly on my computer with a single glClear.

Are you getting a single buffer or a double buffer?

GLint att[] = {
  GLX_RGBA, true,
  GLX_DEPTH_SIZE, 24,
  GLX_DOUBLEBUFFER, None };

This part is wrong, if you want a double buffer you must write GLX_DOUBLEBUFFER, True,
None };

Also you are sure that create the context using the root window it’s safe? Probably that’s why you are getting an undefined behaviour. Try to use a pixel buffer.


#include <stdio.h>
#include <stdlib.h>

#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glu.h>

Display *dpy;
Window root;
XVisualInfo *vi;
GLXContext glc;
GLXPbuffer pBuffer; 
const GLsizei width  =  32;
const GLsizei height = 32;
const GLfloat aspect = (float)width/height;
GLubyte pixels[width*height];

void setup()
{
    dpy = XOpenDisplay(NULL);

    if ( !dpy ) {
        printf("
	cannot connect to X server

");
        exit(1);
    }
    root = DefaultRootWindow(dpy);
    int numFbCfg;
    GLint att[] = {
        GLX_DRAWABLE_TYPE, GLX_PBUFFER,
        GLX_RENDER_TYPE, GLX_RGBA_BIT,
        GLX_DEPTH_SIZE, 24,     // why you need the depth?
        GLX_DOUBLEBUFFER, True,
        None
    };
    GLXFBConfig *fbConfig = glXChooseFBConfig(dpy, XDefaultScreen(dpy), att, &numFbCfg);
    if(numFbCfg == 0)
    {
        printf("Error FbConfig");
        exit(1);
    }
    vi = glXGetVisualFromFBConfig(dpy, fbConfig[0]);

    if (!vi) {
        printf("
	no appropriate visual found

");
        exit(1);
    }

    GLint pBuffAttrib [] = {
        GLX_PBUFFER_WIDTH, width,
        GLX_PBUFFER_HEIGHT, height,
        None
	};
    pBuffer = glXCreatePbuffer(dpy, fbConfig[0], pBuffAttrib); 

    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    glXMakeCurrent(dpy, pBuffer, glc);

    printf("vendor: %s
", (const char*)glGetString(GL_VENDOR));

    glViewport(0,0,width,height);
    XFree(vi);
    XFree(fbConfig);
}

void draw()
{
    float degrees = 0;

    // Render some frames
    for (int i=0; i<4; i++)
    {
        glClear(GL_COLOR_BUFFER_BIT);
        //glClear(GL_COLOR_BUFFER_BIT); // uncommenting this fixes the problem...

        // Set Projection
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0, aspect, 0.1,1000);

        // Set ModelView
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.f, 0.f, -3.f);
        glRotatef(degrees,0,0,1);

        // draw Square
        glBegin(GL_QUADS);
        glVertex3d(0,1,0);
        glVertex3d(1,0,0);
        glVertex3d(0,-1,0);
        glVertex3d(-1,0,0);
        glEnd();

        // get pixels
        glReadPixels(0,0,width,height,GL_RED,GL_UNSIGNED_BYTE,(void*)pixels);
        
        // print buffer to terminal using ascii characters
        for(int y=0;y<height;y++)
        {
            for(int x=0;x<width;x++)
                printf("%02x", pixels[x+width*y] & 0xFF);
            puts("");
        }
        puts("");
        glXSwapBuffers(dpy, pBuffer); 
        // increase rotation
        degrees += 10;
    }
}

int main(int argc, const char* argv[]){
    setup();
    draw();
    return 0;
}

Rosario,

Your code worked for me. Thanks for the improvements and corrections. Some pieces were taken from different examples online, so I appreciate the clean up.

Is it important to use glXSwapBuffers if I’m only reading from the back buffer? I noticed it ran fine without it. On second thought, I guess I don’t really need double buffering either for something like this.