Screen capture problems

I’m trying to implement a screen capture feature in an OpenGL program.


GLubyte* ssBuffer;

ssBuffer = new GLubyte[pixelCount * 3];

glReadPixels(0, 0, windowInfo.actualWidth, windowInfo.actualHeight, GL_RGB, GL_UNSIGNED_BYTE, ssBuffer);

for (int i = 0; i < pixelCount * 3; i+=3) {
outfile << ssBuffer[i + 2]; // B
outfile << ssBuffer[i + 1]; // G
outfile << ssBuffer[i]; // R
}

The problem is that part of whatever is behind the OpenGL window is captured in the file. For example, part of Visual C++'s screen is in the screen capture, when the OpenGL window should take up all of it.

Thanks,
Greg

I think the OpenGL specs state that the contents of the frame buffer is unknown where the GL window is covered by another window… And there is no workaround about this.

Your best bet is to render offscreen (in a DIB).

Regards.

Eric

The problem is that it’s capturing part of whatever is BEHIND the OpenGL window, not what’s over it. Weird, ain’t it? I have no idea what is going on with it. Any other ideas?

Oops sorry: I should read more carefully !

Can you e-mail me a sample app that demonstrates the bug ?

One or two things to check: is your rendering context correctly set up when calling glReadPixels (check wglMakeCurrent) ?

As a side question: what type of hardware/drivers are you using ?

Regards.

Eric

LOL don’t worry, I do it ALL the time.

I’ll email the code, but one thing is that I have no idea what wglMakeCurrent is. Hmmm.

I’m running two machines, an SGI 540 with 1 gig of RAM and the Cobalt graphics chipset(latest drivers) and an SGI/Intergraph Zx10 with 1.5 gigs of RAM and a Wildcat 4210 (also latest drivers).

Thanks Eric,
Greg

I looked at the wglMakeCurrent function, and the only thing is that I’m using GLUT, and I don’t know how to get the window handle. Also, I’d like to keep this as cross-platform as possible. Isn’t there a cross-platform way to do a screen capture?

Thanks,
Greg

This is just a thought, but when do you do your screen capture, and are you using double buffering?

More specifically, are you doing something like so?

RenderScene();
glutSwapBuffers();
GetScreenCapture();

or

RenderScene();
GetScreenCapture();
glutSwapBuffers();

You should be using the second method. If you use the first, then that could be what is causing your problem.

Deiussum,
I don’t know exactly when the screen capture occurs. I’m using GLUT, and I have it set to screen capture when the user presses the “s” key. Any idea when it happens?

Are you using double buffering then? If so, you are probably running into the problem where you are grabbing from a backbuffer that hasn’t had a scene drawn to it yet, thus there is no telling what may be on it. Perhaps you could set a global boolean to say that next frame you need to take a screenshot, then reset that boolean after you’ve taken it. Just one possible solution, but it should work.

how about

keyboard_callback()
{
case ‘s’: s_pressed=true;
}

btw the following 2 are standard for doublebuffed windows
glReadBuffer( GL_BACK )
glDrawBuffer( GL_BACK )

RenderScene();
glFlush();
if ( s pressed )
GetScreenCapture();
glutSwapBuffers();

Got it working! Big thanks to Eric, Deiussum, and Zed. I placed a call to glReadBuffer(GL_FRONT) before glReadPixels, and that fixed it.

Continued challenges on the screen capture I’m afraid. It works fine when my OpenGL window is small, but if it’s say larger than 600 pixels in any direction, it barfs. The resulting image is skewed, like there’s an extra pixel in each row. I don’t know if my screen resolution has anything to do with it, but it’s at 1920 x 1200. Too much for it to handle?

perhaps check out the glPixelStore(…) operations eg glPixelStore( GL_PACK_ALIGNMENT, 1 )

Thanks for the tip, Zed. Now it really does work great! Now for the little nitty-gritty detail: it takes a LONG time to finish. When I do a print screen, it takes maybe two seconds. What gives?

Have you checked whether the slow bit is glReadPixels or your output code to the PIX file ? If it is the former, there’s really nothing you can do about it…

Regards.

Eric