Biológia | Középiskola » Biológia B tételek, 2006

Adatlap

Év, oldalszám:2006, 15 oldal
Nyelv:magyar
Letöltések száma:3546
Feltöltve:2006. február 13
Méret:227 KB
Intézmény:-

Csatolmány:-

Letöltés PDF-ben:Kérlek jelentkezz be!

Értékelések

Ezt a doksit egyelőre még senki sem értékelte. Legyél Te az első!


Új értékelés

Tartalmi kivonat

Az OpenGL története és általános jellemzõi Az OpenGL-t (akkor még IrisGl) a Silicon Graphics (SGI) nevû amerikai cég fejlesztette ki, eredetileg saját grafikus munkaállomásainak programozására. Ezek a munkaállomások nagyon gyors grafikus célhardverek voltak, amelyek ultragyorsan végeztek olyan mûveleteket, amelyek szükségesek a grafikai számításokban, így a Silicon Graphics számítógépek rendkívül gyorsan végeztek például mátrixtranszformációkat. Azért, hogy a programokat más rendszerekre is át lehessen vinni, az SGI átdefiniálta az IrisGl-t, és az OpenGL nevet adta neki. Az egyik legfontosabb szempont az OpenGL kifejlesztésénél a hordozhatóság volt, ezért az OpenGL, az IrisGl-el szemben más rendszerek felé is nyitott (OpenGL = Open Graphics Library). Az elsõ OpenGL specifikációt 1992 júl. 1-én mutatták be Öt nappal késõbb, a legelsõ Win32 fejlesztõi konferencián az SGI az OpenGL mûködését egy Iris Indigo gépen

demonstrálta több grafikus alkalmazáson keresztül, mint pl. orvosi képfeldolgozó rendszerek, ill. részletek a Terminator 2 címû filmbõl. Ezután az SGI és a Microsoft együtt fejlesztették tovább az OpenGL-t. Az OpenGL egy szoftver interfész a grafikus hardverhez. Ez a szoftver interfész pár száz eljárásból és függvénybõl áll, melyek lehetõvé teszik 2 és 3 dimenziós grafikai objektumok létrehozását, és ezeken az objektumokon mûveletek elvégzését. Az OpenGL tehát egy eljárás- és függvénygyûjtemény, melyek 2 és 3 dimenziós geometriai objektumok specifikációját tartalmazzák; ezenkívül olyan eszközöket is nyújt, melyekkel szabályozni lehet ezen objektumok leképezését a képpufferbe, amelyben az OpenGL az eredményként létrejövõ képet tárolja. Ennek megjelenítése már az operációs rendszer, vagy az ahhoz tartozó ablakozó rendszer feladata. Itt elérkeztünk egy fontos dologhoz: az OpenGL nem tartalmaz ablakozó

rendszert, és nem támogatja az input eszközök kezelését sem, tehát ezeket a dolgokat az adott nyelven a programozónak kell megoldania (késõbb majd látni fogjuk, hogy azért mégsem ennyire rossz a helyzet). A Unix-os (Linux-os) OpenGL rendszerek grafikus felülete többnyire az X-Window, amely tartalmazza az ablakozást. Windows 95, 98 és NT esetén maga az operációs rendszer szolgáltatja a grafikus felületet. Az OpenGL platformfüggetlenségét az adatbeviteli és megjelenítési rendszertõl való függetlenség biztosítja. Ugyanezen okok miatt az OpenGL nem tartalmaz olyan parancsokat sem, amelyek magasszintû háromdimenziós objektumok specifikálására szolgálnak, így ezeket a modelleket geometriai primitívekbõl kell felépíteni (vonalak, pontok, sokszögek). Az OpenGL az ügyfél-kiszolgáló (kliens-szerver) felépítést követi. Ezáltal lehetõvé válik, hogy a grafikus alkalmazást futtató, és a végeredményt létrehozó gép egyazon, vagy

két különbözõ gép legyen. A grafikus alkalmazás - mint ügyfél - parancsokat ad az OpenGL kiszolgálónak, amely létrehozza a képet. Mivel a parancsok átadására szabványos protokollt dolgoztak ki, ezért az ügyfél és a kiszolgáló gépek különbözõ típusúak is lehetnek. Az OpenGL funkciói: • • • • • • • • a színtér definiálása háromdimenziós primitívekkel a nézõpont specifikálása megvilágítási modellek alkalmazása a megvilágított színtérrõl árnyalt modell készítése árnyékok és textúrák alkalmazása antialiasing (élsimítás) motion blur (mozgó objektumok körvonalainak elmosása) atmoszféra effektusok kezelése (pl.:köd) Az OpenGL alapfogalmai Az OpenGL primitíveket rajzol. A primitívek grafikai alapelemek Az OpenGL geometriai primitívei a pontok, a szakaszok és a sokszögek (poligonok).A geometriai primitíveket vertexek (csúcspontok, 3D pontok) definiálják. Egy vertex definiálhat egy pontot, egy

szakasz végpontját, vagy egy polygon csúcspontját, tehát minden OpenGL geometriai primitívet meg tudunk határozni a vertexeivel. A vertexek struktúrák, melyek tartalmazzák az illetõ csúcspont térbeli koordinátáit, színét és egyéb adatait. Az OpenGL minden vertexet függetlenül, rendezetten és ugyanúgy kezel. Az OpenGL más struktúrákat is használ, például pixelnégyszögeket, bittérképeket. Ezeket raszterprimitíveknek nevezzük Fontos, hogy megkülönböztessük a geometriai és raszterprimitíveket, mivel azokat az OpenGL eltérõ módon kezeli. Az OpenGL-t állapotautomataként is fel lehet fogni, mivel rendelkezik egy ún. state-tel (állapot) Ezen state tartalmazza azokat az érvényes adatokat, amelyek szükségesek a specifikált objektumok leképezéséhez. Tárolja, hogy pl. a világítás, azon belül mely fényforrások, az élsimítás, az árnyalás, stb. engedélyezve van, vagy le van tiltva Ezeket az információkat általában egyetlen

bit tárolja, ha a bit 1 akkor engedélyezett, ha 0 akkor nem. Az OpenGL-ben minden felhasznált paraméter rendelkezik egy iniciális vagy alapértelmezett (default) értékkel, pl: az alapértelmezett RGBA szín az (1.0, 10, 10, 10); az alapértelmezett transzformáció és vetítési mátrix pedig az egységmátrix. Koordináta-rendszerek Az OpenGL a megjelenítéskor a Descartes féle koordináta rendszert használja (Cartesian coordinate system), tehát a bázis olyan vektorokból áll, melyek mindegyike merõleges a többire. A koordinátákat a megszokott x, y, z hármassal jelöljük. Mivel a számítógépes grafikában leggyakrabban a jobbsodrású rendszerek használatosak, ezért az OpenGL is ezt használja. Jobbsodrású koordináta-rendszer esetén a (0, 0, 0) pontban van az origó, az x, y tengely pozitív része az origótól jobbra ill. fölfelé található, a z tengely pozitív része a képernyõbõl kifelé mutat. Szín módok Az OpenGL kétféle szín módot

használ: az RGBA szín módot, illetve a szín index módot. Az RGBA szín módban minden színt négy komponens definiál, a vörös (Red), zöld (Green), kék (Blue), illetve az alpha (Alpha) komponens. Minél nagyobb a komponens értéke, annál intenzívebben vesz részt a létrejövõ színben. Szín index módban minden színt egy lebegõpontos érték ír le, és minden ilyen lebegõpontos értékhez hozzá van rendelve három 8 bites érték a memóriában, rendre a három szín intenzitása. Szín mélység Mint ahogy a képernyõ felbontásának finomsága, a megjeleníthetõ színek száma is befolyásolja a kép részletességét, valósághûségét. A szín mélység azt jelenti, hogy a pixelek színét hány biten ábrázoljuk. 8-bites színmélység esetén 256 különbözõ szín megjelenítésére van lehetõségünk. 24-bites színmélység esetén egy pixel színét 24 bittel írjuk le, mégpedig úgy, hogy mindhárom színkomponenst intenzitását 8 biten

ábrázoljuk. A teljesítmény növelése érdekében egyes videokártyák más szín módokkal is rendelkezhetnek, pl. a 32 bites, vagy true color szín móddal A 32 bites szín módban ugyan nem tudunk több színt kikeverni, mint a 24 bites szín módban, de teljesítmény szempontjából a 32 bites szín mód van elõnyben, mivel itt gyorsabb a memóriahozzáférés, viszont van 8 elvesztegetett bit. Homogén koordináták Az OpenGL parancsok általában 2 és 3 dimenziós vertexekkel dolgoznak. Az OpenGL minden vertexet olyan 3 dimenziós vertexként tárol, melynek 4 koordinátája van. Minden (x, y, z, w) oszlop vektor egy homogén vertexet reprezentál, ha a vektorban legalább az egyik komponens nem nulla. Ha az a valós szám nem nulla, akkor (x, y, z, w) és (a*x, ay, az, aw) ugyanazt a homogén vertexet reprezentálja. Egy (x, y, z) 3 dimenziós euklideszi pont az (x, y, z, 1.0) homogén vertexnek, egy (x, y) 2 dimenziós euklideszi pont pedig az (x, y, 0.0, 10)

homogén vertexnek felel meg Ha w nem nulla, akkor az (x, y, z, w) homogén vertex az (x/w, y/w, z/w) 3 dimenziós pontnak, ha w = 0.0 akkor pedig egy végtelen távoli ideális pontnak felel meg. A végtelen távoli pontok megértéséhez tekintsük az (1, 2, 0, 0) pontot, és az (1, 2, 0, 1), (1, 2, 0, 0.01), (1, 2, 0, 00001) pontokat; ezek a pontok az (1, 2), (100, 200), (10000, 20000) euklideszi pontoknak felelnek meg. Ez a sorozat a 2x = y egyenes mentén távolodik a végtelenbe. Most már látjuk, hogy az (1, 2, 0, 0) pont ezen egyenes irányában, végtelen messzi van. Homogén koordináták használata több okból is indokolt lehet a számítógépes grafikában. Használatukkal lehetõvé válik, hogy a grafikában alkalmazott transzformációkat (eltolás (translate), forgatás (rotate), nagyítás (scale), nyírás (sheering)), és ezen transzformációk kompozícióját mátrixszorzásokkal el lehet végezni. Fontos szerepet kapnak a homogén koordináták a vágási

feladat megoldásánál is. Normálok Egy felülethez tartozó normál vektor (vagy normális) egy, a felületre merõleges egységnyi hosszúságú vektor. Minden normális egy háromdimenziós vektor, tehát egy normálisnak x, y és z komponense van, és mivel minden normális egységnyi hosszúságú, ezért sqrt(x^2 + y^2 + z^2) = 1. Egy sík felület esetén, a merõleges irány a felület összes pontjára ugyanaz, de egy nem egyenletes felület esetén, a normális a felület minden pontján más és más lehet. Az OpenGL-ben minden polygonhoz és minden vertexhez tartozik normális. Ugyanazon polygon vertexei ugyanazzal a normálissal is rendelkezhetnek, de lehetnek különbözõ normálisaik is. Egy polygon normálisát az OpenGL általában a vertexeinek a normálisaiból számítja ki. Normálisokat azonban csak vertexekhez specifikálhatunk Egy objektum normál vektora a felszínének az irányát definiálja általában a fényforrásokhoz relatívan. A normálisokat

a számítógépes grafikában több helyen is alkalmazzák. Ahhoz, hogy egy sík egyenletét le tudjuk írni, szükségünk van a sík normálisára, vagyis egy, a síkra merõleges vektor koordinátáira. Ekkor a sík egyenlete a következõképpen néz ki: Ax + By + Cz + D = 0 Fontos szerepet kapnak a normálisok az árnyalási feladatnál, a látható felszínek, vonalak meghatározásakor, illetve a megvilágítási feladatnál is. (például polygon határú síklapokkal határolt test hátra nézõ lapjait a normálisok segítségével határozhatjuk meg.) Koordináta transzformációk Vertex transzformáció A vertexeket, normálisokat és textúra koordinátákat az OpenGL transzformálja, mielõtt azokat felhasználná egy kép megalkotásában. A vertex transzformációkat ( forgatás, eltolás, skálázás, nyírás ) 4×4-es mátrixként reprezentálhatjuk. Ha v egy homogén vertexet reprezentál, M pedig egy 4×4-es transzformációmátrix, akkor M*v a v vertex képe az M

transzformáció után. A vertex koordinátákat objektumkoordinátáknak nevezzük, tehát egy vertex objektum koordinátái azok a koordináták, amelyeket a glVertex parancsban megadunk. Az objektum koordinátákat a modell-nézet vagy ModelView mátrix transzformálja ún. szem vagy eye koordinátákká A szem koordinátákból a vetítési vagy Projection mátrix által lesznek az ún. clip koordináták. Ez a transzformáció egy ún viewing volume (látótér)-t definiál (amely párhuzamos vetítés esetén egy téglalap, perspektivikus vetítés esetén pedig egy csonkagúla), úgy, hogy az ezen kívül esõ objektumokból vágott objektumok lesznek, így azok a végsõ képen nem fognak látszani. Ezután egy ún homogén osztás (perspective division) következik, és a clip koordináták normalizált eszköz koordinátákká (normalized device coordinates) transzformálódnak. Ezután már csak egy nézeti (viewport) transzformáció szükséges, és létrejönnek az

ablak koordináták. A gyakorlatban ez így néz ki (jelen esetben a vertexek oszlopvektorral való reprezentálását használjuk, így az adott vertexet mindig balról szorozzuk a transzformációmátrixszal (ez egyébként dr. Kuba Attila jegyzetében is így van, ezért biztosan ismerõs lesz); vannak források, melyek a másik megoldást használják, miszerint sorvektorokat szoroznak jobbról a transzformációmátrixszal, ekkor a transzformációmátrix is némiképp módosul, reméljük ez nem okoz semmi zavart (de hogy ne kelljen feleslegesen gondolkozni, elárulom hogy egyszerûen transzponálni kell a mátrixot;)): Legyenek egy vertex objektum koordinátái (x0, y0, z0, w0) (ez tehát egy oszlopvektor, azaz képzeljünk a vektor kitevõjébe egy T betût), és legyen a modell-nézet mátrix M. ; ekkor a vertex szem koordinátáit a következõképpen kapjuk: (xe, ye, ze, we ) = M*(x0, y0, z0, w0), tehát egy vertex szem koordinátáit úgy kapjuk, hogy az objektumkoordináta

vektorát beszorozzuk balról a modell-nézet mátrixszal. Ugyanígy, ha P a vetítési mátrix, akkor a vertex clip koordinátái: (xc, yc, zc, wc) = P*(xe, ye, ze, we), tehát egy vertex vetítés koordinátáit úgy kapjuk, hogy a szem koordináta vektorát beszorozzuk balról a vetítési mátrixszal. A vertex normalizált eszköz koordinátáit pedig a következõképpen kapjuk: (xd, yd, zd) = (xc/wc, yc/wc, zc/wc), azaz a vetítés koordinátákat leosztjuk a wc homogén koordinátával. Normál transzformáció A normálisok a fényszámításokban (is) vesznek részt. A normálisokat nem úgy transzformáljuk, mint a vertexeket vagy a pozíció vektorokat. Matematikailag jobb, ha a normálisokat nem vektornak, hanem a vektorra merõleges síknak tekintjük. Ekkor a normálisokra vonatkozó transzformációs szabályok a merõleges síkok transzformáció szabályai. Egy homogén síkot egy (a, b, c, d) sorvektorral definiálhatunk, ahol az a, b, c, d komponensek legalább

egyike nem nulla. Ha q egy nemnulla valós szám, akkor (a, b, c, d) és (qa, qb, qc, qd) ugyanazt a síkot reprezentálják. Egy (x, y, z, w) pont pontosan akkor van az (a, b, c, d) síkon, ha ax+by+cz+dw = 0. ( ha w = 1, akkor ez egy euklideszi sík) Ahhoz, hogy egy euklideszi síkot reprezentáljunk, nem lehet az a, b, c ( a sík normálvektora: (a, b, c)) komponensek mindegyike 0. Ha mind 0, akkor (0, 0, 0, d) egy végtelen távoli síkot reprezentál, amely az összes végtelen távoli pontot tartalmazza. Ha p egy homogén sík, v pedig egy homogén vertex, akkor a "v a p síkon fekszik" megállapítás matematikailag a következõt jelenti: p*v = 0, ahol p*v egy szokásos mátrix(vektor) szorzás mûvelet. Ha M egy nemszinguláris vertex transzformáció, akkor p*v = 0 ekvivalens a pM ^(1)Mv = 0 egyenlettel, tehát Mv a pM^(-1) síkon fekszik. Ezért, p*M^(1) az M transzformáció utáni képe a síknak. Vetítések Ha a háromdimenziós objektumokat meg akarjuk

jeleníteni a monitor képernyõjén, akkor ezeket a háromdimenziós modelltérbõl egy kétdimenziós nézetre kell leképezni. Ezért a Számítógépes grafikában kiemelt jelentõségû transzformációk a vetítések. A vetítés dimenziócsökkentõ mûvelet, tehát olyan transzformáció, amely n-dimenziós objektumokat kisebb dimenziós terekbe visz át. A vetítés eredménye a vetület, ami egy térbeli síkon, a vetítési síkon képzõdik. A tárgy- és képpontokon átmenõ egyenest vetítõsugárnak nevezzük. Az egyes tárgypontok képe a vetítõsugár döféspontja a vetítési síkkal. Általában kétféle vetítési típus használatos: párhuzamos, illetve perspektív vetítés. Párhuzamos vetítés esetén a vetítõsugarak párhuzamosak, ilyenkor csupán a vetítési irány van definiálva; perspektív vetítés esetén a vetítõsugarak mindegyike áthalad egy vetítési középponton, a centrumponton (szempozíció). A perspektív vetítés az objektumok

realisztikus ábrázolását teszi lehetõvé, ilyenkor a távolabbi objektumok kisebbnek tûnnek, a vetítési síkkal nem párhuzamos egyenesek egy pont felé tartanak. Párhuzamos vetítés esetén az eredetileg párhuzamos egyenesek párhuzamosak maradnak. Ezt a fajta vetítést a mérnöki tervezésben alkalmazzák, mégpedig azért, mert tudunk olyan párhuzamos vetítést specifikálni, ahol mérhetõek a távolságok és a szögek. Perspektív vetítés esetén a látótér tulajdonképpen egy végtelen piramisként képzelhetõ el, amelynek csúcsa a nézõpont, vagy szem. Az OpenGL-ben azért, hogy a túl közeli és távoli koordinátákkal ne kelljen foglalkozni, a látóteret elülsõ és hátsó síkokkal (vágósíkok) korlátozhatjuk, így a különbözõ megjelenítési eljárásokban csak ezt a korlátozott térrészt vesszük figyelembe. Tehát az OpenGL-ben egy csonkagúla fogja a perspektív vetítés látóterét reprezentálni, amelyet az elülsõ és hátsó

vágósíkokkal adunk meg. Párhuzamos vetítés esetén a látótér egy végtelen hasáb, amelyet itt is vágósíkokkal korlátozhatunk, így az OpenGL-ben a párhuzamos vetítés látótere egy téglatest. Az OpenGL-ben a párhuzamos vetítés azon speciális típusát használhatjuk, ahol a vetítési sík merõleges a z-tengelyre, és a vetítési sík normálisa párhuzamos a vetítési iránnyal, azaz az ortogonális vetítést. Az OpenGL-ben mindkét fajta vetítést úgy specifikálhatjuk, hogy megadjuk a látótér nagyságát és alakját. Világítás/Lighting Az OpenGL a megjelenítés elõtt minden pixel színét kiszámítja, a kiszámolt színértékeket a képpufferben tárolja el. A felmerülõ számítások egy része attól függ, milyen megvilágítást alkalmazunk, és hogy az objektumok ezen megvilágítás fényét hogyan tükrözik illetve nyelik el. Az OpenGL-ben lehetõség van a fényforrások és objektumok tulajdonságainak manipulálására. Az

OpenGL világítási modellben a fényt több, egyenként ki-, illetve bekapcsolható fényforrás határozza meg. A fényforrásoknak csak akkor van hatása, ha vannak olyan felületek, melyek a fényt visszatükrözik, vagy elnyelik. Egy anyagnak lehet saját fénye is, a bejövõ fényt szétszórhatja minden irányban, és tükrözheti a bejövõ fény egy részét egy bizonyos irányba akár egy tükör vagy más tükrözõdõ felszín. Az OpenGL világítási modellben a fénynek három független komponense van: ambient, diffúz és spekuláris. Szórt háttérvilágítás (ambient light) Ebben a modellben az objektumok egyenletesen, minden irányból kapnak fényt. Hatása a nappali fényviszonyoknak felel meg erõsen felhõs égbolt esetén. A számítógépes grafikában azért van rá szükség, hogy a felhasználó az ábrázolt jelenet összes objektumának a megvilágítását szabályozhassa. Ebben a modellben nincs fényforrás, az objektumok "saját"

fényüket bocsájtják ki. Ez megfelel annak, hogy a jelenetet egy irányfüggetlen, szórt fény világítja meg. Diffúz fényvisszaverõdés (diffuse light) A diffúz fényvisszaverõdés a matt felületek jellemzõje. Ekkor a megvilágított felület minden irányban ugyanannyi fényt ver vissza. Fényvisszaverõdés fényes és csillógó felületekrõl (specular light) A sima felületekre általában az a jellemzõ, hogy rajtuk fényes foltokat (specular highlight) is látunk, melyek helye nézõpontunkkal együtt változik. Ezek a felületek bizonyos irányokban visszatükrözik a fényforrásokat. Ekkor a matt felületekre jellemzõ diffúz és a tökéletesen (ideálisan) tükrözõ felületekre jellemzõ visszaverõdés közti átmeneti esetet kell modelleznünk. Anyag színek Az OpenGL aszerint a megközelítés szerint dolgozik, miszerint egy anyag színe a bejövõ fényben szereplõ vörös, zöld és kék fény arányától függ. Például egy tökéletesen piros

labda minden bejövõ piros fényt visszatükröz, és minden zöld és kék fényt elnyel, amely eltalálja õt. Ha a labdát fehér fényben nézzük (a fényt egyenlõ vörös, zöld és kék komponensekbõl kikeverve), akkor egy piros labdát látunk; ha azonban tiszta zöld fénnyel világítjuk meg a labdát, az feketének tûnik (a zöld szín teljesen elnyelõdik, és nincs visszatükrözõdõ fény). Akárcsak a fénynek, az anyagoknak is különbözõ ambient, diffúz és spekuláris színei vannak, amelyek meghatározzák az anyag ambient, diffúz és spekuláris tükrözõdését. Egy anyag ambient tükrözõdése összefüggésben van a bejövõ fény ambient komponensével, a diffúz tükrözõdése a bejövõ fény diffúz komponensével, . Az ambient és diffúz tükrözõdések határozzák meg az anyag színét, ezek többnyire hasonlóak vagy megegyezõek. A spekuláris tükrözõdés általában fehér vagy szürke. Az ambient, diffúz és spekuláris színek

mellett, az anyagoknak emisszív színei is vannak, amelyek a világító objektumok fényét szimulálják, azaz egy anyag emisszív színe az anyag saját fényének a színe. Az OpenGL megvilágítási modellben egy anyag emisszív színe intenzitást ad az objektumnak, de nincsenek rá hatással a fényforrások, és a világító objektum sincs hatással a többi objektumra. A fények és anyagok RGB értékei A specifikált fények szín komponensei némiképp különböznek az anyagokétól. Egy fény esetén, az értékek a teljes intenzitás százalékos kifejezései minden színre. Ha a fény színének mind az R, G és B komponense 1.0, akkor a fény a legfehérebb fehér Ha az értékek mindegyike 0.5, a fény még mindig fehér, de csak fél intenzitással, így az szürkének tûnik. Az anyagok számára, az értékek a színek tükrözõdési arányait specifikálják. pl ha R = 10, G = 05 és B = 00, akkor az anyag minden bejövõ vörös fényt és a zöld fény

50%-át veri vissza, viszont minden kék fényt elnyel. Más szavakkal, ha egy fényforrás szín komponensei (LR,LG,LB) egy anyag megfelelõ fény komponensei pedig (MR,MG,MB), akkor minden más tükrözõdési effekttõl eltekintve a szemünkbe érkezõ fény: (LR*MR,LGMG,LBMB). Megvilágított képek készítése A következõ lépések kellenek ahhoz, hogy a képünkhöz világítást adjunk: 1. minden objektum minden vertexéhez specifikálnunk kell normál vektort. Ezen normál vektorok határozzák meg az objektum irányát a fényforráshoz viszonyítva 2. egy vagy több fényforrás létrehozása, kiválasztása és pozicionálása 3. egy megvilágítási modell létrehozása és kiválasztása 4. az objektumok anyagi tulajdonságainak definiálása Az OpenGL renderelési fázisai Az OpenGL-ben az adott parancsok egy feldolgozási pipeline-on (csõvezeték) haladnak keresztül. A pipeline tartalmazza a megjelenítési listát (display list), a vertexfeldolgozót

(per-vertex operations), pixelfeldolgozót (pixel operations), raszterizálót (rasterization), fragmensfeldolgozót (per-fragment operations) és a képpuffert (framebuffer). Minden fázis egy adott mûvelet elvégzésére képes Az OpenGL parancsok mindig a hívás sorrendjében kerülnek feldolgozásra, bár elõfordulhat a parancs végrehajtása elõtt egy bizonytalan idejû várakozás. A parancsok elsõ lépésben a megjelenítési listába kerülnek, amely egy FIFO rendszerû tároló, amely a parancsokat a feldolgozásukig tárolja. Innen a parancsok két irányba mehetnek tovább A geometriai primitívekre vonatkozó parancsok a vertexfeldolgozóba kerülnek. Itt történnek a geometriai transzformációk, amelyek kiszámítják, hogy adott irányból nézve hol van a vertex képe. Itt történik még az egyenese és a sokszögek vágása is, melynek során az OpenGL levágja azokat a részeket, amelyek kiesnek a látótérbõl. A fázis utolsó mûvelete a vetítés. Azok a

parancsok, amelyek a raszterképekre és bittérképekre vonatkoznak, a pixelfeldolgozóba kerülnek. Ezután az adatok mindkét egységbõl a raszterizáló egységbe kerülnek, amely a primitíveket fragmensekre bontja. A fragmensek pixelek, és hozzájuk tartozó adatok, melyek a képpufferben a primitívek képét adják. Egy pont egyetlen fragmensbõl áll, mely tartalmazza a pont képének koordinátáit, színét és távolságát. A szakaszok annyi fragmensbõl állnak, ahány pixel elõállítja a szakasz képét a képpufferben. A sokszögek a szakaszokhoz hasonlóan több fragmensbõl állnak. A primitíveknél csak a vertexek távolsága, színe, fényessége és egyéb adatai ismertek; a fragmensekre bontás során a fragmensekre vonatkozó adatokat minden fragmensre meg kell határozni, amely elég bonyolult feladat. A végsõ fázisban az elkészült fragmensekbõl a fragmensfeldolgozó hozza létre a képpufferben a képet, de elõtte minden fragmens tesztelésre

kerül, amikor is eldõl, hogy az adott fragmens közelebb vagy távolabb vane annál a fragmensnél, ami a képpufferben ugyanott van. A képpuffer csak akkor frissítõdik, ha az új fragmens közelebb van a megfigyelõhöz, mint az eredeti fragmens. Az OpenGL programok fordításával kapcsolatos információk Általános információk Az OpenGL-nek jelenleg C/C++, ADA, Fortran és Visual Basic implementációja létezik. Ezeken az oldalakon a C/C++ implementációról lesz szó. Az C/C++ programozási nyelven írt OpenGL programokat Windows 9x/NT operációs rendszeren Borland C-vel és Visual C-vel lehet lefordítani. A kettõ közül a Visual C használatát javaslom, nekem az egyszerûbbnek tûnt. A Windows NT 3.5-ös verziójának megjelenése óta az OpenGL része az operációs rendszernek, ezért valószínûleg az OpenGL-é a jövõ (az más dolog, hogy a legtöbb 3D-s játékot még mindig egy másik grafikus rendszerben, a Direct3D-ben írják; viszont egy fontos érv az

OpenGl mellett, hogy platformfüggetlen). A Windows 98 tehát már tartalmazza az OpenGL programok futtatásához szükséges fájlokat. Mint már megjegyeztem, az OpenGL nem tartalmaz az ablakok létrehozását elõsegítõ függvényeket, ezért egy OpenGL program számára szükséges ablakot nekünk kell létrehozni az adott nyelven, amely hiába a Visual C, egyáltalán nem olyan egyszerû. Röviden arról van szó, hogy írni kell egy Windows programot, amelynek annyi a feladata, hogy az OpenGL használatához szükséges minimum követelményeket beállítsa, azaz nyisson egy ablakot, amelybe majd rajzolni lehet. A GDI-nek szüksége van egy Device Context (DC) kontextusra, az OpenGL-nek egy Rendering Context (RC) kontextusra. Az alapvetõ lépések tehát: • Az ablak aktuális pixel formátumának beállítása • Az RC létrehozása • A létrehozott RC aktiválása, azaz a DC összekötése az RC-vel A részletes leírásra nem térek ki, hiszen ez maga több oldalt tenne

ki; akit érdekel, írjon egy e-mailt, és akkor megadom a teljes leírást. A részletezés helyett egy olyan OpenGL kibõvítésre szeretnék kitérni, amely tartalmazza az ablakozási technikákat is, így elõsegíti ablakozó rendszertõl független OpenGL programok írását. Ez a GLUT Ahhoz, hogy egy GLUT programot le tudjunk fordítani Visual C fordítóval, néhány dolgot be kell állítani. Elõszor is be kell másolni a gluth header file-t a Vc98IncludeGl könyvtárba (az OpenGL header file-okat már tartalmazza a VC). Majd ugyanígy be kell másolni a glutlib, glut32lib file-okat a Vc98Lib könyvtárba, a glut.dll, glut32dll pedig a WindowsSystem könvtárba ( ha egy GLUT program exe-jét futtatni akarjuk, a WindowsSystem könyvtárnak tartalmaznia kell a glut32.dll fájlt). Ezek után egy GLUT program lefordítása: 1. variáció : Win32 konzol alkalmazás létrehozása Konzol alkalmazás Egy Win32 konzol alkalmazás egy olyan program, amely egy text módú ablakban

fut. Ez nagyon hasonlít arra, mikor egy DOS programot futtatunk Windows alatt, azzal a kivétellel, hogy ez egy tiszta 32 bites alkalmazás, és elérhetõ a Win32 API-n belül. A konzol programok létrehozhatnak GUI ablakokat az output számára, ahová az OpenGl rajzol. Egy ilyen alkalmazás létrehozása a következõképpen néz ki: 1. hozzunk létre egy új projektet Menjünk a Files menüre, válasszuk ki a New. menüpontot Válasszuk a Projects fület, és azon belül a Win32 Console application-t. Írjuk be a projekt nevét, legyen ez a név: first, majd OK. 2. a megjelenõ ablakban válasszuk az A simple application pontot 3. miután a projekt létrejött, egészítsük ki az stdafxh header file-t a következõ sorral: #include <GLglut.h> 4. menjünk a Projects/Settings menüpontra, majd válasszuk ki a Link fület. Az Objects/Library modules alatti sorba írjuk be a következõket: opengl32.lib glu32lib glut32lib Ezzel hozzáadtuk a projekthez a linkelendõ

könyvtárakat. 5. a source files/firstcpp file-t kiválasztva a következõ kódnak kell megjelennie: #include "stdafx.h" int main(int argc, char *argv[]) { return 0; } készen vagyunk, ide kell beírni a kódot, majd a Build/Build first.exe menüponttal tudjuk a programunkat lefordítani. 2. variáció: Egyszerû Win32 alkalmazás létrehozása (konzol ablak nélkül) Egyszerû Win32 alkalmazás Az OpenGl-lel kapcsolatos könyvek az elõzõ pontban leírt fordítási módszert javasolják, én mégis szeretnék megmutatni egy másikat, ami annyiban más, hogy nem hoz létre egy külön konzol ablakot. 1. hozzunk létre egy új projektet Menjünk a Files menüre, válasszuk ki a New. menüpontot Válasszuk a Projects fület,és azon belül a Win32 application-t. Írjuk be a projekt nevét, legyen ez a név: first, majd OK. 2. a megjelenõ ablakban válasszuk az A simple Win32 application pontot. 3. miután a projekt létrejött, egészítsük ki az stdafxh header file-t

a következõ sorral: #include <GLglut.h> 4. menjünk a Projects/Settings menüpontra, majd válasszuk ki a Link fület. Az Objects/Library modules alatti sorba írjuk be a következõket: opengl32.lib glu32lib glut32lib Ezzel hozzáadtuk a projekthez a linkelendõ könyvtárakat. 5. a source files/firstcpp file-t kiválasztva a következõ kódnak kell megjelennie: #include "stdafx.h" int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. return 0; } Tulajdonképpen készen is vagyunk. Ezután a WinMain függvény lesz a main függvény, ide kell beírni az ablak jellemzõit beállító parancsokat. Ha ezt megtettük, akkor létrejön egy ablak, amelybe már tudunk rajzolni. Ezek voltak a szükséges teendõk, részletesebb leírás a GLUT oldalon található. GLUT A Graphics Library Utility Toolkit(GLUT) A GLUT az OpenGL kibõvítése, amely már tartalmazza az OpenGL ablakok létrehozásához

szükséges eljárásokat, így néhány sor megírásával létre tudunk hozni egy OpenGL renderelésre alkalmas ablakot. A GLUT emellet saját esemény kezelõ rendszerrel is rendelkezik, sõt olyan rutinokat is tartalmaz, amelyekkel karaktereket és magasabb szintû geometriai objektumokat, mint például gömböket, kúpokat, ikozaédereket tudunk specifikálni. A GLUT úgy egyszerûsíti le az eseménykezelést, hogy callback rutinokat rendelhetünk bizonyos eseményekhez, mint például egy billentyû, vagy a bal egérgomb lenyomása. Ezután egy main loop-ba (esemény hurok) lépünk, majd ha egy esemény történik a hurokban, akkor az ezen eseményhez rendelt callback rutinok végrehajtódnak. A GLUT ablak és képernyõ koordináták pixelekben vannak kifejezve. A képernyõ vagy ablak bal felsõ koordinátája (0, 0). Az x koordináta jobbra haladva nõ, az y koordináta pedig lefelé; ez nem egyezik meg az OpenGL koordináta rendszerével, ahol általában a bal alsó

koordinátája (0, 0), de megegyezik a legelterjedtebb ablakozó rendszerek koordináta rendszerével. A GLUT-ban az egész azonosítók 1-gyel kezdõdnek, nem pedig 0-val. pl: az ablak és a menü azonosítók, illetve a menü item indexek. A GLUT header file-ok a következõ include direktívával építhetõk be a forráskódba: #include<GLglut.h> Egy ablak inicializálása és létrehozása Egy ablak létrehozásához specifikálni kell annak tulajdonságait. Ehhez a következõ rutinokat kell alkalmazni: void glutInit(int argc, char *argv); a glutInit eljárást minden más GLUT eljárás elõtt kell meghívni, mert ez inicializálja a GLUT library-t. A glutInit paraméterei megegyeznek a main függvény paramétereivel. megj.: a glutInit függvénynek nem kötelezõ szerepelni az ablak jellemzõit beállító függvények között, de ha szerepel, akkor az összes többi elõtt kell lennie; void glutInitDisplayMode(unsigned int mode); a glutInitDisplayMode a képernyõ

módot specifikálja (egyszeresen vagy kétszeresen pufferelt ablak, RGBA vagy szín index mód,.) pl.: a glutInitDisplayMode(GLUT SINGLE | GLUT RGB) egy egyszeresen pufferelt, RGB módban lévõ ablakot specifikál; megj.: a glutInitDisplayMode-nak meglehetõsen sok lehetséges paramétere van (GLUT DOUBLE, GLUT INDEX, GLUT STEREO, .), de egyszerûbb programok írásához nekünk ezek közül csak néhányra lesz szükségünk. Majd késõbb látni fogjuk, hogy pl kétszeresen pufferelt ablak (GLUT DOUBLE) a jó minõségû animációnál lesz elengedhetetlen. void glutInitWindowSize(int width, int height); az ablak méreteit specifikálja pixelekben. width: szélesség, height: magasság. pl.: a glutInitWindowSize(400, 400) egy 400x400-as ablakot specifikál void glutInitWindowPosition(int x, int y); az ablak bal felsõ sarkának x és y pozíciója. pl.: a glutInitWindowPosition(100, 100) az ablak bal felsõ koordinátái a pontban lesznek int glutCreateWindow(char *name);

megnyit egy ablakot az elõzõ rutinokban specifikált jellemzõkkel. Ha az ablakozó rendszer lehetõvé teszi, akkor a name megjelenik az ablak fejlécén. A visszatérési érték egy egész, amely az ablak azonosítója. Ezt az értéket használhatjuk fel az ablak kontrollálására pl.: a glutCreateWindow("single") egy single névvel ellátott ablakot specifikál. Ablakkezelés és input események Miután az ablakot létrehoztuk, de még mielõtt belépünk az esemény hurokba, kijelölhetjük a callback függvényeket a következõ rutinokkal: void glutDisplayFunc(void(*func)(void)); azt a függvényt specifikálja, amelyet akkor kell meghívni, ha az ablak tartalmát újra akarjuk rajzoltatni. megj.: leegyszerûsítve a dolgot: a func nevû eljárásban kell definiálni azokat a dolgokat, amiket meg szeretnénk jeleníteni. Lásd a példát void glutReshapeFunc(void(*func)(int width, int height)); azt a függvényt specifikálja, amelyet akkor kell meghívni, ha az

ablak mérete vagy pozíciója megváltozik. A func argumentum egy függvényre mutat, amelynek két paramétere van, az ablak új szélessége és magassága. Ha a glutReshapeFunc függvényt nem hívjuk meg vagy NULL az argumentuma, akkor egy alapértelmezett függvény hívódik meg, amely meghívja a glViewport(0, 0, width, height) függvényt. void glutKeyboardFunc(void(*func)(unsigned char key, int x, int y); a függvényt specifikálja, melyet egy billentyû lenyomásakor kell meghívni. key egy ASCII karakter Az x és y paraméterek az egér pozícióját jelzik a billentyû lenyomásakor (ablak relatív koordinátákban). megj.: tehát ha írunk pl egy void keyboard(unsigned char key, int x, int y) { switch(key) { case 27: exit(0); break; default: break; } } függvényt, majd ezt a függvényt átadjuk paraméterként a glutKeyboardFunc eljárásnak a következõképpen: glutKeyboardFunc(keyboard); akkor a programunkból az esc billentyû lenyomásakor léphetünk ki. void

glutMouseFunc(void(*func)(int button, int state, int x, int y); a függvényt specifikálja, amely egy egér gomb lenyomásakor illetve elengedésekor hívódik meg. A button callback paraméter a GLUT LEFT BUTTON, GLUT MIDDLE BUTTON illetve a GLUT RIGHT BUTTON egyike. A state callback paraméter a GLUT UP és a GLUT DOWN szimbolikus konstansok egyike. Az x és y callback paraméterek az egér pozícióját jelzik az egér esemény megtörténtekor (ablak relatív koordinátákban). void glutPostRedisplay(void); az érvényes ablak frissítését eredményezi. megj.: a glutPostRedisplay eljárásra többnyire az animációkészítésnél lesz szükségünk, ugyanis ezzel az eljárással tudjuk az ablakot periodikusan frissíteni. Példa GLUT programra Hozzunk létre egy 200 pixel széles, és 200 pixel magas ablakot a (100, 100) pozícióban. Az ablak neve legyen firstglut Az ablak legyen egyszeresen pufferelt, és RGB szín módú. Rajzoljunk fekete háttérbe egy kék szakaszt

(0.2, 02) pontból a (08, 08) pontba A programból esc-re tudjunk kilépni. #include<GLglut.h> #include<stdlib.h> /*#include "stdafx.h"*/ void init(void) { glClearColor(0.0, 00, 00, 00); // a háttér legyen fekete glMatrixMode(GL PROJECTION); // beállítjuk a vetítési mátrixot glLoadIdentity(); // betöltjük az egységmátrixot glOrtho(0.0, 10, 00, 10, -10, 10); // vágósíkok } void display(void) { glClear(GL COLOR BUFFER BIT); // a képernyõ törlése glColor3f(0.0, 00, 10); // az érvényes szín kék glBegin(GL LINES) { glVertex2d(0.2, 02); glVertex2d(0.8, 08); // az egyenes specifikálása glEnd(); glFlush(); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 27: exit(0); break; } } int main(void) { /* int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) */ glutInitDisplayMode(GLUT SINGLE | GLUT RGB); // egyszeresen pufferelt, RGB szín módú ablak glutInitWindowSize(200, 200); // az

ablak mérete glutInitWindowPosition(100, 100); // az ablak pozíciója glutCreateWindow("firstglut"); // az ablak neve init(); glutDisplayFunc(display); // a képernyõ kezelése glutKeyboardFunc(keyboard); // a billentyûzet kezelése glutMainLoop(); // belépés az esemény hurokba return 0; } /* ha Visual C-ben akarjuk a kódot lefordítani, akkor így fog kinézni a program*/ OpenGL parancsok szintaktikája Egy OpenGL parancs eljárás vagy függvény lehet. Minden OpenGL parancs a gl prefixszel kezdõdik. Egy parancsnak általában több változata is lehet, amelyek az argumentumok átadásában különböznek. Egy OpenGL parancs egy névbõl áll, amelyet maximum 4 karakter követ. Az elsõ karakter az argumentumok számát jelöl; a második karakter vagy karakterpár az argumentumok típusát jelzi: 8 bites egész, 16 bites egész, 32 bites egész, egyszeres pontosságú lebegõpontos, vagy duplapontosságú lebegõpontos szám. Az utolsó karakter, ha van, akkor v,

jelezve azt, hogy az argumentum egy vektorra mutató pointer. Ezek alapján egy OpenGL parancs általános alakja: visszatérési értéktípus Név{#1234}{#b s i f d ub us ui}{#v}([args,] T arg1, . T argN [,args]); ( a # az üres karaktert jelenti ) pl.: a void glVertex3f ( float x, float y, float z ); parancs egy vertexet specifikál az (x, y, z) koordinátákban. Ha a parancs nevének utolsó karaktere v, akkor csak az arg1 van jelen, és az egy N db, adott típusú értéket tartalmazó vektorra mutató pointer; pl.: void glVertex2sv ( short v[2] ); Az OpenGL adattípusai Az OpenGL a jobb hordozhatóság érdekében saját adattípusokkal rendelkezik. Ezek az adattípusok általában megfelelnek a standard C adattípusoknak. Az alábbi táblázat bemutatja az OpenGL adattípusokat és a hozzájuk tartozó C adattípusokat (természetesen használhatjuk a standard C/C++ adattípusokat, többnyire ezen honlap példáiban is ezeket használom). OpenGL adattípus C típus C

szuffix GLbyte GLshort GLint, GLsizei GLfloat, GLclampf GLdouble, GLclampd GLubyte, GLboolean GLushort GLuint, GLenum, GLbitfield Belsõ reprezentáció 8-bites egész 16-bites egész 32-bites egész 32-bites lebegõpontos 64-bites lebegõpontos 8-bites elõjeletlen egész 16-bites elõjeletlen egész 32-bites elõjeletlen egész signed char short long float double unsigned char unsigned short unsigned long b s l f d ub us ui Vertex specifikáció • • • • • A glVertex parancs A glTexCoord parancs A glNormal parancs A glColor parancs A glIndex parancs A vertexek (csúcspontok) az OpenGL alapelemei. Vertexek lehetnek pontok, szakaszok végpontjai, illetve polygonok csúcsai. Minden geometriai primitívet vertexek rendezett sorozataként tudunk specifikálni. Az OpenGL minden vertexet homogén vertexként tárol, így azokat 4 lebegõpontos számmal reprezentálja, amely a vertex négy koordinátája. A negyedik, w koordináta általában imlicit 1.0 Ha a vertexek

koordinátáit kiegészítjük ezzel a plusz koordinátával, akkor lehetõvé válik, hogy minden lineáris transzformációt (eltolás, forgatás, skálázás) mátrixszorzásokkal végezzünk el. Mivel a mátrixszorzás asszociatív, így egyetlen mátrixszorzással akár bonyolult transzformációkat is el tudunk végezni. Mivel minden vertexhez( és az OpenGL-ben csak vertexekhez) színt, koordinátákat, normált és textúra-koordinátákat rendelhetünk, ezért a vertexeket struktúraként is fel lehet fogni. A glVertex parancs Vertexeket úgy specifikálhatunk, ha megadjuk a koordinátáit 2, 3 vagy 4 dimenzióban. Ez a specifikáció a void glVertex{234}{sifd}( T coords ); void glVertex{234}{sifd}v( T coords ); parancsokkal lehetséges. Bármely glVertex parancs négy koordinátát specifikál: az x, y, z és w koordinátákat. A glVertex2 parancs például beállítja az x és y koordinátákat, a z koordinátát 0-ra, a w koordinátát pedig 1-re állítja. A glVertex4 egy

ideális pontot specifikál a projektív térben pl.: a glVertex2f(05, 05) parancs egy 2-dimenziós vertexet specifikál a (0.5, 05) koordinátákban a glVertex3i(10, 10, 10) parancs egy 3-dimenziós vertexet specifikál a (10, 10, 10) koordinátákban egy vertex specifikálása ( glVertex3d(50,50,0)) A glTexCoord parancs A void glTexCoord{1234}{sifd}( T coords ); void glTexCoord{1234}{sifd}v ( T coords ); a homogén textúra koordinátákat állítja be, névszerint az s, t, r és q koordinátákat. A glTexCoord1 parancs az s koordinátát állítja be a meghívott értékre, a t és r koordinátákat 0-ra, q-t pedig 1-re állítja. A glTexCoord4 mind a négy koordinátát beállítja. Mint a neve is mutatja a glTexCoord parancs a textúra koordinátákat állítja be. A glNormal parancs Az érvényes normálist a void glNormal3{bsifd}( T coords ); void glNormal3{bsifd}v ( T coords ); parancsokkal specifikálhatjuk. Az érvényes normálisok a fényszámításokban, az

árnyékolásban, illetve a látható felszín meghatározásában vesznek részt. Mivel minden normális egy 3 dimenziós vektor, ezért a glNormal parancsnak csak egy változata van. pl.: a glNormal3f(10f, 00f, 00f) egy normális specifikációja A glColor parancs Az OpenGL-ben kétféle szín mód használatára van lehetõség. Az egyik az RGB, vagy RGBA szín mód, a másik az indexelt szín mód. Az elsõben minden színt 3 vagy 4 komponens határoz meg. R: vörös, G: zöld, B: kék, A: alpha komponens. Az indexelt szín módban minden színt egy lebegõpontos érték ír le, és minden ilyen értékhez meg van határozva a memóriában három 8 bites komponens. Az RGBA színeket a void glColor{34}{bsifd ubusui}( T components ); void glColor{34}{bsifd ubusui}v( T components ); eljárásokkal állíthatjuk be. A glColor4 az RGBA szín mind a négy komponensét beállítja; a glColor3 az R, G és B komponenseket specifikálja, az A pedig implicit 0.0 A glColor eljárás

lebegõpontos értékeket vár 0.0 és 10 között, ezen kívül esõ értékeket nem fogad el 00 a minimum, 1.0 pedig a maximum értéknek felel meg pl.: a glColor3d(10, 00, 00) a tiszta piros színt specifikálja a glColor3d(0.5, 05, 05) a szürke egy árnyalata A glIndex parancs Az érvényes szín indexet a void glIndex{sifd ub}( T index ); void glIndex{sifd ub}v ( T index ); eljárásokkal állíthatjuk be. A szín index határok gépfüggõek; az eljárás a határon belül esõ értékeket fogad