„Számítógépes grafika házi feladat tutorial” változatai közötti eltérés

Nullzero (vitalap | szerkesztései)
Rohamcsiga (vitalap | szerkesztései)
Az OpenGL és GLUT alapjai - kb újraírtam az egészet.
46. sor: 46. sor:


==Az [[OpenGL]] és GLUT alapjai==
==Az [[OpenGL]] és GLUT alapjai==
* Az [[OpenGL]] alapja egy állapotgép. Ha valamit beállítasz (pl. rajzolószínt) az úgy is marad, amíg nem módosítod.
=== Az OpenGL ===
* Az [[OpenGL]] alacsony szinten programozható, sebesség-orientált rendszer. Nem képes olyan "extrákra" mint árnyékolás, 3D tesszelláció stb., ezek megoldását a programozóra bízza.
* Az [[OpenGL]] egyszerű térbeli alakzatok (primtívek), pl.: pontok, vonalak, háromszögek rajzolására specializálódott.
* A függvények neve a Hungarian Notation elveit követi, azaz:
** Ezekből az építőkockákból csodákat lehet művelni, a mai számítógépes játékok nagyrészt hárszomszögek rajzolásából építkeznek.
** mindig kisbetűvel kezdődik, a gl, glu vagy glut szavakkal, attól függően hogy melyik függvénykönyvtárban található a függvény
** A primitíveket nagyon sok féle képpen és nagyon hatékonyan lehet az [[OpenGL]]-lel kirajzolni, de ezen kívül semmi mást nem tud, nem tud képet betölteni, árnyékokat számolni, de még egy kocka kirajzolásához is "küzdeni" kell.
** ha több szóból áll, a szavak első betűje nagy
** Egy rajzolófüggvény viselkedése több száz paramétertől függ, persze nem kell az összeset függvény argumentumként átadni, ehelyett az '''OpenGL egy állapotgép'''-en alapszik.
** a függvény végén gyakran megadjuk a paraméterek típusát, így megkülönböztetve a különböző meghívásokat (pl.: 3f - 3 db float, v - vector)
*** Ha valamit átállítasz (pl. a rajzolószínt), akkor az onnantól kezdve minden rajzolás-hívást befolyásol.
* A legtöbb OpenGL függvényt több különböző típusú paraméterrel is meg lehet hívni, viszont az OpenGL egy C könyvtár, amiben nincs függvény overload. Ennek kiküszöbélésére a függvények neve Hungarian Notation szerűen a név végén tartalmaz pár karaktert, ami a paraméterekre utal, pl.: 3f - 3 db float, 2iv - 2 elemű int vector (azaz pointer egy 2 elemű int tömbre / 2db intet tartalmazó struktúrúra első tagjára / tetszőleges memóriaterületre, ahol 2 db int van egymás után)
** pl.: glVertex3f()
** pl.: glVertex3f()
* Az [[OpenGL]] elnevezési konvenciója:
** A függvények neve mindig kisbetűvel kezdődik, a gl, glu vagy glut szavakkal, attól függően hogy melyik függvénykönyvtárban található a függvény
** Ha több szóból áll, azokat egybeíjuk, és a szavakat nagy betűvel kezdjük (camelCase).
*** pl.: glDrawElementsInstancedBaseVertexBaseInstance() - amúgy ez a leghosszabb nevű [[OpenGL]] függvény, de a tárgyból nincs rá szükség.
* Az OpenGL RGB színskálán állítja elő a képet, és neki is RGB érétéket kell adni, ha egy színt akarunk leírni. A grafikában jobban szeretünk a (-végtelen, végtelen) tartományon dolgozni a színekkel, ezért általában nem a megszokott egy byte-on (0,255) specifikáljuk a színeket, hanem inkább floatként kezeljük őket a (0, 1) - vagy a (-1, 1) - tartományon. Ennek az az oka, hogy így jóval nagyobb fényerősség beli különbségek is megjeleníthetőek, két teljesen fehér fény összegeként kaphatunk egy fényesebb fehéret, amit csak a rajzolási fázis legvégén konvertálunk vissza a (0, 255) tartományra. Technikailag byte-ot is lehet adni az OpenGL-nek, de pedagógia okokból a házikban kötelező float színeket használni.
* Az [[OpenGL]] csak a rajzolással foglalkozik, az, hogy hogyan jön létre az a valami (célszerűen egy ablak), amire ő tud rajzolni, az viszont már nem az ő dolga. Itt jön a képbe a GLUT.
=== A GLUT ===
* A GLUT egy platformfüggetlen ablak- és eseménykezelő, lényegében egy híd az oprendszer és az OpenGL context között. A GLUT beállításának nagyrésze a keretben előre meg van írva, csak az eseménykezelő függvényekről kell gondoskodnunk, amiket majd a GLUT meghív (ezek a függvények határozzák meg, hogy mit csinál a programunk).
* GLUT eseménykezelő függvények:
* GLUT eseménykezelő függvények:
** '''onDisplay()''' - a legfontosabb függvény, ide írjuk a képernyő törlését, majd a szükséges rajzoló részeket. Ha valami változás hatására frissíteni szeretnénk a képernyőt, azaz szeretnénk az onDisplay()-t lefuttatni, hívjuk meg a '''glutPostRedisplay()''' függvényt (ne közvetlenül az onDisplay-t!)
** '''onDisplay()''' - a legfontosabb függvény, ide írjuk a képernyő törlését, majd a szükséges rajzoló részeket. Ha valami változás hatására frissíteni szeretnénk a képernyőt, azaz szeretnénk az onDisplay()-t lefuttatni, hívjuk meg a '''glutPostRedisplay()''' függvényt (ne közvetlenül az onDisplay-t!). Fontos hogy az '''onDisplay()-en belül tilos meghívni a glutPostRedisplay()-t,''' az így megírt program elvi hibás (a képernyő mindig érvénytelen marad), ez a beadón nem fog működni.
** '''onInitialization()''' - inicializáló rész, pl. globális változók inicializálására. Figyeljünk rá hogy bizonyos GLUT függvények itt még nem használhatók, hisz pl. még nem jött létre az ablak amire rajzolunk.
** '''onInitialization()''' - inicializáló rész, pl. globális változók inicializálására. Tipikus hiba, hogy a globális változóknak egy gl/glu/glut függvény visszatérési értéket adjuk, vagy a változó konsktrukorában meghívunk ilyen függvényt. Így ugyanis még a main() kezdete előtt futattánk le egy ilyen típusú függvényt, amikor még ezek a könyvtárak nincsenek inicilaiálva. Ennek az elkerülésére van ott az onInitialization - ebben már nyugodtan használhatunk bármilyen függvényt az inicializációhoz.
** '''onKeyboard()''' - billentyűzet kezelés, a keret példája alapján eléggé egyértelmű, ne feledjük az újrarajzolást (glutPostRedisplay)
** '''onKeyboard()''' - Itt tudjuk kezelne egy billentyű lenyomását. Erre a házikban általában csak minimális szükség van.
** '''onMouse()''' - egér esemény kezelő, a keret példája alapján érthető. Figyeljünk rá, hogy a kapott koordináták nem a mi világkoordinátáink, hanem az oprendszer által átadott ablak koordináták! Ezek jellemzően bal fentről jobb lefelé nőnek, 2D-ben némi matekozással átszámolhatjuk világkoordinátákra.
** '''onMouse()''' - Itt kapunk értesíést arról, ha valamelyik egérgomb állapota megváltozott, és azt is megtudjuk, hogy az ekkor az egér az ablak koordináltái szerint (figyelem itt bal felül van az origó!) hol volt.
** '''onIdle()''' - Az időzítést és animációt megoldó függvény, akkor hívódik meg ha a gépnek éppen nincs jobb dolga. Részletesen lásd az animációról szóló részben.
** '''onMouseMotion()''' - Itt tudjuk meg, ha a felhasználó lenyomott egér gomb mellett mozgatta az egeret. A koordinálta értékére ugyan az vonatkozik, mint az onMouse esetén.
* Az openGL-ben a színek RGB értékekkel adhatók meg, de a megszokottól eltérően nem a 0-255 tartományban, hanem a 0-1 tartományban. A (0,0,0) tehát a fekete, az (1,0,0) a piros, míg az (1,1,1) szín a fehéret jelenti.
** '''onIdle()''' - Ez a függvény az idő múlását hivatott jelezni, így itt kell kezelni mindent ami az időtől függ (animáció).


==Koordináta-rendszerek és 2D/3D projekció==
==Koordináta-rendszerek és 2D/3D projekció==