Today, I was working on a project where I wanted to do some OpenGL
rendering to an offscreen buffer and save it as a bitmap. I googled
around a bit for information on creating an offscreen rendering context
(in Windows). The usual way to do it, according to the Internet (see for
example this GameDev
seems to be to create an offscreen device context with
CreateCompatibleDC, and use a PFD_DRAW_TO_BITMAP pixel format.
However, when I tried this I found that the GL context thus created is
not hardware accelerated, but falls back to Windows’ built-in GL 1.1
The other obvious way to do it is create a hidden window and set up GL
normally, with PFD_DRAW_TO_WINDOW. This gets hardware accelerated and
works (you can draw and retrieve the image without ever showing the
window on-screen). It seems a bit extravagant though. Both methods
“should” work equally well since it just comes down to drawing to a
memory area that doesn’t happen to be on-screen.
I’m curious about other peoples’ experience here - if you’ve built a
program that uses offscreen rendering, have you encountered similar
issues? Are there configurations out there for which offscreen-DC does
work, or hidden-window doesn’t? Is there a different way of setting up
the offscreen DC to make this work?
Please log in or register to post a reply.
What about a framebuffer object (EXT_framebuffer_object), which can
render to an offscreen framebuffer? Since it’s
windowing-system-agnostic, you wouldn’t need any window-specific
information and it should be accelerated by the hardware if it’s
supported. You can then use glReadPixels or glCopyTexImage2D to read
back the contents of the render buffer. Seems like this should work in
your case, unless I misunderstood what you’re trying to do.
has good information about them.
You anyway need valid OpenGL context to create and use framebuffer
Like what Dia said, I too would recommend just using a render to texture
option and then you can pull / save the bitmap data however you like.
It’s pretty fast too, since I’ve recorded video feeds in real-time using
it (if you’re worried about glCopyTeximage being slow). Its my preferred
choice over off-screen rendering / p-buffers, which also runs into
numerous portability issues.
I’m aware of framebuffer objects, but those don’t solve my problem -
like martinsm says, you need to have an OpenGL context already to use
them. My question is about how you get the OpenGL context in the first
place. If you are writing an interactive app or game and already have a
context for your main window, great, but I’m writing a console app to do
some offline processing and am not showing anything on the screen, so I
don’t have a main window.
Update: I found that while the hidden-window method works in Vista, it
does not seem to work in XP - with the window hidden, attempting to read
back the framebuffer just grabs whatever is on-screen at the window’s
I can probably still use a framebuffer object together with the hidden
window to get hardware offscreen rendering. It’s even more rigmarole,
I usually use hidden window + FBO approach for some GPGPU stuff I do.
Now of course I wait for OpenCL :)
Yep, a hidden window is the only way to go. Here’s some code, which
works fine in XP. Resolutions are of course limited to your desktop, but
you can add a quick FBO in there and you’re well off into the races.
LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
return DefWindowProc(hWnd, Message, wParam, lParam);
int main (int argc, char **argv)
// Window properties
int width = 640;
int height = 480;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = 0;
wndClass.hIcon = 0;
wndClass.hCursor = LoadCursor(0, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = 0;
wndClass.lpszClassName = "WndClass";
wndClass.hIconSm = 0;
// Style the window and remove the caption bar (WS_POPUP)
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP;
// Create the window. Position and size it.
HWND wnd = CreateWindowEx(0,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
0, 0, 0, 0);
HDC dc = GetDC(wnd);
// Setup OpenGL
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 16;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
int pixelFormat = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, pixelFormat, &pfd);
HGLRC rc = wglCreateContext(dc);
// Initialize your OpenGL properties and states here.
// Do a loop or call display() once, whatever rocks your boat
while ( true )
// Save yer image here.
Thanks. BTW, you can actually specify DefWindowProc directly as the
window procedure, with no need for the passthrough routine. :)
I just ripped parts and pieces from my engine so I didn’t bother
cleaning it up much ;)
I’m slightly confused with the idea of rendering openGL to an off-screen
I am trying to generate a skin using openGL that will be used as a
source bitmap by UpdateLayeredWindow. It takes a source HDC as an input.
I used the code you provided above, and it works fine, but only if I
leave the new openGL window visible (SW_SHOW). If I hide the new openGL
window the hdc doesnt seem to contain the image I generated, and
updateLayeredWindow is not what I expect.
Am I missing something?