„Számítógépes grafika házi feladat tutorial” változatai közötti eltérés
a Apró hibákat javítottam →A harmadik házihoz szükséges elmélet |
|||
| 582. sor: | 582. sor: | ||
** Azt is tudnunk kell, hogy melyik iránynak felel meg a felfele ("What's up?"). Kódban pl nevezzük <code>up</code>-nak. | ** Azt is tudnunk kell, hogy melyik iránynak felel meg a felfele ("What's up?"). Kódban pl nevezzük <code>up</code>-nak. | ||
** Tegyük fel, hogy téglalap (vagy sík) egységnyi távolságra van a kamerától. Ekkora annak a középpontja: <code>pos + fwd</code>. | ** Tegyük fel, hogy téglalap (vagy sík) egységnyi távolságra van a kamerától. Ekkora annak a középpontja: <code>pos + fwd</code>. | ||
** Tudnunk kell még, hogy melyik irány van jobbra. Ezt | ** Tudnunk kell még, hogy melyik irány van jobbra. Ezt az előre és a felfele pozícióból ki tudjuk számolni: <code>right = cross(fwd, up)</code>. | ||
** A felfele vektor amit megadtunk nem biztos, hogy merőleges az előre vektorra, pedig nekünk olyanra van szükségünk. Pl: ha rézsútosan előre és lefele nézünk, de az 'up' vektor az ég fele mutat. Ez igazándiból nem baj, mert a jobbra és előre vektor ismeretében már ki tudjuk számolni a pontos felfele vektort: <code>up = cross(right, fwd)</code>. | ** A felfele vektor amit megadtunk nem biztos, hogy merőleges az előre vektorra, pedig nekünk olyanra van szükségünk. Pl: ha rézsútosan előre és lefele nézünk, de az 'up' vektor az ég fele mutat. Ez igazándiból nem baj, mert a jobbra és előre vektor ismeretében már ki tudjuk számolni a pontos felfele vektort: <code>up = cross(right, fwd)</code>. | ||
** Ha ezek megvannak, akkor ki kell tudnunk számolni, hogy egy (x, y) koordinátájú pixelnek a téglalap ( | ** Ha ezek megvannak, akkor ki kell tudnunk számolni, hogy egy (x, y) koordinátájú pixelnek a téglalap (ami most egy egység oldalhosszúságú négyzet) melyik része felel meg. Ezt így tehetjük meg: | ||
<br/> <syntaxhighlight lang="c"> | <br/> <syntaxhighlight lang="c"> | ||
| 607. sor: | 607. sor: | ||
* Megjegyzések az algoritmussal kapcsolatban: | * Megjegyzések az algoritmussal kapcsolatban: | ||
** | ** Az ernyő (a téglalap) az, amin a kép keletkezik, az viselkedik úgy mint a szemünk. Ha a téglalap helyére állnánk, akkor látnánk ugyan azt a képet, mint amit meg fogunk jeleníteni. Ezért célszerű kezdetben a kamera pozíciója helyett a téglalap pozícióját megadni. A kamera pozíciója amúgy irreleváns, az tetszőlegesen távol lehet a téglalaptól, ha a távolsággal arányosan növeljük a téglalap méretét, akkor ugyan azt a képet fogjuk kapni. | ||
** Azzal, hogy kijelentettük, hogy téglalap egység négyzet, és egységnyi távolságra van a kamerától, implicit kimondtuk, hogy a kamera látószöge arctg(1) = 45 fok. De nem biztos, hogy ennyit szeretnénk, úgyhogy a látószög (Field of View - Fov) is legyen inkább paraméter. A kamera téglalap távolságot célszerűbb változtatni, mint a téglalap méretét, mert így nem kell eltárolni a FoV-ot. Az arány amit akarunk az 0.5*ctg(fov/2) | ** Azzal, hogy kijelentettük, hogy téglalap egység négyzet, és egységnyi távolságra van a kamerától, implicit kimondtuk, hogy a kamera látószöge arctg(1) = 45 fok. De nem biztos, hogy ennyit szeretnénk, úgyhogy a látószög (Field of View - Fov) is legyen inkább paraméter. A kamera-téglalap távolságot célszerűbb változtatni, mint a téglalap méretét, mert így nem kell eltárolni a FoV-ot. Az arány amit akarunk az 0.5*ctg(fov/2) | ||
** Ezeket a változtatásokat is felhasználva egy lehetséges megvalósítás: | ** Ezeket a változtatásokat is felhasználva egy lehetséges megvalósítás: | ||
| 645. sor: | 645. sor: | ||
</syntaxhighlight> <br/> | </syntaxhighlight> <br/> | ||
* Most | * Most már mindent tudunk a sugárkövetésről, azt leszámítva, hogy hogyan kell egy sugarat követni. | ||
=== Hogyan kövessük a sugarakat? === | === Hogyan kövessük a sugarakat? === | ||
| 672. sor: | 671. sor: | ||
// Az óra járásával ellentétes (CCW) körüljárási irányt feltételez ez a kód a pontok megadásakor. | // Az óra járásával ellentétes (CCW) körüljárási irányt feltételez ez a kód a pontok megadásakor. | ||
Triangle( | Triangle(const Vector& a, const Vector& b, const Vector& c) | ||
: | : a(a), b(b), c(c) { | ||
Vector ab = b - a; | Vector ab = b - a; | ||
Vector ac = c - a; | Vector ac = c - a; | ||
| 761. sor: | 760. sor: | ||
</syntaxhighlight> <br/> | </syntaxhighlight> <br/> | ||
* A legközelebbi metszéspont kiszámolásához a legegyszerűbb (de leglassabb) megoldás, ha végigmegyünk az összes objektumon, és amikkel találtunk metszéspontot, azokra a | * A legközelebbi metszéspont kiszámolásához a legegyszerűbb (de leglassabb) megoldás, ha végigmegyünk az összes objektumon, és amikkel találtunk metszéspontot, azokra a metszéspontokra kiszámoljuk a kamerától vett távolságot, és ezeknek az értékeknek nézzük a minimumát. | ||
** Ehhez persze el kell tárolni az összes objektumot egy helyre, hogy végig tudjuk iterálni rajtuk. De az objektumok persze különböző osztályúak is lehetnek, itt segít | ** Ehhez persze el kell tárolni az összes objektumot egy helyre, hogy végig tudjuk iterálni rajtuk. De az objektumok persze különböző osztályúak is lehetnek, itt sokat segít a heterogén kollekció használata. Az objektumok az én implementációmba azt is eltárolják, hogy milyen anyagból vannak. | ||
<br/> <syntaxhighlight lang="c"> | <br/> <syntaxhighlight lang="c"> | ||
| 792. sor: | 791. sor: | ||
} | } | ||
static const | static const Vector env_color; | ||
/* Majd a fényforrásokat is el kéne tárolnunk itt */ | |||
Scene() : obj_num(0) { } | Scene() : obj_num(0) { } | ||
| 822. sor: | 815. sor: | ||
if(closest_index != -1) { | if(closest_index != -1) { | ||
return objs[closest_index]->mat-> | return objs[closest_index]->mat-> /* Kérdezzük meg tőle valahogy, hogy milyen színű abban a pontban. */; | ||
} else { | } else { | ||
return env_color; | return env_color; | ||
| 830. sor: | 823. sor: | ||
</syntaxhighlight> <br/> | </syntaxhighlight> <br/> | ||
* Ha ennél gyorsabb algoritmusra van szükséged, akkor ajánlom egy BSP-fa implementálását, mármint konkrétan egy KD-fát csinálj, ne általános BSP-t. Ez nagyon gyors, és nem nehéz implementálni... | * Ha ennél gyorsabb algoritmusra van szükséged, akkor ajánlom egy BSP-fa implementálását, mármint konkrétan egy KD-fát csinálj, ne általános BSP-t. Ez nagyon gyors, és nem nehéz implementálni... csak meg kell írni... | ||
* Ami a kódból is látszódik, hogy még nem vagyunk készen, amikor meghatároztuk a legközelebbi metszéspontot, ugyanis nekünk egy színre van szükségünk, amit megjeleníthetünk, nem egy helyvektorra. | * Ami a kódból is látszódik, hogy még nem vagyunk készen, amikor meghatároztuk a legközelebbi metszéspontot, ugyanis nekünk egy színre van szükségünk, amit megjeleníthetünk, nem egy helyvektorra. | ||
** Tesztelésképpen kipróbálhatod, hogy ha találsz metszéspontot, akkor mondjuk fehér színt rajzolsz ki, amúgy feketét. Ez egy ronda és unalmas eredményt ad, de legalább észre tudod venni, ha eddig valamit elrontottál. | ** Tesztelésképpen kipróbálhatod, hogy ha találsz metszéspontot, akkor mondjuk fehér színt rajzolsz ki, amúgy feketét. Ez egy ronda és unalmas eredményt ad, de legalább észre tudod venni, ha eddig valamit elrontottál. | ||
=== Megvilágítás === | === Megvilágítás === | ||
* A hihető, valóságosnak tűnő képek hatásának kb. 90%-át a megvilágítás adja. De ahhoz, hogy ilyeneket tudjuk renderelni előbb bele kell hatolnunk a fényforrások lelki világába, és egy kis fizikára és statisztikára lesz | * A hihető, valóságosnak tűnő képek hatásának kb. 90%-át a megvilágítás adja. De ahhoz, hogy ilyeneket tudjuk renderelni előbb bele kell hatolnunk a fényforrások lelki világába, és egy kis fizikára és statisztikára is szükségünk lesz. | ||
* A legegyszerűbb fényforrás, amit bevezethetünk, az a környezeti világítás. Ez a valóságban nem létezik, csak egy modell, azt hivatott utánozni, hogy nappal a tárgyaknak az a része sem teljesen fekete, amit közvetlenül nem világít meg egy fényforrás se. Ugyanis a tárgyakról a környezetében minden irányba verődik vissza fény, nem csak a szemünk irányába, és ez pl. egy szobába létrehoz egy nagyjából konstans, iránytól független háttérvilágítást. Ez a modell nagyon sok környezetben nem állja meg a helyét, pl nagy nyílt terepen, bár vannak technikák a hibáinak kiküszöbölésére, vagy helyettesítésére (SSAO, Hemisphere lighting, Light probes stb...). Ez kódban csak annyit fog jelenteni | * A legegyszerűbb fényforrás, amit bevezethetünk, az a környezeti világítás. Ez a valóságban nem létezik, csak egy modell, azt hivatott utánozni, hogy nappal a tárgyaknak az a része sem teljesen fekete, amit közvetlenül nem világít meg egy fényforrás se. Ugyanis a tárgyakról a környezetében minden irányba verődik vissza fény, nem csak a szemünk irányába, és ez pl. egy szobába létrehoz egy nagyjából konstans, iránytól független háttérvilágítást. Ez a modell nagyon sok környezetben nem állja meg a helyét, pl nagy nyílt terepen, bár vannak technikák a hibáinak kiküszöbölésére, vagy helyettesítésére (SSAO, Hemisphere lighting, Light probes stb...). Ez kódban csak annyit fog jelenteni a környezeti (ambiens) fényerőt változtatás nélkül hozzáadjuk az objektum színéhez. | ||
* Egy mások fontos fényforrás az irányfényforrás. Ilyen például a Nap. A Nap olyan távol van tőlünk, hogy a szobámon belül teljesen mindegy, hogy hol helyezkedik el egy objektum, a nap mindig ugyan olyan irányból és intenzitással világítja meg. Itt viszont már az iránynak fontos szerepe van. Egy megvilágított szobában az asztal teteje sokkal világosabb, mint az asztal alja. Hogy ezt meg tudjuk valósítani, egyszerű fizikára van szükségünk. Tegyük fel, hogy egy anyagra két azonos erősségű fénysugár esik, az egyik merőlegesen, a másik theta szögben. | * Egy mások fontos fényforrás az irányfényforrás. Ilyen például a Nap. A Nap olyan távol van tőlünk, hogy a szobámon belül teljesen mindegy, hogy hol helyezkedik el egy objektum, a nap mindig ugyan olyan irányból és intenzitással világítja meg. Itt viszont már az iránynak fontos szerepe van. Egy megvilágított szobában az asztal teteje sokkal világosabb, mint az asztal alja. Hogy ezt meg tudjuk valósítani, egyszerű fizikára van szükségünk. Tegyük fel, hogy egy anyagra két azonos erősségű fénysugár esik, az egyik merőlegesen, a másik theta szögben. | ||
** Így ha a merőlegesen eső sugár átmérője egységnyi, akkor a theta szögben eső sugár esetében az a felület amin ugyan annyi energia eloszlik sokkal nagyobb. | ** Így ha a merőlegesen eső sugár átmérője egységnyi, akkor a theta szögben eső sugár esetében az a felület amin ugyan annyi energia eloszlik sokkal nagyobb. Könnyen levezethető, hogy az egységnyi felületre eső energia (azaz a megvilágítás ereje) cos(theta)-val arányos. | ||
** A beesési szög kiszámításához szükségünk van a felületi normálra. Még jó, hogy korábban gondoltunk erre. A cos(theta) | ** A beesési szög kiszámításához szükségünk van a felületi normálra. Még jó, hogy korábban gondoltunk erre. A cos(theta) kiszámításának egy egyszerű módja a skaláris szorzat használata. Ugyanis definíció szerint u * v = |u| * |v| * cos(theta). | ||
De ha u-t és v-t úgy választjuk meg, hogy egységnyi hosszúak legyenek, akkor a skaláris szorzat a cos(theta)-t adja. Ha a cos(theta) negatív, akkor a test takarásban van, és az irányfény semmit nem befolyásol a színén. | *** De ha u-t és v-t úgy választjuk meg, hogy egységnyi hosszúak legyenek, akkor a skaláris szorzat a cos(theta)-t adja. Ha a cos(theta) negatív, akkor a test takarásban van, és az irányfény semmit nem befolyásol a színén. | ||
* Azokat az anyagokat, amiknek a színét csak ebből az összefüggésből ki lehet számolni, diffúz anyagoknak mondjuk. Ilyenek az a nem tükröző és a nem átlátszó anyagok, pl. a műanyagok nagy része. | * Azokat az anyagokat, amiknek a színét csak ebből az összefüggésből ki lehet számolni, diffúz anyagoknak mondjuk. Ilyenek az a nem tükröző és a nem átlátszó anyagok, pl. a műanyagok nagy része. | ||
* Ezt felhasználva: | * Ezt felhasználva: | ||