How to save an OpenGL rendering to disk - jeske/opentk GitHub Wiki
You can use the following code to read back an OpenGL rendering to a System.Drawing.Bitmap. You can then use the Save method to save this to disk.
Hints:
- Don't forget to call Dispose on the returned Bitmap once you are done with it. Otherwise, you will run out of memory rapidly. If you wish to save a video, rather than a single screenshot, consider modifying this method to reuse the same Bitmap.
- Call GrabScreenshot from your main rendering thread, i.e. the thread which contains your GraphicsContext.
- Make sure you have bound the correct framebuffer object before calling GrabScreenshot.
- You can improve performance significantly by removing the bmp.RotateFlip call and saving the resulting image as a BMP rather than a PNG file. This is especially important if you wish to record a video - it is the difference between a real-time recording and a slideshow.
- This code can record 720p/30Hz video relatively easily, given suitable hardware and a little optimization (as outlined above). There are many programs that can encode a stream of consecutive BMP files into a high definition video.
using System;
using System.Drawing;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
static class GraphicsHelpers {
// Returns a System.Drawing.Bitmap with the contents of the current framebuffer
public static Bitmap GrabScreenshot() {
if (GraphicsContext.CurrentContext == null) {
throw new GraphicsContextMissingException;
}
Bitmap bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
System.Drawing.Imaging.BitmapData data =
bmp.LockBits(this.ClientRectangle,
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
GL.ReadPixels(0, 0, this.ClientSize.Width, this.ClientSize.Height,
PixelFormat.Bgr, PixelType.UnsignedByte, data.Scan0);
bmp.UnlockBits(data);
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
return bmp;
}
}