class CAlphaBlendDlg : public CDialogEx
{
...
HGLRC m_hBitmapRC;
HPBUFFERARB m_hBitmapPbuffer;
HDC m_hBitmapPbufferDC;
...
};
BOOL CAlphaBlendDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
CClientDC dc (this);
CRect clientRect;
GetClientRect(clientRect);
// create an off-screen buffer for bitmap rendering
int numMultiSamples = 2;
const int attributes[] =
{
// need OpenGL supported
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
// enable render to pbuffer
WGL_DRAW_TO_PBUFFER_ARB, GL_TRUE,
// at least 24 bits for depth
WGL_DEPTH_BITS_ARB, 24,
// need RGBA colors
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
// at least 24 bits for color
WGL_COLOR_BITS_ARB, 24,
// need alpha channel for transparent background
WGL_ALPHA_BITS_ARB, 8,
// we don't need double buffering
WGL_DOUBLE_BUFFER_ARB, GL_FALSE,
// enable FSAA
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
WGL_SAMPLES_ARB, numMultiSamples,
// end with a NULL terminator
NULL
};
int newPixelFormat = 0;
UINT numFormats = 0;
bool usePixelFormat = false;
wglChoosePixelFormat (dc.m_hDC, attributes, NULL, 1, &newPixelFormat, &numFormats);
// try to use OpenGL pbuffers to render to an off-screen buffer
m_hBitmapPbuffer = wglCreatePbuffer (dc.m_hDC, newPixelFormat, clientRect.Width(), clientRect.Height(), NULL);
m_hBitmapPbufferDC = wglGetPbufferDC (m_hBitmapPbuffer);
/* No need to set the pixel format because the pbuffer is already
created with the pixel format specified. */
m_hBitmapRC = ::wglCreateContext (m_hBitmapPbufferDC);
}
void CAlphaBlendDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect clientRect;
GetClientRect (clientRect);
CDC *pBitmapDC = new CDC();
pBitmapDC->CreateCompatibleDC (&dc);
BITMAPINFO bitMapInfo;
memset (&bitMapInfo, 0, sizeof(bitMapInfo));
bitMapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitMapInfo.bmiHeader.biWidth = clientRect.right;
bitMapInfo.bmiHeader.biHeight = clientRect.bottom;
bitMapInfo.bmiHeader.biPlanes = 1;
bitMapInfo.bmiHeader.biBitCount = 32;
bitMapInfo.bmiHeader.biCompression = BI_RGB;
void *pBitmapBits = NULL;
HBITMAP hBitmapDIB = ::CreateDIBSection (pBitmapDC->m_hDC, &bitMapInfo, DIB_RGB_COLORS, &pBitmapBits, NULL, 0);
pBitmapDC->SelectObject (hBitmapDIB);
VERIFY(wglMakeCurrent (m_hBitmapPbufferDC, m_hBitmapRC) != FALSE);
// set up orthogonal projection so we can specify window coordinates for vertices
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D (0, clientRect.right, clientRect.bottom, 0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
glViewport (0, 0, clientRect.Width(), clientRect.Height());
glDisable(GL_DEPTH_TEST);
glDrawBuffer (GL_FRONT);
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT);
// draw a bunch of filled white triangles
glColor4ub (255,255,255,255);
static const int numTriangles = 100;
static const double triangleSizeFactor = 0.1;
const int triangleSize = (int) (clientRect.Width() * triangleSizeFactor);
glBegin(GL_TRIANGLES);
for (int index = 0; index < numTriangles; index++)
{
int x = rand() % (clientRect.Width() - triangleSize) + triangleSize / 2;
int y = rand() % (clientRect.Height() - triangleSize) + triangleSize / 2;
for (int vertexIndex = 0; vertexIndex < 3; vertexIndex++)
{
int vx = x + (rand() % triangleSize) - triangleSize / 2;
int vy = y + (rand() % triangleSize) - triangleSize / 2;
glVertex3i (vx,vy,0);
}
}
glEnd();
// read the pixels
glReadBuffer(GL_FRONT);
glReadPixels (0, 0, clientRect.Width(), clientRect.Height(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, pBitmapBits);
VERIFY(wglMakeCurrent (NULL, NULL) != FALSE);
// use pBitmapBits to draw onto DC using AlphaBlend
// ...
// cleanup
delete pBitmapDC;
pBitmapDC = NULL;
::DeleteObject (hBitmapDIB);
hBitmapDIB = NULL;
}