11. Speciális megjelenítési módszerek, hatások

A sugárkövetés a fény modellezésével a valósághű megjelenítés számos problémáját megoldja. Hasonlóképpen, fizikai szimulációs rendszert is készíthetünk a virtuális terünkhöz. A probléma ezekkel, hogy nagyon számításigényesek, ezért általában valamilyen helyettesítő megoldást használunk. A következőkben néhány jellegzetes effektusnak a modellezési lehetőségeit tekintjük át.

Égbolt modellezése

  • Skybox

  • Skydome

\(\rhd\) Hogyan kerülhető el az, hogy az égbolt közepén összegyűrődjön a textúra?

\(\rhd\) A félgömbös modell esetében egy felületi ponthoz hogyan számítható ki a normálvektor?

Domborzat modellezése

A domborzat modellezéséhez egy gyakori megközelítés, hogy ismerjük a felület bizonyos pontjait (jellemzően négyzetrácson), majd a közbülső pontokat azok alapján határozzuk meg.

  • Tulajdonképpen a \(z = f(x, y)\) formában írjuk le a felületet.

\(\rhd\) Hogyan érdemes tárolni, szerkeszteni a magasságértékeket?

\(\rhd\) Hogyan becsülhető egy tetszőleges \((x, y)\) pontban a \(z\) értéke?

\(\rhd\) Hogyan becsülhetők a normálvektorok?

Árnyékok

Az OpenGL (általunk aktuálisan használt változata) az árnyékokat nem kezeli.

Folt

Az alakzatunk alá megjeleníthetünk egy (például kör alakú) foltot, ami az objektummal együtt mozog.

  • Előnye, hogy egyszerűen megoldható, és mégis ad hozzá valamennyit a megjelenítés minőségéhez.

  • Hátránya, hogy főként csak sík felületeken, egy irányba vetítve működik, és nem túl valószerű.

Leképzett modell

A megjelenített alakzatunkat skálázással síkba lapíthatjuk. Sötét színnel megjelenítve árnyék hatását keltheti.

  • Előnye, hogy az árnyék alakja igazodik a megjelenített alakzathoz. Az implementációja aránylag egyszerű.

  • Hátránya, hogy szintén csak leszűkített esetben működik. A számítási ideje gyakorlatilag megegyezik a modell megjelenítési idejével.

\(\rhd\) Nézzük meg a shadow példát!

Előrenderelt textúra

  • Előnye, hogy jó minőségű árnyékokat tudunk így kapni, amely megjelenítése nem rontja a futási időt.

  • Hátránya, hogy az árnyékok statikusak. A kivitelezése jellemzően sugárkövetéses módszerekkel történhet. Az árnyékok előrenderelése sok ideig tarthat. Az előrenderelt textúrákat tárolni kell.

\(\rhd\) Milyen megoldandó problémák merülnek fel az előrenderelés során?

Sugárkövetés

  • Előnye, hogy az árnyékok valószerűek tudnak lenni.

  • Hátránya, hogy számításigényes.

Tükrök

Az árnyékhoz hasonlóan a modell ismételt kirajzolásával oldható meg aránylag egyszerűen.

  • Félig átlátszó felületeket érdemes hozzá használni.

  • A fény pozícióját is tükrözni kell.

  • A mélységbuffer kezelésére külön figyelni kell.

\(\rhd\) Nézzük meg a mirror példát!

Kollekciók kezelése

Az alkalmazásokban gyakran szükség lehet arra, hogy egy elemből tetszőleges sokat letároljunk. Ezt valamilyen dinamikus tároló használatával célszerű megoldani. Erre a C programozási nyelv közvetlenül nem ad megoldást.

Maximalizált méretű tömb

#define MAX_ARRAY_SIZE

typedef struct Array {
  Item items[MAX_ARRAY_SIZE];
  int n_items;
} Array;
  • Beszúrás esetén az n_items értékét növelni kell.

  • Figyelni kell, hogy ne lépjük túl a MAX_ARRAY_SIZE értéket.

  • Az elem törlésénél az n_items értékét csökkenteni kell, és az elemek mozgatására is szükség lehet.

Dinamikusan átméretezhető tömb

typedef struct Array {
  Item* items;
  int n_items;
} Array;

create_array(Array* array, int size);
append_to_array(Array* array, const Item* item);
remove_from_array(Array* array, int index);
destroy_array(Array* array);
  • A tömb mérete a beszúrásokat, törléseket végrehajtva változhat.

\(\rhd\) Milyen heurisztikákat használhatunk az allokált (items) tömb méretének meghatározásához?

Láncolt lista

typedef struct Node {
  const Item* item
  struct Node* next;
} Node;

typedef struct List {
  Node* head;
} List;

create_list(List* list);
append_to_list(List* list, const Item* item);
remove_from_list(List* list, int index);
destroy_list(List* list);

\(\rhd\) Milyen további kollekció típusok szoktak még előfordulni?

\(\rhd\) Hogyan lehet ezeket implementálni C-ben?

Nyomvonal modellezése

Tegyük fel, hogy meg szeretnénk jeleníteni a virtuális terünkben, hogy merrefelé jártunk.

\(\rhd\) Nézzük meg a footprints példát!

Részecskerendszerek

Egyszerűbb esetben tekinthetünk egy részecskére úgy, mint egy pontra, amelynek van sebessége

typedef struct Particle {
  vec3 position;
  vec3 velocity;
} Particle;

A következőkben néhány példát láthatunk részecskerendszerek segítségével megvalósított effektekre.

Eső, hóesés modellezése

  • A részecskéket adott magasságból indíthatjuk, úgy hogy azok szabadon essenek.

  • Az esés során különféle módosítókat is alkalmazhatunk (például, hogy a hópelyhek szálingózzanak).

Robbanás

Egy adott pontból véletlenszerűen választott sebességekkel tudjuk például modellezni.

\(\rhd\) Nézzük meg a explosion példát!

Tűz, füst

Változatos lehetőségek vannak a modellezési módjára.

Animált textúra

  • Képsorozatként megjeleníthetjük egy alakzat textúráján.

  • Általában félig átlátszó textúrákat szoktak hozzá használni.

  • Gyakran egymással szöget bezáró sík felületekként jelenítik meg (például merőleges, vagy 60 fokos szögben).

Modellek sorozata

  • A tűz alakját meg lehet próbálni modellezni, majd időközönként váltogatni.

  • Ez gyakorlatilag a képsorozat térbeli változata.

Változó színű részecskék

Egy további lehetőség például, hogy a részecskék színét időben változtatjuk, például a fehér, sárga, piros és fekete színátmenetekkel.

  • Tegyük fel, hogy egy láng élettartama 3 másodperc!

  • Hasson a részecskékre egy erőhatás, amelyik \(z = 1\) irányba mozgatja a részecskét!

  • Amint egy részecske kihűlt, indítsuk újra az origóból!

#define N_FLAMES

typedef struct Flame {
  vec3 position;
  vec3 velocity;
  double lifetime
} Flame;

typedef struct Fire {
  Flame flames[N_FLAMES];
} Fire;

\(\rhd\) Nézzük meg a fire példát!

\(\rhd\) Hogyan tudnánk megoldani azt, hogy a láng teteje összefelé tartson?

\(\rhd\) Milyen fényhatásokat lehet érdemes beállítani a tűz közepéhez?

Cella alapú hőáramlás szimuláció

A tűz megjelenítéséhez készíthetünk egyszerű áramlási, hőterjedési modellt.

  • Meg kell határozni egy rögzített, raszteres felbontást. Ez praktikusan egy négyzetrács pontjait jelenti, amelyhez az intenzitásokat egy mátrixban tárolunk.

  • Definiálhatunk egy szabályrendszert, ami alapján az aktuális intenzitások alapján kiszámítjuk a következő iterációhoz tartozó intenzitásokat.

  • Hogy ha a rácsfelosztás miatt az eredmény túlságosan szögletes lenne, akkor alkalmazhatunk valamilyen interpolációt. (Textúrázás esetében ezt az OpenGL megoldja helyettünk.)

\(\rhd\) Nézzük meg a fire.html példát!

Víz, folyadékok

Állóvíz modellezése

  • Egy félig átlátszó textúra használatával megoldható.

  • A textúrát mozgatva érdekesebbé tehető az összkép.

Hullámzás modellezése

A víz felszínét modellezhetjük, mint magasságmezőt.

Folyadék áramlása

Raszteres rácsfelbontást alkalmazva szimulálhatjuk, hogy azokban mennyi a folyadék mennyisége.