játékfejlesztés.hu
FórumGarázsprojectekCikkekSegédletekJf.hu versenyekKapcsolatokEgyebek
Legaktívabb fórumozók:
Asylum:    5448
FZoli:    4892
Kuz:    4455
gaborlabor:    4449
kicsy:    4304
TPG:    3402
monostoria:    3284
DMG:    3172
HomeGnome:    2919
Matzi:    2520

Pretender:    2498
szeki:    2440
Seeting:    2306
Geri:    2188
Orphy:    1893
Joga:    1791
Bacce:    1783
MaNiAc:    1735
ddbwo:    1625
syam:    1491
OpenGL + WinAPI 2. 2008.04.17 08:31


Legutóbb megtanultunk lérehozni egy egyszerű, üres Windows ablakot programunkban, de a lényeg, az OpenGL még kimaradt. Sajnos, hasonlóan az ablak létrehozásához, ezt sem ússzuk meg egy-két sorral, cserébe viszont ezzel is egy csomó olyan dolog felett lesz uralmunk, amiről nem is hallottunk GLUT használatával.
A mostani OpenGL inicializálásával foglalkozó kód az előző ablakozóra épül.
Az már tudjuk, hogy OpenGL-hez be kell hívnunk egy header fájlt:

Kód:
#include <glgl.h>


s mivel külső függvényket hívogatunk (az OpenGL függvényekre gondolok), ezért valami módon csatolnunk is kell a projecthez az “opengl32.lib” fájlt is. Visual C++ környzet alatt ezt a legegyszerűbben a :

Kód:
#pragma comment(lib, "opengl32")


utasítással követhetjül el. Nem gondolom, hogy ez máshol is gondot jelentene. :)

Hogy könnyítsük a dolgunkat, és az átláthatóságot is növeljük, ezért az OpenGL init-et végző kódot külön függvénybe tesszük, legyen a neve mondjuk:

Kód:
bool InitOpenGL()


s törlést pedig:

Kód:
void ClearOpenGL()


Mint az ablak létrehozásánál, itt is kell pár új változó, melyek segíteni fogják munkánkat:

Kód:
HDC hDC = NULL;
HGLRC hRC = NULL;


A HDC típusú változó nem konkrétan az OpenGL-hez tartozik, annál inkább az ablakunkhoz. A DC Windows-os környzetben (máshol is?) device context-et jelent. Igazából nem annyira lényeges dolog, hogy meg kellene ismerni az egész múltját/jelenét/jövőjét, elég azt tudni róla, hogy ez is egy azonosító, mégpedig abból a fajtából, ami a rajzoláshoz kapcsolódik.
A hRC már annál inkább OpenGL-es, ez szintén azonosító (de sok azonosító van), ez fogja nekünk nyilvántartani a renderelési környzetünket (render context).

Legelső lépésben meg kellene tudakolnunk valahonnan, hogy hogyan tudunk majd az ablakra rajzolni is. Itt jön képbe az a bizonyos hDC, valamint egy új függvény:

Kód:
hDC = GetDC(hWnd);


Mint látjuk csak egy paramétert vár, ez pedig az ablakunk azonosítója. Fontos, hogy valós azonosító legyen, mert érvénytelennel gyorsan megszakad a játék.
Ha minden jól megy, akkor már van egy valós felületünk (maga az ablak, ugye) ahova már tudnánk rajzolni. Ehhez előbb érvényesíteni kell az OpenGL render környzetet.
Első lépésben egy struktúrát kell kitöltenünk, mely leírja a kívánt pixel formátumot:

Kód:
PIXELFORMATDESCRIPTOR pfd;


Első ránézésre iszonyat sok tagja van, de szerencsénk van, nem fontos mindet kitöltenünk. Nézzük azokat, melyeket mégis kell:

Kód:
ZeroMemory(&pfd, sizeof(pfd));

pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;


nSize - a struktúra méretét tárolja
nVersion – értéke mindig 1
dwFlags – pár pixel pufferre vonatkozó beállítás tárol, a nevek elég beszédesek, nem szorulnak semmiféle magyarázatra
iPixelType – egy pixel alakját határozzuk meg, R,G,B és egy A(lpha) komponens
cColotBits – a színpuffer mélysége, 32 bit jelen esetben
cDepthBits – a mélységpuffer mérete, 24 bit

Most van egy pixel puffer leíró struktúránk, viszont jó lenne kideríteni, hogy működőképes-e a mi ablakunkkal.
ChoosePixelFormat néven erre is biztosítva van egy függvény, mely egy egész típusú, a kérthez legközelebb eső pixel formátum indexét adja vissza.

Kód:
int pixelFormat;
pixelFormat = ChoosePixelFormat(hDC, &pfd);


Ha a ChoosePixelFormat által visszaadott érték nem nulla, akkor helyben vagyunk haladhatunk tovább, ellenkező esetben lehetetlent kérünk. :)
A helyzetünk, hogy van egy használható pixel formátumunk, alkalmazzuk hát:

Kód:
SetPixelFormat(hDC, pixelFormat, &pfd);


Szerintem nem sokat kell magyarázni a paraméterlistán: hDC az ablakunk DC-je, pixelFormat az imént visszakapott index, pfd pedig a mi listánk a pixel pufferre vonatkozóan. Visszatérési értéke pedig: true ha a pixel formátumot sikerült beüzemelni, false ha hiba keletkezett valahol.

Ezután már csak pár apróbb függvényhívás választ el a céltól.
Amink még nincs, az maga az OpenGL környezet melybe rajzolunk. Létrehozása az eddigiekhez képest már csukott szemmel is elvégezhető:

Kód:
hRC = wglCreateContext(hDC);


A CreateContext már magától adja a megoldást, maga a környezet létrehozása. Ha valami hiba történt, akkor NULL értékkel tér vissza, ellenkezős esetben pedig egy valós azonosítóval a környzetünkre. Ezek után már csak meg kell mondanunk, hogy ezt a környezetet szeretnénk használni, mégpedig mostantól:

Kód:
wglMakeCurrent(hDC, hRC);


Létrehozni létre tudunk már egy teljesen működő OpenGL rajzolási felületet, de mielőtt a program befejeződik, ezt törölni is illik. Ezt meglepően kevés kóddal el is érhetjük:

Kód:
wglMakeCurrent (NULL, NULL);
wglDeleteContext (hRC);
ReleaseDC (hWnd, hDC);


Első lépést úgy is értelmezhetjük, hogy az init-nél beállított környezetet most inaktiváljuk, így az alapkörnyezet lép érvénybe.
Ha már nem aktív, akkor nyugodtan törölhetjük is az OpenGL felületet (wglDeleteContext). Mostmár semmi közünk az OpenGL-hez, de még van egy érvényes DC-nk, ezt is töröljük: ReleaseDC(…).

Ezek után már csak annyi a dolgunk, hogy a programunk fő ciklusa előtt, és az ablak létrehozás után meghívjuk az OpenGL inicializáló, valamint kilépés/ablaktörlés előtt pedig a törlő függvényt.

Az ablak létrehozásánál már beszéltünk a fő hurokról, melyben elkapjuk az ablakhoz küldött üzeneteket, s szó volt arról is, hogy ha nincs üzenet, a program unatkozik (nem szó szerint persze :)). Tehát itt fogunk rajzolni. Mivel ezt a leírást nem az OpenGL-lel ismerkedőknek szánom, sokkal inkább azoknak, akik közelebb szeretnének kerülni Windows platformon a rendszerhez, ezért ilyen kérdésekkel, hogy hogyan kell rajzolni, melyik parancs mit csinál, stb, nem foglalkozom.
Tehát, ha rajzolni szeretnénk már tudjuk, hogy hol kell ezt csinálni, de még egy fontos dolog hátra van. Mivel dupla puffert használunk, s sosem az elsőre rajzolunk, ezért meg kellene valahogy fordítani őket a rajzolás végén.

Kód:
SwapBuffers(hDC);


Igen, az a hDC azonos az ablakunk rajzolási környzetével, amit OpenGL init-nél kérdeztünk le. Csak a teljesség kedvéért, az alap főciklusunk végül valahogy így néz ki:

Kód:
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3f(0.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(-0.2f, -0.2f);
glVertex2f(0.2f, -0.2f);
glVertex2f(0.2f, 0.2f);
glVertex2f(-0.2f, 0.2f);
glEnd();

SwapBuffers(hDC);
}
}


Remélem hasznát tudjátok venni valamikor. :)
Fájl : OpenGL + WinAPI 2.
Méret: 4kb Mb - Letöltve : 376

Értékelés: 10.00

Új hozzászólás
levyyz          2009.07.29 17:07
sziasztok nyilván tudtik nekem segiteni.a problémám a következö.Sof2 multival játtszom és mint tudjátok vagyis remélem...tehát szeretnek a játékosok játékközben üzengetni különbözö obscén kifelyezésekkel illetni a másik társk játék stilusát namármost ezt egy játékos ugy teheti meg ha lenyomja a t. billentyüt majd @és szám pl65 ...enter.Majd a monitoron láthatja és a hangszorokon hallhatja is az éppen beirt számhoz tartozo üzenetet.
Hogyan lehetne eggyes parancssorokat különbözo8a játék közben nem használt) billentyükhöz kapcsolni pl. u-billentyü@65 tehát hogy egy üzenethez csak egy billentyüt kelljen lenyomnom majd enter
előre isz köszönöm rem.tudtok nekem segiteni.
terbed          2008.10.04 01:41
1 kérdés mért nem frissül az oldal????