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, 1.0, 1.0, 1.0); az alapértelmezett transzformáció
és vetítési mátrix pedig az egységmátrix.
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.
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.
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.
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,
a*y, a*z, a*w) 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, 1.0) 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, 0.0001) 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.
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.)
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 p*M
^(-1)*M*v = 0 egyenlettel, tehát M*v a p*M^(-1)
síkon fekszik. Ezért, p*M^(-1) az M transzformáció
utáni képe a síknak.
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.
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 = 1.0, G = 0.5 és B = 0.0, 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,LG*MG,LB*MB).
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