Hlavne menu We are sorry, but magazine AMMO is suspended. Here is just read-only access to the articles archive. Some features are removed because they were outdated, pointless in read-only (voting and pools), or it was missused by spammers (comments) etc. Now the webpages aren't maintained so when something will get broken most probably it won't be fixed at all. If you liked our magazine then please make donation with paypal so we can pay for traffic on this server.

TOP Výuka
01 Maľované krížovky 103 bodov
02 OpenGL, lákadlo 38 bodov
03 MySQL (+ použitie Visual C++ a PHP) 28 bodov
04 Huffmanove kódovanie 19 bodov
05 Pascal, časť 1 18 bodov
06 Ako tlačiť s HP 16 bodov
07 Základy HTML časť 2 16 bodov
08 Základy HTML časť 3 13 bodov
09 Hry pre nenáročných + zdrojáky 10 bodov
10 OpenGL, úvod 8 bodov
11 Faktúrka v4.0 + zdrojáky v MS Visual C++ 6.0 7 bodov
12 OpenGL – Intermezzo 1 7 bodov
13 OpenGL povinná literatúra 6 bodov
14 Základy HTML časť 1 6 bodov
15 WinSocket Communication via VC++ 6 bodov
Najnovsie clanky
Kvalitné služby podľa skúseností iných - TopSlužby.sk
LOTR - Dve veže - Parodia - Scénka 2. časť
Neverwinter nights
Children Of Bodom-Hatebreeder
Kult Duny - 6. časť (Bonus)
Kult Duny - 5. časť (Filmy, Hry)
Dobré ráno. (morc certa, hora incerta...)
Kult Duny - 4. časť (Knihy 2/2)
Stretnutie Spoločenstva Tolkiena
GRAVE DIGGER – Knights Of The Cross
Kult Duny - 3. časť (Knihy 1/2)
Kult Duny - 2. časť (Pojmy)
Kult Duny - 1. časť (Úvod)
LOTR - Dve veže - Parodia - Scénka
Jackass
Vsetky clanky
Airsoft - Specnaz [4 clanky]
Básne [6 clankov]
Fantázia [4 clanky]
Filmy a DVD [51 clankov]
Hardware [10 clankov]
Hry [170 clankov]
Hry, návody [6 clankov]
Hudba [8 clankov]
Internet [7 clankov]
Knihy [6 clankov]
O AMME [4 clanky]
Pandemonium [10 clankov]
Poviedky [14 clankov]
Programy [18 clankov]
Rôzne [8 clankov]
Technické [3 clanky]
Úvahy [8 clankov]
Výuka [50 clankov]
Ako tlačiť s HP
Algoritmy v grafoch
Fake2
Faktúrka
Faktúrka v4.0 + zdrojáky v MS Visual C++ 6.0
Fract
HLSaver
Hry pre nenáročných + zdrojáky
Huffmanove kódovanie
IPicture2 & aggresiveoptimize.h
Maľované krížovky
MySQL (+ použitie Visual C++ a PHP)
OpenGL - GLWnd
OpenGL AMMO Saver
OpenGL povinná literatúra
OpenGL – Intermezzo 1
OpenGL, časť 10
OpenGL, časť 11
OpenGL, časť 12
OpenGL, časť 13
OpenGL, časť 14
OpenGL, časť 15
OpenGL, časť 16
OpenGL, časť 17
OpenGL, časť 18
OpenGL, časť 8
OpenGL, časť 9
Opengl – Cloth Simulation
RenameR
SkinMagic
WinSocket Communication via VC++
Údajové štruktúry
viac...
Zábava [5 clankov]
Zdravie [15 clankov]
Celkovy pocet clankov: 407
OpenGL, časť 1 
Výuka | Dna 2.3.2002 | Johny | 14 znamok, priemer 1.71 | 9007 videni | 219 WAP videni

Vitajte v prvej časti seriálu OpenGL. V tejto časti sa dozviete, ako nejaké OpenGL okno otvoriť a to bude asi tak všetko. Síce neuvidíte žiadne super efekty, ale táto časť je základ, a preto je všetko tu nutné ako soľ. Takže sa pokúste to vydržať. Nie je nevyhnutné, aby ste všetkému, čo je tu napísané rozumeli na 100%. Pokiaľ Vám stačí 1 okno a nezaujíma Vás nič okrem toho, ako niečo do toho okna vykresliť, tak môžete vypnúť mozog a len tak tento text prebehnúť. Pre tých, ktorý sa zaujímajú o programovanie v MSVC++ to budú asi aj známe veci.

Takže našim cieľom bude spraviť OpenGL okno, ktoré bude bežať alebo fullscreen=celá obrazovka, alebo proste len v okne. Tento kód je takmer úplne bez ničoho, teda môže tvoriť základ každej vašej aplikácie. Všetky ďalšie zdrojové súbory budú založené na tomto zdrojáku.

Takže začíname… Prvá vec, ktorú je potrebné urobiť je spraviť si project vo Visual C++. Je to veľmi jednoduchá operácia. Takže, tí z Vás, ktorí Visual C++ v živote nevideli budú asi trošku zmetený všetkými tými okienkami, ktoré vo Visual C++ sú. Najlepšie bude, keď najprv začnete skúšať niečo urobiť vo Visual C++. Alebo si jednoducho otvoríte zdroják z tejto časti a budete sa len tak hrabkať v prostredí Visual C++. Prejdite si všetky položky v MENU, skúste pochodiť v ľavom paneli, v spodnom paneli. Nie je potrebné ovládať všetko, čo Visual C++ ponúka. Stačí, keď na to budete prichádzať postupne, keď budete modifikovať program. Dôležité je, len aby ste vedeli ten váš výtvor skompilovať, spustiť a prípadne aj niečo pomeniť.

Dopredu sa chcem ospravedlniť ak niektoré názvy nepreložím správne, ale poznám ich v anglickom jazyku a slovenské ekvivalenty nemusia byť správne alebo dobre nevystihujú podstatu. V týchto prípadoch radšej nechám názov anglický.

Po vytvorení Win32 aplikácie (nie konzolovej aplikácie) vo Visual C++, budete musieť nastaviť v menu položku pre linkovanie OpenGL knižníc. Takže choďte na Project, Settings, a kliknite na LINK, pod Object/Library Modules je riadok, kde by malo byť napísané kernel32.lib a ešte pár ďalších knižníc *.lib. Na začiatok riadku dopíšte OpenGL32.lib Glu32.lib Glaux.lib. Keď kliknete na OK, už ste pripravený skompilovať nejakú OpenGL aplikáciu. Dôležité je, aby ste vedeli, že toto nastavenie platí len pre Debug mód. To je taký mód, kde má exe súbor aplikácie o pár kb viacej a môžete ho debugovať. Keď Váš program odladíte, tak ho budete chcieť skompilovať ako Release, teda exe už nebude obsahovať všetky prebytočné dáta a bude tam len to, čo tam má byť. Takže nezabudnite potom nastaviť tieto *.lib aj tam. Inak dostanete niečo ako: Unresolved External symbol.... – a váš program sa neskompiluje. Pár ľudí, ktorý majú skúsenosti s OpenGL by mohli namietať, že nie všetky tie knižnice je potrebné tam napísať. Ale my ich tam necháme všetky, nech nemáme s tým už v budúcnosti žiadne starosti. Uvedené knižnice *.lib a tiež hlavičkové súbory *.h by mali byť v adresári, kde ich môže kompilér nájsť.

A môžeme sa pustiť hneď na zdroják.

Nasledujúce 4 riadky začínajúce s #include hovoria programu, že v týchto hlavičkových súboroch sú definované nejaké funkcie, ktoré bude náš program používať.


#include <windows.h> // hlav. Súbor pre Windows
#include <glgl.h> // hlav. Súbor pre OpenGL32 knižnicu
#include <glglu.h> // hlav. Súbor pre GLu32 knižnicu
#include <glglaux.h> // hlav. Súbor pre GLaux knižnicu

Teraz musíme zadeklarovať všetky premenné, ktoré budeme v našom programe používať. Náš program nerobí takmer nič, takže veľa premenných potrebovať nebudeme.

Prvý riadok nastavuje Rendering Context. Každý OpenGL program je pripojený k nejakému Renderovaciemu Contextu. Rendering Context pripája OpenGL volania na Device Context (Context zariadení). (PC REVUE, C++ pod win, 3,4.časť) Rendering Context je deklarovaný ako hRC. Ďalej budeme potrebovať ešte Context zariadení, ktorý je potrebný pre kreslenie našou aplikáciou. Teda Device Context bude hDC. Device Context spája naše okno s GDI (Graphics Device Interface) a RC spája OpenGL s DC.
V tomto odstavci padlo dosť „veľkých“ slov. Stačí ak to budete chápať intuitívne, teda o kreslenie sa stará GDI my tam ideme cez RC->DC. Malé písmeno „h“ značí handle. Takisto si dávajte pozor na malé a veľké písmená. Lebo je rozdiel medzi premennou PP a pp.
Na 3. riadku je hWnd, teda handle na Window. 4. riadok vytvára Instance pre náš program.

HGLRC hRC=NULL; // Rendering Context
HDC hDC=NULL; // GDI Device Context
HWND hWnd=NULL; // Window Handle
HINSTANCE hInstance; // Instance aplikácie

Prvý riadok nižšie deklaruje pole, ktoré použijeme na monitorovanie stlačených klávesov. Je veľa spôsobov, ako sa to dá spraviť a toto je jeden z nich, myslím, že je celkom ľahko porozumiteľný. A umožňuje zachytiť viac ako jeden stlačený kláves v nejakom okamihu.
Premenná active buď sledovať či je nás program aktívne okno alebo či je minimalizované. A keď je minimalizované, môžeme ho pekne uspať a nebude bežať v pozadí, keď je minimalizované.
Premenná fullscreen nám hovorí o tom, či program beží fullscreen alebo v okne. Ak je program na celú obrazovku fullscreen bude TRUE. Ak bude v okne fullscreen bude FALSE. Je dôležité, aby táto premenná bola globálna, aby každá funkcia vedela, akú má hodnotu.


bool keys[256]; // pole použité pre klávesy
bool active=TRUE; // active flag, nastavíme na TRUE
bool fullscreen=TRUE; // fullscreen, dáme na TRUE

Teraz musíme definovať WndProc. Dôvod prečo to musíme urobiť je, že CreateGLWindow() má odkaz na WndProc(), ale WndProc() ide po CreateGLWindow(). V C chceme mať prístup k nejakej časti kódu, tak ten kód alebo funkcia musí byť definovaná niekde nad tým. Takže zadefinujeme WndProc().


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // deklarácia WndProc

Úlohou nasledujúcej časti kódu je meniť veľkosť OpenGL scény, keď sa zmenia rozmery okna. Ak program bude bežať ako fullscreen, tak túto funkciu využijeme, aby sme nastavili perspektívu pre našu OpenGL scénu. Tá sa nastaví podľa parametrov width a height, čo sú rozmery okna v ktorom sa zobrazuje.


GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
// zmena veľkosti a inicializácia GL Window
{
if (height==0) // nulou deliť nechceme
{
height=1; // nastavíme na 1
}

glViewport(0, 0, width, height); // nastavíme viewport (viditeľná časť)


Nasledujúcich pár riadkov nastavuje perspektívne videnie, tak aby všetko na scéne vyzeralo realisticky. Perspektíva sa počíta s FOV=45. FOV-field of view, teda zorné pole, je vyjadrené v stupňoch. 0.1f je začínajúci a 100.0f je koncový bod na scéne. Predstavte si 3D priestor. Vy sa na začiatku vždy nachádzate na 0,0,0. Tieto rozmery nám určujú, ako hlboko, môžeme kresliť na scénu.


glMatrixMode(GL_PROJECTION) určuje, že nasledujúce 2 riadky kódu budú pracovať s projection matrix. Perspective matrix je spoľahlivý pri pridávaní perspektívy do našej scény.
Projection matrix – akási šablóna, nastavenia… matrix znamená matica… Ak máte znalosti z algeri, tak viete, že pri prepočte rôznych typov súradníc, napríklad z karteziánskeho do iného, napríklad cylindrického súradnicového systému je možné urobiť to pomocou prechodovej matice. Mohli ste sa s ňou stretnú napríklad, ak ste programovali vlastné rotácie v 3D priestore, napríklad v Pascale ste spravili nejakú 3D kocku.

glLoadIdentity() sa dá popísať ako reset. Obnoví zvolený matrix do jeho základného stavu. Po volaní glLoadIdentity() nastavíme perspektívu pre našu scénu. Predstavte si, že kreslíte niečo perom. A kreslíte nejakú čiaru. A nemusíte skončiť vždy v tom bode, kde sa začínali, teda 0,0,0 a chcete sa tam dostať, ale neviete svoju aktuálnu pozíciu, takže sa nemôžte posunúť, lebo neviete ktorým smerom. A práve táto funkcia Vás tam nastaví.

glMatrixMode(GL_MODELVIEW) značí, že každá nová transformácia ovplyvní modelview matrix. To je matica, kde sú uložené informácie o našom objekte. A nakoniec ho resetneme. Neznepokojte sa, ak ste to nerozumeli, určite sa s tým stretnete v ďalších častiach seriálu, kde budú aj znova popísané.

glMatrixMode(GL_PROJECTION); // vyber Projection Matrix
glLoadIdentity(); // resetni Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW); // vyber Modelview Matrix
glLoadIdentity(); // resetni Modelview Matrix
}


V ďalšej časti kódu, urobíme všetko, čo je potrebné pre nejaké počiatočne nastavenie OpenGL. Zvolíme farbu, ktorou chceme vyčistiť obrazovku, zapneme depth buffer a tiež smooth shading, atd. Táto rutina=funkcia nebude zavolaná kým nebude vytvorené OpenGL okno. Táto funkcia síce vracia nejakú hodnotu, ale pretože náš program nebude taký zložitý, nebude sa tým trápiť.


int InitGL(GLvoid) // celý setup OpenGL ide sem
{

Nasledujúci riadok zapína smooth shading. Smooth shading spriesvitňuje farby krížom cez polygón, a tiež smoothuje svetlo. Smooth shading bude ešte popísané v inej časti.


glShadeModel(GL_SMOOTH); // zapneme Smooth Shading

Nasledujúci riadok nastavuje farbu, na akú chceme vyčistiť obrazovku. Ak neviete ako farby fungujú, tak to rýchlo vysvetlím. Hodnoty farby sú 0.0f až 1.0f. Asi ste si všimli, že za hodnotami sa niekedy vyskytne „f“. Týmto chceme povedať, že ide o hodnotu typu float. Kompilér síce vie urobiť konverziu na float, on si myslí, že je to double, a napíše to ako warning. 0.0f je najtmavšia farba, 1.0f je najsvetlejšia. A parametre sú R,G,B. Red, Green, Blue. Teda my si tú farbu vlastne namiešame z týchto troch farieb. Posledný údaj je aplha, ale pri čistení obrazovky nás zatiaľ tento parameter nemusí trápiť.
Mixovaním rôznych hodnôt týchto základných farieb si môžeme namiešať, farbu akú len chceme.

glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // čierne pozadie

Ďalšie 3 riadky pracujú s Depth Bufferom. V tomto bufferi sa ukladá, ako „hlboko“ sú objekty v priestore, aby predmety, ktoré sú úplne vzadu boli vykreslené, ako prvé, a ako posledné tie najbližšie ku 0,0,0. Nemusíme síce v našom programe nič také používať, ale keďže tento zdroják bude tvoriť základný kameň všetkých ostatných príkladov, tak to sem dáme a v budúcnosti už budeme mať všetko pripravené. Depth buffer triedi objekty podľa hĺbky, je to dôležitá časť OpenGL. Niektorí ľudia hovoria, že to nie je príliš rýchle, ale pre naše potreby to bude určite stačiť, ak si chcete naprogramovať vlastnú triediacu funkciu, tak vám odporúčam použiť techniku BSP, čo je Binary Space Partition. Je to o binárnych stromov, táto technika bola použitá už v starom DOOMe. A používa sa aj dnes.


glClearDepth(1.0f); // depth buffer setup
glEnable(GL_DEPTH_TEST); // zapneme depth testovanie
glDepthFunc(GL_LEQUAL); // typ depth funkcie

Ďalej povieme OpenGL, že chceme tú najlepšiu korekciu perspektívy, akú nám môže poskytnúť. Síce uberáme kúsok na rýchlosti, ale vyzerá to kúsok lepšie.


glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

Nakoniec vrátime TRUE. Ak chceme kontrolovať, či inicializácia prebehla v poriadku, môžeme nižšie kontrolovať túto návratovú hodnotu. Ale to Vás teraz trápiť nemusí.


return TRUE; // všetko išlo OK
}

Táto časť kódu je tá časť, kde napíšeme, čo chceme nakresliť. Všetko, čo plánujete vykresliť na obrazovku ide práve sem. Všetko, čo budete chcieť kresliť pôjde sem nižšie. Nakoniec vrátime TRUE. Teraz len vyčistíme obrazovku farbou, akú sme pred tým zvolili. Vyčistíme depth buffer a resetneme scénu. A nič viac nakresliť nechceme, zatiaľ.
Návratová hodnota hovorí, že všetko prebehlo bez problémov. Ak chcete nejakým spôsobom zisťovať, či to prebehlo v poriadku.


int DrawGLScene(GLvoid) // sem príde, čo sa bude kresliť
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // vyčistí obrazovku a depth buffer
glLoadIdentity(); // resetneme Modelview Matrix
return TRUE; // všetko prebehlo OK
}

Ďalej definujeme funkciu, ktorá zavrie OpenGL okno a program skončí. Úlohou KillGLWindow() je uvoľniť Rendering Context, Device Context a nakoniec handle na window. Ako vidíte je pridaná rôzna kontrola chýb. Ak program nemôže zničiť nejakú časť okna, vypíše okienko so správou. Takto ľahšie nájdete chyby v programe.

GLvoid KillGLWindow(GLvoid) // zničí OpenGL okno
{

Najprv zistíme, či sme fullscreen. Ak sme prepneme sa najprv na desktop. Najprv vypneme fullscreen, aby sa nám neporušil desktop.

if (fullscreen) // fullscreen ?
{

Použijeme ChangeDisplaySettings(NULL,0), aby sme sa navrátili k originálnemu desktopu. Nastavenie NULL ako prvého parametru a 0 ako druhého prinútime windows použiť hodnoty uložené vo windows registry, rozlíšenie, hĺbka farieb, frekvencia, atd. A znovu zapneme kurzor.

ChangeDisplaySettings(NULL,0); // späť na Desktop
ShowCursor(TRUE); // ukáž kurzor
}


Ďalej skontrolujeme či máme Rendering Context (hRC). Ak nie, program skočí nižšie a skontroluje či máme Device Context.


if (hRC) // máme Rendering Context?
{

Ak ho máme, tak skontrolujeme, či ho môžeme uvoľniť (detach the hRC from the hDC). Stále kontrolujeme či nedošlo k nejakej chybe. Skúšame uvoľniť s glMakeCurrent(NULL,NULL), a skontrolujeme či sa podarilo.

if (!wglMakeCurrent(NULL,NULL))
// môžeme uvoľniť DC a RC Contexty?
{

Ak sa to nepodarí, tak vyskočí okienko MessageBox() s chybovým hlásením. NULL znamená, že message box nemá, nepatrí žiadnemu oknu. Ďalej je tam správa a titulok okna. A nakoniec typ okna, MB_OK znamená, že tam bude jedno tlačítko OK.

MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}

Teraz skúsime uvoľniť Rendering Context. Ak sa nepodarí, znova vypíšeme chybové hlásenie.

if (!wglDeleteContext(hRC)) // môžeme uvoľniť RC?
{

Ak nemôžme uvoľniť Rendering Context znova sa vypíše chybné hlásenie.

MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}

Ďalej skontrolujeme či máme Device Context a ak hej, skúsime ho uvoľniť. Ak sa nepodarí, vypíše chybové hlásenie.

if (hDC && !ReleaseDC(hWnd,hDC)) // môžeme uvoľniť DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // nastav DC na NULL
}

Skontrolujeme, či je Window Handle a ak je, skúsime ho zničiť pomocou DestroyWindow(hWnd). Ak sa to nepodarí, vypíše sa príslušné chybové hlásenie a hWnd sa nastaví na NULL.

if (hWnd && !DestroyWindow(hWnd)) // môžeme zničiť Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // nastav hWnd na NULL
}

Posledná vec je odregistrovanie Windows Class. To nám umožní korektne „zabiť“ naše okno.

if (!UnregisterClass("OpenGL",hInstance)) // môžeme unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}

Nasledujúca časť kódu, ktorá vytvorí naše OpenGL okno. Ako vidíte funkcia vracia BOOL a má 5 parametrov: titulok okna, šírka, výška, bits (16/24/32) a či bude fullscreen. A vrátim či sa okno podarilo otvoriť v poriadku.


BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{

Spýtame sa windowsu, nech nám nájde vhodný pixel format aký chceme. A uloží to do PixelFormat.


GLuint PixelFormat; // výsledky hľadania

Wc je štruktúra Window Class. Sú v nej obsiahnuté informácie o našom okne. Zmenou rôznych parametrov môžeme meniť vzhľad a vlastnosti okna.


WNDCLASS wc; // štruktúra Windows Class

dwExStyle a dwStyle uchovávajú normálne a rozšírené informácie.

DWORD dwExStyle; // štýl okna (rozšírené)
DWORD dwStyle; // štýl okna


Nasledujúcich 5 riadkov uchovajú horný ľavý a pravý dolný roh. Normálne nastavíme okno na 640x480, okraje okna.


RECT WindowRect; // obdĺžnik
WindowRect.left=(long)0; // ľavá hodnota na 0
WindowRect.right=(long)width; // pravú na Width
WindowRect.top=(long)0; // top na 0
WindowRect.bottom=(long)height; // Bottom na Height

V ďalšej časti nastavíme fullscreen podľa fullscreen flag.

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

V ďalšej časti, získame instance nášho okna a potom definujeme Window Class.

CS_HREDRAW, CS_VREDRAW prekreslí okno, keď zmeníme rozmery.
CS_OWNDC vytvorí private DC pre naše okno. DC nie je zdieľaný cez aplikácie. WndProc hliadkuje správy v našom programe. Nastavíme Ikonu, ak nechceme žiadnu dáme NULL. A tiež nepoužívame Menu, akže NULL.


hInstance = GetModuleHandle(NULL);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // prekresli pri pohybe a zmene veľkosti
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0; // žiadne extra dáta
wc.cbWndExtra = 0; // žiadne extra dáta
wc.hInstance = hInstance; // nastavíme Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
// nahráme ikonu
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
// nahráme kurzor myši
wc.hbrBackground = NULL; // žiadne pozadie
wc.lpszMenuName = NULL; // nemáme Menu
wc.lpszClassName = "OpenGL"; // nastavíme meno Class

Zaregistrujeme Class. Ak niečo neprebehlo v poriadku, uvidíme chybové hlásenie.

if (!RegisterClass(&wc)) // pokús sa zaregistrovať Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; }

Skontrolujeme či sme na fullscreen

if (fullscreen)
{

DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
// pamäť musí byť čistá
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
// veľkosť DmScreenSettings
dmScreenSettings.dmPelsWidth = width;
// šírka
dmScreenSettings.dmPelsHeight = height;
// výška
dmScreenSettings.dmBitsPerPel = bits;
// bits per pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;


Pokús sa zmeniť mód a získaj výsledky.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{

Ak sa zvolený mód nedá nastaviť, spustí sa kód nižšie.

if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By
Your Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{

Ak chceme window fullscreen bude FALSE


fullscreen=FALSE;
(Fullscreen=FALSE)
}
else
{




MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; }
}
}

Ešte raz skontrolujeme fullscreen, pred tým, ako nastavíme typ okna.

if (fullscreen) // sme Fullscreen
{

Ak sme stále vo fullscreen, nastavíme extended style na WS_EX_APPWINDOW. Pre window style vytvoríme WS_POPUP. Tento typ okna nemá žiadny okraj a je perfektné pre fullscreen mód. Nakoniec vypneme kurzor myši.


dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // skry myš
}
else
{


WS_OVERLAPPEDWINDOW vytvorí okno so šírkou, záhlavím, možnosťou zmeny veľkosti a tlačítkami minimize/maximize.


dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}

Riadok nižšie nastaví parametre pre naše okno.

AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

V ďalšej časti vytvoríme okno a skontrolujeme či sa vytvorilo OK.

if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style pre Window
"OpenGL", // Class Name
title, // titulok okna WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
dwStyle, 0, 0, // pozícia okna WindowRect.right-WindowRect.left,
WindowRect.bottom-WindowRect.top,
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL)))

A teraz skontrolujeme, či sa vytvorilo správne.


{
KillGLWindow(); // Reset Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}


Ďalšia časť opisuje Pixel Format. My zvolíme taký, ktorý podporuje double buffering. A pokúsime sa nájsť taký, aby zodpovedal našim požiadavkám na bps. A nakoniec nastavíme 16 bit Z-Buffer.


static PIXELFORMATDESCRIPTOR pfd=
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
// podpora okna
PFD_SUPPORT_OPENGL |
// podpora OpenGL
PFD_DOUBLEBUFFER,
// podpora double buffer
PFD_TYPE_RGBA,
// rgba format
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, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Rezervované
0, 0, 0 // Layer Masks Ignored
};

Ak sa nevyskytla nijaká chyba pokúsime sa získať OpenGL Device Context. Inak vypíšeme chybu a skočíme.

if (!(hDC=GetDC(hWnd))) // získali sme Device Context?
{
KillGLWindow(); // Reset Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}


if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
// našiel windows Pixel Format?
{
KillGLWindow();
// Reset Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}

Ak windows našiel zodpovedajúci Pixel format, pokúsime sa ho zaviesť.

if(!SetPixelFormat(hDC,PixelFormat,&pfd))
// môžeme ho nastaviť ?
{
KillGLWindow(); // Reset Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}

if (!(hRC=wglCreateContext(hDC)))
// môžeme získať Rendering Context?
{
KillGLWindow(); // Reset Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}



if(!wglMakeCurrent(hDC,hRC)) // skús aktivovať Rendering Context
{
KillGLWindow(); // Reset Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}


Ak išlo všetko OK, tak máme vytvorené okno.


ShowWindow(hWnd,SW_SHOW); // ukáž okno Window
SetForegroundWindow(hWnd);
SetFocus(hWnd); // Keyboard Focus na naše okno
ReSizeGLScene(width, height); // nastav perspektívu

Nakoniec skočíme na InitGL, kde nastavíme svetlá, textúry, a všetko ostatné, čo je treba. Samozrejme môžete testovať či to prebehlo OK a podľa toho sa zariadiť.


if (!InitGL())
{
KillGLWindow(); // Reset Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // vráť FALSE
}



return TRUE;
}


Ďalej sa budeme venovať, ako spracovať správy, ktoré prichádzajú k nášmu oknu.


LRESULT CALLBACK WndProc( HWND hWnd,
// Handle na Window
UINT uMsg,
// správa pre náš Window
WPARAM wParam,
// parametre
LPARAM lParam)
// parametre
{


Podľa typu správy sa rozhodneme, čo bude nasledovať.
switch (uMsg) {


case WM_ACTIVATE: // správa Activate
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program je Aktívny
}
else
{
active=FALSE; //program je neaktívny
}

return 0;
}


Ak je parameter WM_SYSCOMMAND (system command) porovnáme wParam, či náhodou nechce začať screensaver alebo vypnutie monitoru.

case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_SCREENSAVE: // chce začať screensaver?
case SC_MONITORPOWER: //vypnutie monitoru?
return 0;
}
break;
}

case WM_CLOSE: // zatvárame?
{
PostQuitMessage(0); // pošli Quit Message
return 0; // skoč späť
}

case WM_KEYDOWN: // bol stlačený kláves
{
keys[wParam] = TRUE; // ak hej, zaznač to
return 0;
}

case WM_KEYUP: // bol pustený?
{
keys[wParam] = FALSE; // zaznač ako FALSE
return 0; //
}

case WM_SIZE: // pri zmene OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam));
// LoWord=šírka, HiWord=výška
return 0;
}
}





// ostatné správy do DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

Hlavná funkcia WinMain.

int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // parametre
int nCmdShow)
{
MSG msg; // štruktúra message
BOOL done=FALSE;



// chce užívateľ fullscreen ?
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // chce Window
}

// vytvor OpenGL Window
if (!CreateGLWindow("OpenGL Framework",640,480,16,fullscreen))
{
return 0;
}

while(!done) // kým je done==FALSE
{

if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
// nejaká správa?
{

if (msg.message==WM_QUIT)
// treba končiť ?
{
done=TRUE;
}
else
{
TranslateMessage(&msg); DispatchMessage(&msg);
}
}
else // žiadne správy
{

// nakresli OpenGL scénu a pozri či nie je stlačený Esc.
if (active) // aktívne
{
if (keys[VK_ESCAPE]) // stlačený ESC ?
{
done=TRUE;
}
else // nekončíme, Updatni obrazovku
{


Ak sme aktívny a ESC nie je môžeme kresliť.


DrawGLScene(); // kresli Scénu
SwapBuffers(hDC); // (Double Buffering)
}
}

F1 – môžeme sa prepnúť z fullscreen do okna a naopak

if (keys[VK_F1]) // F1 stlačené
{
keys[VK_F1]=FALSE;
KillGLWindow(); // Kill Window
fullscreen=!fullscreen;
if (!CreateGLWindow("OpenGL Framework",640,480,16,fullscreen))
{
return 0;
}
}
}
}





// Shutdown
KillGLWindow(); // Kill Window
return (msg.wParam); // Exit Program
}


To je z dnešnej časti asi všetko. Ja viem, že sa toho zdá veľmi veľa, ale žiadny strach, pri programovaní sa 90% a možno aj viac z toho zdrojáku vôbec nezmení. Takže nie je nutné aby ste tomu rozumeli do veľmi hlbokej úrovne, ale aby ste mali aspoň nejaký ten šajn.

Môžete si stiahnuť komplet zdroják s týmto príkladom, ktorý otvorí OpenGL okno.
Už v ďalších častiach uvidíte, že budeme modifikovať skôr procedúru, ktorá kreslí do okna a na všetky inicializácie a nastavenia sa nebudete až tak musieť sústrediť. Ak sa o to zaujímate podrobnejšie, skúste si prečítať články v PC REVUE, ktoré sa venujú práve týmto častiam MSVC++.
MSVC++ http://www.softsklad.host.sk/opengl/lesson01.zip
BC++ http://www.softsklad.host.sk/opengl/lesson01-bc.zip
Delphi http://www.softsklad.host.sk/opengl/lesson01-delphi.zip



Podobne clanky