Hi !
Here is some code I use in my application to have OGL rendering into an offscreen bitmap and then copy the result into a dialog box custom button (Preview Button !).
I am sorry but for security reasons, I had to change the code and I haven’t tested the result (no time). I hope it still works…
Post messages for any question regarding the code…
Eric
P.S. : you should start at the function called RenderToDC and follow it (I always code from top to bottom where the most interesting function is at the bottom !).
P.S. 2 : well at least, this code compiles (but didn’t test it !).
//--------------------------------------------------------------------//
#include <stdafx.h>
HGLRC InitializeOpenGL(CDC*& pDC,DWORD PixelFormatFlags);
bool SetupPixelFormat(CDC*& hDC,DWORD PixelFormatFlags);
bool SetupViewingFrustum(int Width,int Height);
void EnterPictureMode(int Width,int Height);
void* SnapPicture(void);
void ExitPictureMode(void);
bool CreateOffScreenDC(CDC*& pDC);
void* CreateOffScreenBitmap(CDC*& pDC,HBITMAP& pBitmap,int Width,int Height);
void RENDER_WHATEVER_YOU_WANT(void);
// You need some variables //
bool m_Perspective;
double m_oLeft,m_oRight;
double m_oBottom,m_oTop;
double m_oNear,m_oFar;
double m_pFOV,m_pAspect;
double m_pZNear,m_pZFar;
CDC *m_pPictureDC;
HGLRC m_hPictureRC;
HBITMAP m_hPictureBitmap;
void *m_PictureDIBits;
int PictureWidth,PictureHeight;
// Give it a pDC and your settings, it gives tou a HGLRC ! //
HGLRC InitializeOpenGL(CDC*& pDC,DWORD PixelFormatFlags)
{
HGLRC hRC;
if (!SetupPixelFormat(pDC,PixelFormatFlags))
{
AfxMessageBox("SetupPixelFormat failed.
");
return 0;
}
if ((hRC=wglCreateContext(pDC->GetSafeHdc()))==0)
{
AfxMessageBox(“wglCreateContext failed.”);
return 0;
}
if (wglMakeCurrent(pDC->GetSafeHdc(),hRC)==FALSE)
{
AfxMessageBox(“wglMakeCurrent failed.”);
return 0;
}
return hRC;
}
// The classic one ! //
bool SetupPixelFormat(CDC*& pDC,DWORD PixelFormatFlags)
{
#define N_Color_Bits 32
#define N_ZBuffer_Bits 24
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),// size of this pfd
1, // version number
PixelFormatFlags,
PFD_TYPE_RGBA, // RGBA type
N_Color_Bits, // Color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
N_ZBuffer_Bits, // Z-Buffer Depth
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelformat;
PIXELFORMATDESCRIPTOR *pPFD=&pfd;
if ((pixelformat=ChoosePixelFormat(pDC->GetSafeHdc(),pPFD))==0)
{
AfxMessageBox(“ChoosePixelFormat failed.”);
return false;
}
if (SetPixelFormat(pDC->GetSafeHdc(),pixelformat,pPFD)==FALSE)
{
AfxMessageBox(“SetPixelFormat failed.”);
return false;
}
return true;
}
// Another Classic ! //
bool SetupViewingFrustum(int Width,int Height)
{
if (m_Perspective)
gluPerspective(m_pFOV,(GLdouble) Width/Height*m_pAspect,m_pZNear,m_pZFar);
else
glOrtho(m_oLeft,m_oRight,m_oBottom,m_oTop,m_oNear,m_oFar);
if (glGetError()!= GL_NO_ERROR)
{
//AfxMessageBox(“Error while trying to set viewing frustum.”);
return false;
}
return true;
}
// Creates an OffScreen DC compatible with current Display //
bool CreateOffScreenDC(CDC*& pDC)
{
pDC=new CDC;
if (pDC->CreateCompatibleDC(NULL)==0) // failure to get DC
{
AfxMessageBox(“Couldn’t get a valid DC.”);
return false;
}
}
// Give it your pDC and Width/Height, it gives you the Bitmap ! //
void* CreateOffScreenBitmap(CDC*& pDC,HBITMAP& pBitmap,int Width,int Height)
{
void *DIBits;
BYTE myBufferInfo[sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)];
BITMAPINFO *myBitmapInfo = (BITMAPINFO *) myBufferInfo;
myBitmapInfo->bmiHeader.biSize = sizeof(myBitmapInfo->bmiHeader);
myBitmapInfo->bmiHeader.biWidth = Width;
myBitmapInfo->bmiHeader.biHeight = Height;
myBitmapInfo->bmiHeader.biPlanes = 1;
myBitmapInfo->bmiHeader.biBitCount = N_Color_Bits;
myBitmapInfo->bmiHeader.biCompression = BI_RGB;
myBitmapInfo->bmiHeader.biSizeImage = WidthHeightN_Color_Bits/8;
pBitmap=CreateDIBSection(pDC->GetSafeHdc(),myBitmapInfo,DIB_RGB_COLORS,&DIBits,NULL,0);
if (pBitmap==NULL)
{
AfxMessageBox(“Couldn’t get a valid Bitmap”);
return 0;
}
pDC->SelectObject(pBitmap);
return(DIBits);
}
// Start the snapshot process ! //
void EnterPictureMode(int Width,int Height)
{
PictureWidth=Width;
PictureHeight=Height;
CreateOffScreenDC(m_pPictureDC);
m_PictureDIBits=CreateOffScreenBitmap(m_pPictureDC,m_hPictureBitmap,PictureWidth,PictureHeight);
m_hPictureRC=InitializeOpenGL(m_pPictureDC,PFD_DRAW_TO_BITMAP|PFD_SUPPORT_OPENGL);
glViewport(0,0,PictureWidth,PictureHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetupViewingFrustum(PictureWidth,PictureHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void* SnapPicture(void)
{
wglMakeCurrent(m_pPictureDC->GetSafeHdc(),m_hPictureRC);
RENDER_WHATEVER_YOU_WANT();
wglMakeCurrent(NULL,NULL);
return(m_PictureDIBits);
}
// Start the snapshot process ! //
void ExitPictureMode(void)
{
wglDeleteContext(m_hPictureRC);
m_pPictureDC->DeleteDC();
delete m_pPictureDC;
DeleteObject(m_hPictureBitmap);
}
void RenderToDC(CDC *pDC,int Width,int Height)
{
void *DIBits;
BYTE myBufferInfo[sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)];
BITMAPINFO *myBitmapInfo = (BITMAPINFO *) myBufferInfo;
EnterPictureMode(Width,Height);
DIBits=SnapPicture();
StretchDIBits(pDC->GetSafeHdc(),0,0,Width,Height,0,0,Width,Height,DIBits,myBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
ExitPictureMode();
}
//--------------------------------------------------------------------//