..::Kopφrovßnφ okna OpenGL do DIBu::..

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.