ObΦas pot°ebujete sejmout obrazovku v OpenGL a potΘ s nφ pracovat jako s obyΦejnou bitmapou. V tomto Φlßnku vßm ukß₧i jak zφskat OpenGL obrazovku a ulo₧it ji do DIBu (v globßlnφ pam∞ti). Vysv∞tlenφ bude ud∞lßno formou komentovanΘho zdrojovΘho k≤du. Jedin² problΘm je, ₧e obrazovka musφ mφt barevnΘ rozliÜenφ 24 bit∙, tj. zφskßme nekomprimovanou bitmapu.
// Funkce, kterß sejmeme OpenGL obrazovku a vytvo°φme z nφ DIB jeho₧ handle vrßtφ
HANDLE COpenGLView::CreateDIB()
{
BeginWaitCursor(); // P°epneme kurzor na p°esφpacφ hodiny
// Zφskßme rozm∞ry okna
CRect rect;
GetClientRect(&rect);
CSize size(rect.Width(),rect.Height());
TRACE(" Klientskß plocha : (%d;%d)\n",size.cx,size.cy);
// ╪ßdky musφ b²t zarovnßvßny na 32 byt∙, za p°edpokladu 24 bit∙ na pixel, tak₧e co je navφc odst°ihneme
size.cx -= size.cx % 4;
TRACE(" KoneΦnß klientskß plocha : (%d;%d)\n",size.cx,size.cy);
// Alokujeme byty pro pixely
// poΦet byt∙ = (byt∙ na pixel, tj. 3 pro 24 bit∙ na pixel) * (Üφ°ka obrßzku) * (v²Üka obrßzku)
int NbBytes = 3 * size.cx * size.cy;
unsigned char *pPixelData = new unsigned char[NbBytes];
// Zkopφrujeme pixely z OpenGL
// Parametry jsou lev² dolnφ roh, Üφ°ka a v²Üka, formßt: GL_RGB = 24 bit∙ na pixel (GL_RGBA = 32 bit∙ na pixel), typ pixelov²ch dat a ukazatel kam data kopφrovat
::glReadPixels(0,0,size.cx,size.cy,GL_RGB,GL_UNSIGNED_BYTE,pPixelData);
// Vyplnφme hlaviΦku DIBu
BITMAPINFOHEADER header;
header.biWidth = size.cx; // Üφrka
header.biHeight = size.cy; // v²Üka
header.biSizeImage = NbBytes; // poΦet byt∙ obrßzku
header.biSize = sizeof(BITMAPINFOHEADER); // velikost tΘto struktury
header.biPlanes = 1; // Hodnota kterß musφ b²t v₧dy jedna
header.biBitCount = 24; // PoΦet bit∙ na pixel
header.biCompression = BI_RGB; // Typ komprese -> nekomprimovanß
header.biXPelsPerMeter = 0;
header.biYPelsPerMeter = 0;
header.biClrUsed = 0;
header.biClrImportant = 0;
// Vygenerujeme handle globßlnφ pam∞ti (DIBu) o velikosti hlaviΦky + poΦtu byt∙
HANDLE handle = (HANDLE)::GlobalAlloc (GHND,sizeof(BITMAPINFOHEADER) + NbBytes);
if(handle != NULL) // Alokace glabßlnφ pam∞ti byla ·sp∞Ünß
{
// Uzamkneme handle
char *pData = (char *) ::GlobalLock((HGLOBAL)handle);
// Zkopφrujeme hlaviΦku a data
memcpy(pData,&header,sizeof(BITMAPINFOHEADER));
memcpy(pData+sizeof(BITMAPINFOHEADER),pPixelData,NbBytes);
// Odemkneme handle
::GlobalUnlock((HGLOBAL)handle);
EndWaitCursor(); // Vrßtφme kurzoru p∙vodnφ stav
return handle;
}
EndWaitCursor();
return NULL;
}
A₧ p°estaneme DIB pou₧φvat musφme jej smazat pomocφ GlobalFree. Jedinou vyjφmkou je, kdy₧ tento dib p°edßme do schrßnky, potom se schrßnka o jeho smazßnφ postarß.
A nakonec ukßzka pou₧itφ tΘto funkce (uvnit° funkcφ t°φdy okna).
HANDLE hDib = CreateDIB();
if (hDib)
{
// Prßce s DIBem
............
............
// U₧ DIB nepot°ebujeme tak ho sma₧eme
::GlobalFree(hDib);
}
Pokud nepot°ebujete zφskat handle DIBu, ale staΦφ vßm mφt jen DC zobrazovanΘ OpenGL scΘny je to velmi jednoduchΘ. Zφskejte DC okna ve kterΘm se OpenGL scΘna vykresluje pomocφ funkce GetDC a je to.