2011. augusztus 24., szerda

SlimDX9 08 - Fények

Elég régen írtam már a DirectX C#-ban való alkalmazásáról. Ennek egyetlen egy oka volt, mégpedig a lustaság. Persze az is igaz, hogy nem túl sokan érdeklődnek ezen téma iránt. Minden estre én szeretném mindenképpen folytatni a SlimDX tutorialt és később a DirectX11 képességeit is áttekinteni. Most pedig folytassuk ott, ahol valahol régen abbahagytuk, rágjuk át magunkat újra a fényeken...

A DirectX és a fények

A megvilágítás az egyes vertexekhez rendel színértéket a következő információk alapján: az adott vertexnél használt anyag tulajdonságai, a fényforrás tulajdonságai, illetve az ún. visszaverődési modell, amely a számításokat konkrétan definiálja. A Direct3D ún. lokális megvilágítási modellt használ, azaz minden vertexhez úgy rendelünk színt, hogy az összes többi vertextől függetlennek tekintjük. Ebből következően a rendszer nem képes közvetlenül árnyékokat előállítani, mivel nem vizsgálja az objektumok egymáshoz való viszonyát. Az anyagtulajdonságok ismeretében a Direct3D minden egyes vertexre meghatározza, hogy az adott vertexet megvilágítva milyen visszaverődés következik be, a visszavert fény mértéke határozza meg, hogy az objektum az adott vertexben milyen színű lesz. Az API a visszavert fénynek a következő formáit különbözteti meg:
  • Ambiens: olyan fényt jelöl, amelynek a forrása a jelenetben minden objektumot egyformán világit meg. Legegyszerűbben háttérmegvilágításként képzelhető el. Pozíció és irány tulajdonságai nem értelmezettek. Minden objektum színintenzitását egyenletesen növeli.
  • Diffúz: Olyan felületek esetén tapasztalható, amelyek az adott szögben érkező fénysugarakat minden lehetséges irányban megközelítőleg egyenlő intenzitással szórják szét (a hétköznapokban ezeket matt felületeknek nevezzük). A Direct3D itt a Lambert-féle koszinusz-törvény segítségével számol. Az intenzitás függ a vertexhez tartozó felületi normális és a fény terjedési irányának viszonyától, de független a megfigyelő helyzetétől.
  • Spekuláris: A felület viselkedése leginkább egy tükörhöz hasonlítható. A beérkező fény nagy részét a felület egyetlen sugárként veri vissza (a gyakorlatban ezek a tükröződő felületek). Ebben az esetben a számítások az optimális visszaverődést tételezik fel, azaz a beérkező fénysugár és a visszavert fénysugár ugyanakkora szöget zár be a pontban vett felületi normálissal. Az intenzitás a megfigyelő helyzetétől is függ. Az API ebben az esetben a Phong-Blinn modellt használja.
  • Emissziós: Igazából itt nem is visszavert fényről, hanem az objektum által kibocsátott fényről van szó. Ennek ellenére a Direct3D az ilyen tulajdonságú objektumokat nem tekinti fényforrásoknak. segítségével fluoreszkáló és hasonló felületeket modellezhetőek.
A Direct3D a fények két nagy csoportját különbözteti meg: a szórt háttérvilágítást (ambient light) és a direkt megvilágítást (direct light), amely előre definiált fényforrást feltételez. Ez utóbbi esetben a Direct3D háromféle fényforrást képes modellezni: pontszerű (point light), irányított (directional light) és reflektor (spot light) fényforrásokat. Közös tulajdonságuk a fényforrás által kibocsátott fény intenzitása, amely külön ambiens, diffúz és spekuláris komponenseivel adható meg.

Fények a Direct3D API-ban
A szórt megvilágítás esetén sem a fény iránya, sem a pontos forrása nem állapítható meg, a szórt fény mindenütt jelen van. Ebben a modellben az objektumaink megvilágítása minden irányból, egyenletesen történik. A szórt megvilágítás nem játszik szerepet a fényvisszaverődésben illetve fényfoltképzésben. Szerepe a számítógépes grafikában egy általános, alacsony intenzitású megvilágítás biztosítása. A szórt fény esetében nem kell megadni az irány és a forrás helyzetét sem, kizárólag a színe és az intenzitása a lényeges.
A pontszerű fényforrás minden irányban egyenlő intenzitással bocsát ki fényt, egy meghatározott pontból. Ha a fényforrás távol van az objektumtól, hatását tekintve az irányított fényforrást közelíti; ellenkező esetben a különböző csúcspontokba különböző szögben érkeznek be a fénysugarak.

Pontszerű fényforrás
Egy felületi pont megvilágításának kiszámításához figyelembe kell venni az adott pont koordinátáit és a fényforrás helyzetét. A pontszerű fényforrás hatását egy meghatározott hatókörben (range) fejti ki, amelyen belül a fényintenzitás egyenletesen gyengül. Ennek a gyengülésnek a mértékét egy tompítási faktor (attenuation) szabályozza. Pontszerű fényforrásnál a tompítás értéke a range paramétertől függ a következő összefüggés szerint:


ahol d az aktuális vertex távolsága a fényforrástól, A0, A1 és A2 a tompítási konstans lineáris és kvadratikus tagjait jelölik, értékük [0,∞] intervallumból kerülhet ki, legalább egyikük nem nulla. Ez a megvilágítási modell egyike a legrealisztikusabbnak, azonban a számításigénye is viszonylag magas.
Az irányított fényforrás jellemzője a fénysugarak közös irányát meghatározó vektor. A vertexekben számított visszaverődés intenzitása nem függ a fényforrás helyzetétől, minden objektumot egyenletesen világit meg. Távoli fényforrások, elsősorban a Nap modellezésére használják. Ezen fényforrástípus esetében nem vesszük figyelembe a fényintenzitás-csökkenést. Mivel csak a fénysugarak irányát kell figyelembe venni a megvilágítás kiszámításakor, az összes fényforrás közül ennek a modellnek a legszerényebb a számításigénye. Irányított fényforrás esetén attenuation=1.
A reflektor fényforrás hatását egy kúpszerű tartományon belül fejti ki, hasonlóan egy zseblámpához. A kúpon belül a fényintenzitás nemcsak a fényforrástól vett távolsággal változik a megvilágított területen belül is két tartomány lesz elkülöníthető: egy belső, világosabb rész, amelyet a Θ szög határoz meg; és egy külső, gyengébben megvilágított tartomány, amelyet a Φ szög határoz meg.

Reflektor fényforrás

A kettő közötti intenzitás átmenet az ún. falloff paraméterben adható meg. Ha falloff>1, az átmenet hirtelen és éles, míg falloff<1 esetén folyamatosabb átmenetet érhetünk el. Minden vertexben a visszavert fény intenzitását a tompítási faktorral modulálhatjuk. Reflektor fényforrás esetén a tompítás a következő:


ahol a Spot0 a fénykibocsátás irányának és a vertexbe húzott vektornak skalárszorzata, Spot1=cos(Θ/2), Spot2=cos(Φ/2). Ennyit egyenlőre az elméletről. 
A gyakorlatban a bemutatott fényforrások közül a reflektor fényforrást valósítjuk meg mivel ez a leglátványosabb. A példa a CodeSampler oldalán található Spot Light példán alapul. A program futásának eredménye pedig itt csodálható:


A teljes forrás itt érhető el:


A bejegyzés megírásában nagy segítségemre voltak Nyisztor Károly DirectX-el kapcsolatos könyvei valamint Bóta Balázs - C# és Komputergrafika c. dolgozata.

0 megjegyzés :

Megjegyzés küldése