OpenGL screenshot
Hi all, I'd like to add the possibility to take screenshots to my little OpenGL app, but I can't figure out how to do that. Generally I have no Idea whatsoever when it comes to save things to files... really I must have been creating completely useless software so far
Greetings,
Use glReadPixels() to capture the rendered buffer, then reformat the data and save it to a file in the image format you're most comfortable with (I use targa's, mostly because I use them for input as well, check out NEHE's tutorials for information on the format of targa files).
Cheers,
Rocco
Use glReadPixels() to capture the rendered buffer, then reformat the data and save it to a file in the image format you're most comfortable with (I use targa's, mostly because I use them for input as well, check out NEHE's tutorials for information on the format of targa files).
Cheers,
Rocco
Virus Out
Big Bang Board Games
Adventures on Pirate Isle
Solace - Strategy, War, and Glory!
The Belt
Hit command shift 3, sometimes it doesn't work with GL games or DivX movies, so make sure the scene is static
The follow group of functions allow you to write the pixels of the current OpenGL context to a TIFF image. It may have to be tweaked to suit your code.
Code:
-(void)saveSnapshotToFile:(NSString*)filePath
{
NSBitmapImageRep * bitmap;
GLint viewport[4];
long bytewidth;
GLint width, height;
long bytes;
glReadBuffer(GL_FRONT);
glGetIntegerv(GL_VIEWPORT, viewport);
width = viewport[2];
height = viewport[3];
bytewidth = width * 4;
bytewidth = (bytewidth + 3) & ~3;
bytes = bytewidth * height;
bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:width
pixelsHigh:height
bitsPerSample:8
samplesPerPixel:3
hasAlpha:NO
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:bytewidth
bitsPerPixel:8 * 4];
glFinish();
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glReadPixels(0, 0, width, height,
GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV,
[bitmap bitmapData]);
swizzleBitmap(bitmap);
NSData * tiff;
if (bitmap == NULL)
return;
tiff = [bitmap TIFFRepresentation];
[tiff writeToFile:filePath atomically:YES];
}
static inline void swapcopy32(void * src, void * dst, int bytecount )
{
uint32_t *srcP;
uint32_t *dstP;
uint32_t p0, p1, p2, p3;
uint32_t u0, u1, u2, u3;
srcP = src;
dstP = dst;
#define SWAB_PIXEL(p) (((p) << 8) | ((p) >> 24))
while ( bytecount >= 16 )
{
p3 = srcP[3];
p2 = srcP[2];
p1 = srcP[1];
p0 = srcP[0];
u3 = SWAB_PIXEL(p3);
u2 = SWAB_PIXEL(p2);
u1 = SWAB_PIXEL(p1);
u0 = SWAB_PIXEL(p0);
srcP += 4;
dstP[3] = u3;
dstP[2] = u2;
dstP[1] = u1;
dstP[0] = u0;
bytecount -= 16;
dstP += 4;
}
while ( bytecount >= 4 )
{
p0 = *srcP++;
bytecount -= 4;
*dstP++ = SWAB_PIXEL(p0);
}
}
static void swizzleBitmap(NSBitmapImageRep * bitmap)
{
int top, bottom;
void * buffer;
void * topP;
void * bottomP;
void * base;
int rowBytes;
rowBytes = [bitmap bytesPerRow];
top = 0;
bottom = [bitmap pixelsHigh] - 1;
base = [bitmap bitmapData];
buffer = malloc(rowBytes);
while ( top < bottom )
{
topP = (top * rowBytes) + base;
bottomP = (bottom * rowBytes) + base;
swapcopy32( topP, buffer, rowBytes );
swapcopy32( bottomP, topP, rowBytes );
bcopy( buffer, bottomP, rowBytes );
++top;
--bottom;
}
free( buffer );
}
But faster than the alternative, i.e. pausing the game and painting everything you see on a piece of canvas
to be honest, I haven't yet found my way around cocoa or obj-c. my whole code is basically the cocoa-app template, but without the nib or main.m files. GLUT handles all the windowing stuff, and all my drawing and interaction functions. its all written in plain C. I don't think I can use all these fancy cocoa NSBitmap things without major overhaul of the whole thing, which is not what I really want to do.
I think a library which makes such tasks like saving a frame to a picture would be the most straightforward way, or am I wrong?
I think a library which makes such tasks like saving a frame to a picture would be the most straightforward way, or am I wrong?
You don't even have to deal with NSBitmap, all you have to do is call saveSnapshotToBuffer, with an NSString.
Did you ever wonder why we had to run for shelter when the promise of a brave new world unfurled beneath the clear blue sky?
Yes, calling that function for each and every frame will drastically hamper your frame rate. It's meant as a snapshot function, not a recording function. If you want to record, then you'd probably do what Steven suggested: save all the data to a buffer, then dump the buffer into images/movie whenever the animation is done (or when memory is full).
If you're running GLUT, just select File/Save As...
Kudos to Smashspeak for finding that oddity out.
-"Sta7ic" Matt
Kudos to Smashspeak for finding that oddity out.
-"Sta7ic" Matt
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Screenshot of OpenGL context | aarku | 6 | 6,328 |
Jul 23, 2004 07:05 PM Last Post: aarku |
|
| Normal Problem - Screenshot available | designdb | 8 | 3,516 |
May 17, 2003 11:31 AM Last Post: designdb |
|

