Az OpenGL
rutinkönyvtárai |
|||||||||||||||||||||||||||
Az előző cikkben leszögeztük, hogy C++-szal fogunk dolgozni a
továbbiakban. Nos, aki már ismeri a C-t, tudja, hogy ez nem fog menni a
megfelelő header és lib fájlok hiányában.
Nagyban megkönnyíti a dolgunkat, hogy az OpenGL nem új keletű dolog, így
a legtöbb fordítóhoz már mellékelik a fent említett komponenseket. Ha egyik
vagy másik esetében mégsem lenne így, a http://www.opengl.org címen mindig
elérhető belőlük a legújabb változat. Röviden szólnék
néhány szót ezekről a rutinkönyvtárakról és a hozzájuk tartozó header fájlokról. Az, amit mindig használni fogunk, az OPENGL32 és a hozzá
tartozó GL.H nevű header fájl. Ez utóbbi általában a szabványos Include-könyvtár alatt egy GL
könyvtárban van, így az #include <GL/gl.h> paranccsal kell beilleszteni a programunkba.
(Linuxosok! Figyeljenek a kis és nagybetűk különbségére!) Szintén
sűrűn használt library a GLU32 (include: GL/glu.h), amely az OpenGL Utility Library rövidítése
és arra szolgál, hogy extra matematikai megoldásokkal és adattípusokkal,
függvényekkel segítse munkánkat. Az előbbi rutinkönyvtárhoz hasonlóan ez
is standard része az OpenGL fejlesztői csomagjának. A
következő library már nem tartozik szervesen az OpenGL
rutinkönyvtáraihoz, hanem egy különálló fejlesztés, viszont mi mégis
használni fogjuk, mert rengeteg fejfájástól kíméli meg a programozót! Ez a
library a GLUT (OpenGL Utility
Toolkit). A fájlok pedig GLUT32 és GL/glut.h. Megjegyezném, hogy mivel ez nem standard, mint
az előző kettő, nem mindegyik fordítóhoz mellékelik. (A CD
mellékletre felkerül egy általam összeállított csomag, amely biztosítja, hogy
a DevC++ használóinak is gond nélkül menjen a GLUT használata. Én ezzel dolgozom és
tapasztaltam némi verzió-problémát, amikor megpróbáltam GLUT-ra épülő programot fordítani vele,
ennek kijavítására szolgál a csomag.) Nem tudom, ki
mennyire van tisztában az ilyen külső rutinkönyvtárak használatával
C-ben, ezért megjegyzem, hogy a linkernek senki se felejtse el beállítani,
hogy a tárgykódhoz a fenti library-kat szerkessze hozzá, különben egyetlen
példaprogram sem fog lefordulni! Ez a beállítás fordítónként más és más,
ezért mindenkit megkérek, nézze meg annak dokumentációjában, hogyan kell! |
|||||||||||||||||||||||||||
Adattípusok |
|||||||||||||||||||||||||||
Ezzel most meg is volnánk, akár írhatnánk is az első programunkat,
de még mindig van egy kis elméleti rész, amit át kell tekintenünk! Ez pedig
nem más, mint az OpenGL adattípusai, amelyeket a függvények használnak és mi
is használni fogunk. Az egyszerűség kedvéért az egyes típusokat a
leginkább közel álló C típusokkal hasonlítjuk össze:
Miután
feltételezem, hogy C-ben nagyjából mindenki ismeri az adattípusokat, erre nem
is szándékozom több időt vesztegetni. |
|||||||||||||||||||||||||||
Az első program |
|||||||||||||||||||||||||||
Hát igen! Bármily hihetetlen, idáig is eljutottunk! Álljon itt most egy
rövid program, amely nem csinál mást, csak kirajzol egy fehér négyzetet a
képernyőre! Utána pedig igyekszem minél érthetőbben elmagyarázni a
kódot. #define
GLUT_DISABLE_ATEXIT_HACK #include
<windows.h> #include
<GL/gl.h> #include
<GL/glu.h> #include
<GL/glut.h> void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT); //(1) glClearColor(0.0f, 0.0f, 0.0f, 1.0f ); //(2) glColor3f(1.0f, 1.0f, 1.0f); //(3) glBegin(GL_QUADS); //(4) glVertex3f(-0.5f, -0.5f, 0.0f); glVertex3f(-0.5f, 0.5f, 0.0f); glVertex3f( 0.5f, 0.5f, 0.0f); glVertex3f( 0.5f, -0.5f, 0.0f); glEnd(); glutSwapBuffers(); //(5) } int main(int argc, char*
argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE |
GLUT_RGB | GLUT_DEPTH); //(6) glutCreateWindow("Pelda01"); //(7) glutDisplayFunc(RenderScene); //(8) glutMainLoop(); return
0; } Hát, ez lenne
az! Mindjárt el kell mondanom, hogy az első két sor azért kell, hogy a GLUT tudjon Windows környezetben is
működni, az OpenGL-hez más köze nincsen. (Az 1. sor elég
fordítófüggő dolog, MinGW-nél és CygWin-nél általában
kell, különben a linker hibával kilép...) Két függvényünk
van: a main() és a RenderScene(). A GLUT működésének alapja, hogy
inicializálja a képernyőt az OpenGL számára (6.), majd létrehoz egy
ablakot, amibe rajzolni fogunk (7.).
Ha ez megvan, beállítunk neki egy függvényt, ami semmi mást nem
csinál, csak letörli a viewportot (az ablaknak/képernyőnek azt a részét,
ahová rajzolunk) és kirajzolja újra a képet. (8.) Ennek az animációnál van
igazán szerepe, ahol közben néhány dolog megváltozik és más fog megjelenni az
újrarajzolás után. Valójában ez a
folyamat (innentől úgy hívjuk: a renderelés) úgy történik, hogy két
képpuffert használunk. Az egyiket nem látjuk, erre történik a rajzolás, a
másik pedig éppen látható. Az előbbit hívjuk BackBuffernek. Ha a
BackBuffer-ben befejeződött a rajzolás, a program megcseréli a két
puffert (5.), így amit a BackBufferbe rajzoltunk, az válik láthatóvá. A BackBuffer
letörléséért az (1.) utasítás a felelős, a (2.) csupán annyit csinál,
hogy a háttérszínt feketére állítja. Mivel ez az első utasítás, amely
színeket kezel, megemlíteném, hogy a szineket 3 db 0 és 1 közötti float értékkel
adjuk meg, egy RGB (vörös, zöld és kék színkomponensek) kombinációval.
Értelemszerűen a (0,0,0) a fekete és az (1,1,1) a fehér. A negyedik,
eddig nem említett paramétert alpha-nak hívjuk, de ezzel majd csak
később foglalkozunk, addig maradjon 1.0f-re állítva ez az érték! A (3.) utasítás
legegyszerűbben fogalmazva azt a színt állítja be, amivel rajzolunk – ez
itt most a fehér. Természetesen mindig a rajzolás előtt kell a színt
állítani, utána meghívni a rajzolást végző függvényt. A (4.) és
egyben utolsó rész, amit tárgyalni szeretnék, egy példa a korábban említett
primitive-ek használatára. A glBegin() függvény paramétere megadja, hogy milyen primitive kerül rögtön utána
megadásra. Most nekünk bőven elég, ha ezt az egy primitive-et ismerjük,
a következő cikkben úgy is sorra vesszük őket. A glBegin() lezáró párja a glEnd(), amelynek nincsen paramétere. A
kettő között kell megadni sorban a létrehozandó primitive vertexeit.
Erre a célra itt a Vertex3f()-et használtuk. A függvény 3 paramétere a vertex (x,y,z) koordinátáit jelenti. Most, hogy
láttunk egy OpenGL programot, remélhetőleg mindenki tisztában van
annyira az alapokkal, hogy a következő részben továbbléphetünk az alap
primitive-ek részletezésére. Aki még nincs, az nyugodtan próbálgassa a
programban a koordinátákat, színértékeket a saját kedvére változtatni! Ezúttal is
várom kérdéseiteket, kommentárjaitokat e-mailben! Viszlát következő
alkalommal! |
|||||||||||||||||||||||||||
Merczel László |