redrawing the window using glDrawPixels?

Hi, I don’t know if this is the right way to be doing this, well, I guess not, because it doesn’t work. I successfully render an image to the single-buffered window, and wish to redraw it when glut calls the refresh callback. So I do this:

GLubyte screenPixels = (GLubyte) calloc
(4glutGet(GLUT_WINDOW_WIDTH)
glutGet(GLUT_WINDOW_HEIGHT), sizeof(GLfloat));

glReadPixels
  (0,0,glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT), 
   GL_RGBA, GL_UNSIGNED_BYTE, screenPixels);

glClear(GL_COLOR_BUFFER_BIT);
glDrawPixels
  (glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT),
  GL_RGBA , GL_UNSIGNED_BYTE , screenPixels);

When the DrawPixels finishes, my screen is white. It seems to be that the glReadPixels is not functioning correctly, because it reads all zeros, ones or 255’s depending on what format and type I use. glGetError reports no errors. I do have the correct buffer as current.
I’m using OpenGL on IRIX 6.5 (SGI).
any ideas? I don’t care how I get it working, if DrawPixels is wrong, I’m open to ideas. Looking at the GL pipeline, I don’t see how glReadPixels can really get that confused.
thx, Cc: by mail if possible, great!

[This message has been edited by wealthychef (edited 11-29-2000).]

[This message has been edited by wealthychef (edited 11-29-2000).]

Before calling glDrawPixels, do you set the current raster position to the bottom left corner of the window ?

I suggest you do it like this :

GLint depth_enabled;
GLint fog_enabled;
GLint texture2d_enabled;
GLint texture1d_enabled;
GLint saved_matrix_mode;

GLubyte screenPixels = (GLubyte)malloc(4 * glutGet(GLUT_WINDOW_WIDTH) * glutGet(GLUT_WINDOW_HEIGHT) * sizeof(GLfloat));

glReadBuffer(GL_FRONT);
glReadPixels(0,0,glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT), GL_RGBA, GL_UNSIGNED_BYTE, screenPixels);

// this is to speed up a bit
if(depth_enabled = glIsEnable(GL_DEPTH_TEST))
glDisable(GL_DEPTH_TEST);
if(fog_enabled = glIsEnabled(GL_FOG))
glDisable(GL_FOG);
if(texture2d_enabled = glIsEnable((GL_TEXTURE_2D))
glDisable(GL_TEXTURE_2D);
if(texture1d_enabled = glIsEnabled(GL_TEXTURE_1D))
glDisable(GL_TEXTURE_1D);

glGetIntegerv(GL_MATRIX_MODE, &saved_matrix_mode);
glMatrixMode(GL_PROJECTION);

glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0, (GLfloat) glutGet(GLUT_WINDOW_WIDTH), 0.0, (GLfloat) glutGet(GLUT_WINDOW_HEIGHT));
glRasterPos2i(0, 0);

glDrawBuffer(GL_FRONT);
glDrawPixels(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT), GL_RGBA, GL_UNSIGNED_BYTE, screenPixels);

free(screenPixels);

glPopMatrix();
glMatrixMode(saved_matrix_mode);

if(depth_enabled)
glEnable(GL_DEPTH_TEST);
if(fog_enabled)
glEnable(GL_FOG);
if(texture2d_enabled)
glEnable(GL_TEXTURE_2D);
if(texture1d_enabled)
glEnable(GL_TEXTURE_1D);

And if you read and write RGBA make sure you actually have an RGBA buffer.
Note that you don’t have to clear the color buffer before writting pixels in it.

Originally posted by Moz:
Before calling glDrawPixels, do you set the current raster position to the bottom left corner of the window ?

Yes, I do, as follows:
glRasterPos2i(0,0);
correct?

Remember that the raster position is transformed by the modelview and projection matrices. (0, 0) are NOT window coordinates, that’s why I change the projection matrix when I call glDrawPixels.
Taken from the red book :
The coordinates of the raster position are transformed to screen coordinates in exactly the same way as coordinates supplied with a glVertex*() command (that is, with the modelview and perspective matrices). After transformation, they either define a valid spot in the viewport, or they’re clipped out because the coordinates were outside the viewing volume. If the transformed point is clipped out, the current raster position is invalid.

So according to what I wrote above, you might also need to add this :
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
just before calling glRasterPos.

And if you need to dive into the red book for any kind of problem concerning OGL, it can be found here : http://helios.scripps.edu/library/SGI_bookshelves/SGIindex/SGI_Developer_OpenGL_PG.html

Originally posted by Moz:
[b]So according to what I wrote above, you might also need to add this :
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
just before calling glRasterPos.

And if you need to dive into the red book for any kind of problem concerning OGL, it can be found here : http://helios.scripps.edu/library/SGI_bookshelves/SGIindex/SGI_Developer_OpenGL_PG.html [/b]

Thanks for your posts, I’ve read them with great interest and will try them soon. I am not at work yet (ah, the student life :slight_smile:
I have the book you referenced and read the part you did but for some reason didn’t do anything about the matrix. I’ll try it; sounds promising. The actual calls to glReadPixels and glDrawPixels seem unchanged from mine, and I agree that the Clear call is unnecessary, but I’m flailing here. :slight_smile: In fact, the only substantial difference between your code is that you save state and use RasterPos correctly (details, details) :slight_smile:
I’m curious, though, as to why glReadPixels and glDrawPixels, which totally bypass Fog, Textures, etc. (looking at the OpenGL machine), are slowed down by those modes?
Anyhow, I am anxious to take your advice, so I’m off to work… thanks
More soon

Actually, glDrawPixels DOESN’T bypass fog, textures and the per-fragment tests. That is why you have to disable all of them if you don’t need them when calling glDrawPxixels … check the pipeline again (Chapter 8 figure 8-3).
And note that in my code, I don’t check that everything is disabled (alpha test, stencil test…).

Originally posted by Moz:
Actually, glDrawPixels DOESN’T bypass fog, textures and the per-fragment tests. That is why you have to disable all of them if you don’t need them when calling glDrawPxixels … check the pipeline again (Chapter 8 figure 8-3).
And note that in my code, I don’t check that everything is disabled (alpha test, stencil test…).

Hmm, still not working. Here’s what I did. Notice the glClear call for debugging purposes. Also notice that I disable GL_BLEND, the only other thing my code turns on explicitly elsewhere.
At the beginning of the code, there is an image in the window; at the end of this snippet, the screen is black–the image is gone.

GLint blend_enabled;
GLint depth_enabled;
GLint fog_enabled;
GLint texture2d_enabled;
GLint texture1d_enabled;
GLint saved_matrix_mode;

GLubyte screenPixels = (GLubyte)
malloc(4 * glutGet(GLUT_WINDOW_WIDTH) *
glutGet(GLUT_WINDOW_HEIGHT) *
sizeof(GLfloat));

glReadBuffer(GL_FRONT);
glReadPixels(0,0,glutGet(GLUT_WINDOW_WIDTH),
glutGet(GLUT_WINDOW_HEIGHT), GL_RGBA, GL_UNSIGNED_BYTE,
screenPixels);

/* this is to speed up a bit*/
if(blend_enabled = glIsEnabled(GL_BLEND))
glDisable(GL_BLEND);
if(depth_enabled = glIsEnabled(GL_DEPTH_TEST))
glDisable(GL_DEPTH_TEST);
if(fog_enabled = glIsEnabled(GL_FOG))
glDisable(GL_FOG);
if(texture2d_enabled = glIsEnabled(GL_TEXTURE_2D))
glDisable(GL_TEXTURE_2D);
if(texture1d_enabled = glIsEnabled(GL_TEXTURE_1D))
glDisable(GL_TEXTURE_1D);

glGetIntegerv(GL_MATRIX_MODE, &saved_matrix_mode);
glMatrixMode(GL_PROJECTION);

glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0, (GLfloat) glutGet(GLUT_WINDOW_WIDTH),
0.0, (GLfloat) glutGet(GLUT_WINDOW_HEIGHT));
glRasterPos2i(0, 0);

glDrawBuffer(GL_FRONT);
glDrawPixels(glutGet(GLUT_WINDOW_WIDTH),
glutGet(GLUT_WINDOW_HEIGHT), GL_RGBA, GL_UNSIGNED_BYTE,
screenPixels);

glPopMatrix();
glMatrixMode(saved_matrix_mode);

if(depth_enabled)
glEnable(GL_DEPTH_TEST);
if(fog_enabled)
glEnable(GL_FOG);
if(texture2d_enabled)
glEnable(GL_TEXTURE_2D);
if(texture1d_enabled)
glEnable(GL_TEXTURE_1D);

theories? thanks

[This message has been edited by wealthychef (edited 11-30-2000).]

Look at your mail chef !