It is not uncommon that one wants to be able to create and save images from an OpenGL application. This might be for promotional purposes, a WWW page, documentation, creating frames for an animation etc. This short note gives a simple example on how this can be done, making it elegant and suited to your own needs is left as an exercise.
The first example creates a raw image file but of course it can be modified to write any image format. The source code is given here: WindowDump(). The key parts are setting the read buffer correctly, glReadBuffer(GL_BACK_LEFT); and reading the buffer image glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);
NoteThis example will write two stereo pairs if the application supports stereo buffers.
This example writes the bytes out individually, with some loss of generality this could be greatly simplified with fwrite(). Writing single bytes can cope with formats that might reverse the colour components such as TARGA, it is also convenient to sometimes flip the image vertically.
The above function should be called before the buffers are swapped. While this doesn't make much difference on most OpenGL implementations, strictly speaking the the back buffers are undefined after the swap.
One restriction of the above method is that one is limited to screen resolution, how does one create a higher resolution image? One way to handle this is to render the scene N times (N = 4 in the followng example), each time the viewport is set so as to capture the appropriate subimage.
if (dobigdump) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
CreateTheProjection(); /* - Application Specific - */
for (i=0;i<4;i++) {
for (j=0;j<4;j++) {
fprintf(stderr,"Frame (%d,%d)\n",i,j);
ClearTheBuffers(); /* - Application Specific - */
glViewport(-i*width,-j*height,4*width,4*height);
glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_BACK);
glLoadIdentity();
gluLookAt(vp.x,vp.y,vp.z,focus.x,focus.y,focus.z,up.x,up.y,up.z);
MakeLighting();
MakeMaterial();
DrawTheModel(); /* - Application Specific - */
WindowDump();
glutSwapBuffers();
}
}
dobigdump = FALSE;
}
NoteThis example makes no attempt to stitch the images back together, the idea here is to present the technique, the details are left up to the reader. The local solution is to have a post processing tool that collages the images into the one 4x4 grid.
It is sometimes necessary to check the maximum viewport size, on most "decent" systems this is 65536 x 65536. The maximum size is obtained using glGet() and GL_MAX_VIEWPORT_DIMS, for example glGetIntegerv(GL_MAX_VIEWPORT_DIMS,num);