Dear OpenGl Community,
I have a strange problem with glReadPixels. Maybe you have a suggestion for me.
I was playing around with this function a bit and noticed a strange effect as soon as I display objects, which don’t contain solid color. On screen they render fine but the pixels I read show strange patterns. To get closer to the source of the problem I wrote a quick and dirty demo program, which just displays one single quad and then uses glReadPixels to read all pixels of the viewport. Those I write to a tga file.
As soon as I apply a gradient to that quad I get the folowing effect. On top is a screenshot of the window, bottom are the read pixels. Its vertically mirrored since I was to lazy to change the origin before writing the tga.
If I use a solid color for the quad all works fine. Also for multiple quads. But as soon as I have a gradient it screws up the read pixels. It gets even worse if I map a texture with an uneven pattern onto the quad - which is what I eventually want to do.
#include <windows.h>
#include <gl\glew.h>
#include <gl\glut.h>
#include <gl\freeglut_ext.h>
#include <iostream>
#include <stdio.h>
//helpers
void renderScene(void)
{
glClear (GL_COLOR_BUFFER_BIT );
glBegin(GL_QUADS);
glColor3f(1,0,0);
glVertex2f(10 , 10);
glVertex2f(10, 512 +10);
glVertex2f(512 + 10 , 512 +10 );
/** glReadPixels will work if a solid color is used on this quad,
* so commenting out folowing line will give correct behaviour */
glColor3f(0,1,0);
glVertex2f(512 + 10 , 10);
glEnd();
glFlush();
}
void changeSize(GLsizei w, GLsizei h)
{
glViewport(0,0,w,h);
//Reset the coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w , 0, h , 1,-1);
glMatrixMode(GL_MODELVIEW );
glLoadIdentity();
}
bool writeTGA(const std::string & filename, unsigned char * texture, unsigned int width, unsigned int height, unsigned int bpp)
{
FILE *file = fopen(filename.c_str(), "w");
if( file == NULL)
return false;
GLubyte header[] = {
00,00,02, 00,00,00, 00,00,00, 00,00,00,
0xff & width, 0xff & width >> 8,
0xff & height, 0xff & height >> 8,
bpp, 0x20
};
fwrite( header, sizeof(header), 1, file);
fwrite(texture, width * height * bpp / 8, 1, file);
fclose(file);
return true;
}
//main
int main(int argc, char ** argv)
{
unsigned int windowW = 800;
unsigned int windowH = 600;
int windowId = 0;
std::cout << "ReadPixels Test" << std::endl;
std::cout << "-----------------------------
" << std::endl;
//Setup FreeGlut
int tmpArg = 0;
glutInit(&tmpArg, NULL);
// Note: glutSetOption is only available with freeglut
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(windowW, windowH);
windowId = glutCreateWindow("glReadPixels Test");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
//setup some opengl states
glClearColor (0.5, 0.5, 0.5, 1.0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
//adjust window size
changeSize(windowW, windowH);
//main loop
int counter = 200;
while(counter--)
{
glutPostRedisplay();
glutMainLoopEvent();
glutSwapBuffers();
if(50 == counter )
{
unsigned char * texture = (unsigned char *)malloc(windowW * windowH * 3);
memset(texture, 0x00, windowW * windowH * 3);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, windowW , windowH, GL_BGR, GL_UNSIGNED_BYTE, texture);
//write pixels to file
writeTGA("testout.tga", texture, windowW, windowH, 24);
free(texture);
}
Sleep(25);
}
return 0;
}
This seems like one of those problems, where I stare at my code for too long and just don’t see the obvious. At least I hope it’s that trivial and some of you can point me to my error. I have looked through forum and internet and this problem seems to be not very common - I found no references describing this behaviour.
Query for the gl version string returns 3.3.0 at my system . I’m using freeglut to setup the opengl window, in case you want to test that code.
I have played around with all kinds of opengl settings but I just don’t seem to find the right switch here. GL_PACK_ALIGNMENT seems not the problem here, though I still set it to 1 just to make sure. I also tried to move swapBuffers behind the glReadPixels since I read it somewhere in the forum but it changes nothing.
Thanks,
Michael