„Számítógépes grafika házi feladat tutorial” változatai közötti eltérés

Rohamcsiga (vitalap | szerkesztései)
aNincs szerkesztési összefoglaló
Rohamcsiga (vitalap | szerkesztései)
Hozzáadtam a 'Koordináta rendszerek' részt
265. sor: 265. sor:
</div>
</div>


==Projekciós mátrixok, transzformációk==
== A második házihoz szükséges elmélet ==
 
=== Koordináta rendszerek ===
* Az első háziba valószínűleg feltűnt, hogy a pontok NDC (normalizált eszköz koordináta) megadása nem túl kényelmes, még akkor se ha, a világnak mindig ugyan azt a részét nézzük. De mit tegyük akkor, ha a képzeletbeli kamera amivel "lefényképezzük" a jelenetet mozoghat, sőt akár még forghat is.
* Az OpenGL kitalálónak az ötlete az volt erre, hogy a kamera mindig maradjon egyhelyben, de ha pl. balra akarnánk forgatni, akkor helyette inkább a világ forogjon jobbra, a kamera maradj ugyanott, és ezzel ugyan azt a hatást érjük el. Persze nem kell minden egyes pontot nekünk elforgatni, ezt rábízhatjuk az OpenGL-re is, hogy mindig mielőtt rajzolna, azelőtt végezzen el valamilyen transzformációt a pontokat amiket kapott.
** A lineáris (és affin) transzformációkat a legkényelmesebb a mátrixuk segítségével tudjuk megadni, több egymás utáni transzformáció pedig egyszerűen a mátrixok szorzatát jelenti. Viszont fontos megjegyezni, hogy 3D-ben az eltolás nem lineáris transzformáció, és nem is lehet mátrixal felírni. Ennek kiküszöbölésére használhatunk 4D-be w = 1 koordinátával beágyazott 3D-s koordináta rendszert, ahol az eltolás is egy lineáris trafó.
** Az OpenGL két mátrixot ad nekünk, amiknek módosíthatunk, és amivel az összes kirajzolandó pontot mindig beszorozza helyettünk. Az egyik a GL_MODELVIEW, a másik a GL_PROJECTION. A GL_MODELVIEW-val mozgathatunk objektumokat egymáshoz képest, és itt tudjuk megadni, hogy hogyan kell transzformálni a világot, hogy az origóban lévő, -z irányba néző képzeletbeli azt lássa, amit meg akarunk jeleníteni. A GL_PROJECTION pedig azt adja meg, hogy a kamerával hogyan kell fényképzni.
*** Két dimezióban a két mátrix különválasztása gyakorlatilag fölösleges, ennek csak 3D-be lesz szerepe, majd a megvilágításkor. 2D-ben a kényelmesebb a GL_PROJECTION-ra bízni a kamera mozgatást is, és a GL_MODELVIEW-t pedig meghagyni csak az objektumok közötti transzformációk leírására.
* Projekció 2D-ben: a fényképezés módja nagyon egyszerű, egyszerűen eldobjuk a 'z' koordinátát, és az x-y pozició alapján rajzolunk. Vagy legalábbis ezt csináltuk eddig, de az NDC nem volt kényelmes. Itt viszont lehetőséget kapunk saját koordinátarendszer megválasztására, ahol az egység lehet pl. 1 méter, és a kamera pedig mondjuk követhet egy karaktert egy játékban.
 
* Példaprogram: [http://pastebin.com/zV32Zg1f Sidescroller]
 
<br/> <syntaxhighlight lang="c">
// Megmondjuk a OpenGL-nek, hogy ezután a projekciós mátrixot
// akarjuk módosítani a transzformációs mátrix műveletekkel.
glMatrixMode(GL_PROJECTION);
// Egység mátrixot töltük be a jelenlegi vetítési mátrix helyére.
glLoadIdentity();
// Ez egy olyan merőleges (Orthogonális) vetítés, aminek eredménye képpen a karakter
// az x tengely mentén középen lesz, és 10 egység (méter) széles részt látunk a világból
// míg az y tengely mentén a képernyő alsó egy ötödében lesz, és itt is 10 egység magas
// részt látunk.
gluOrtho2D(
  stickman.pos.x - 5, stickman.pos.x + 5,
  stickman.pos.y - 2, stickman.pos.y + 8
);
</syntaxhighlight> <br/>
 
Az eredménye:
<div style="text-align:left;margin:0px auto;">
http://i.imgur.com/6WgP4iC.gif
</div>
 
== Régi wikiről áthozott rész, frissitésre szorul ==
=== Projekciós mátrixok, transzformációk ===


* Az OpenGL a megjelenítő csővezetékben két transzformációs mátrixot használ, ezek a ModelView és a Projection mátrixok. A keretrendszer nem módosítható részében mindkét mátrixba az egység mátrixot töltik a glLoadIdentity() függvény segítségével. Ez alkotja a már említett 2D orthogonális vetítést (-1,+1) méretű koordináta-rendszerben.
* Az OpenGL a megjelenítő csővezetékben két transzformációs mátrixot használ, ezek a ModelView és a Projection mátrixok. A keretrendszer nem módosítható részében mindkét mátrixba az egység mátrixot töltik a glLoadIdentity() függvény segítségével. Ez alkotja a már említett 2D orthogonális vetítést (-1,+1) méretű koordináta-rendszerben.
324. sor: 358. sor:
</pre>
</pre>


==Görbék==
=== Görbék ===
* A görbékről igen sok anyag található a könyvben, diákon, még itt a wiki-n is, így csak néhány hasznos tippet és programozás-technikai dolgot írok itt le
* A görbékről igen sok anyag található a könyvben, diákon, még itt a wiki-n is, így csak néhány hasznos tippet és programozás-technikai dolgot írok itt le
* A görbe egy elvont matematikai fogalom, a kirajzoláskor nem használjuk! A görbéket vektorizáljuk (vonalakra bontjuk), és ezeket a törött-vonalakat rajzoltatjuk ki az openGL segítségével.
* A görbe egy elvont matematikai fogalom, a kirajzoláskor nem használjuk! A görbéket vektorizáljuk (vonalakra bontjuk), és ezeket a törött-vonalakat rajzoltatjuk ki az openGL segítségével.
331. sor: 365. sor:
* A görbék kontrollpontjainak megadása nem egyszerű, a rajzolás és a tesztelés egyszerűbbé tehető, ha a görbénket egy másik program segítségével "megtervezzük". Ilyen Java-applet-eket könnyen találhatunk az Interneten, elég rákeresni a "<görbenév> applet" kifejezésre, és máris grafikus felületen kattingathatjuk össze a görbénket.
* A görbék kontrollpontjainak megadása nem egyszerű, a rajzolás és a tesztelés egyszerűbbé tehető, ha a görbénket egy másik program segítségével "megtervezzük". Ilyen Java-applet-eket könnyen találhatunk az Interneten, elég rákeresni a "<görbenév> applet" kifejezésre, és máris grafikus felületen kattingathatjuk össze a görbénket.


==Időzítés, animáció==
=== Időzítés, animáció ===
* Az animáció kezelésére és az újrarajzolás elhelyezésére (a Gordiuson történő hibás működések miatt) sokféle megoldás született. Én a szerintem leglogikusabb elrendezést írom itt le, amely garantáltan működik otthon és a Gordiuson is. Az animáció elve a következő:
* Az animáció kezelésére és az újrarajzolás elhelyezésére (a Gordiuson történő hibás működések miatt) sokféle megoldás született. Én a szerintem leglogikusabb elrendezést írom itt le, amely garantáltan működik otthon és a Gordiuson is. Az animáció elve a következő:
** Létezik a világ modellje, gyakorlatilag a globális változóink. Azért globálisak, hogy elérhetőek legyenek a különböző GLUT függvényekből. A modellt csak az események, azaz az onKeyboard, onMouse és onIdle függvények módosíthatják.
** Létezik a világ modellje, gyakorlatilag a globális változóink. Azért globálisak, hogy elérhetőek legyenek a különböző GLUT függvényekből. A modellt csak az események, azaz az onKeyboard, onMouse és onIdle függvények módosíthatják.
365. sor: 399. sor:
*** Pontosan ezt csinálja az fmod függvény is: lebegőpontos osztás maradékát adja vissza. Így fmod(6.8, 2.0) = 0.8.
*** Pontosan ezt csinálja az fmod függvény is: lebegőpontos osztás maradékát adja vissza. Így fmod(6.8, 2.0) = 0.8.


==Tesszelláció==
=== Tesszelláció ===
* A tesszelláció a világban található objektumok felbontása háromszögekre. Hogy miért van erre szükség? Mert az openGL csak vonalakat és háromszögeket képes kirajzolni, minden test ezekből épül fel.
* A tesszelláció a világban található objektumok felbontása háromszögekre. Hogy miért van erre szükség? Mert az openGL csak vonalakat és háromszögeket képes kirajzolni, minden test ezekből épül fel.
* '''2D házik'''
* '''2D házik'''
377. sor: 411. sor:
** TODO: tipikus testek
** TODO: tipikus testek


==Sugárkövetés==
=== Sugárkövetés ===
* A sugárkövetés házinak nem sok köze van az openGL-hez, inkább sok 3D-s koordináta-geometria és némi fizika szükséges hozzá.
* A sugárkövetés házinak nem sok köze van az openGL-hez, inkább sok 3D-s koordináta-geometria és némi fizika szükséges hozzá.
* A sugárkövetés nagy hátránya, hogy mivel mi írjuk a "renderelő motort", így igen nehéz a tesztelés és debuggolás, hiszen egy apró hiba miatt is előfordulhat hogy a képen semmit sem látunk. Könnyítsük meg a saját dolgunkat azzal, hogy egy papírra lerajzoljuk a testek elhelyezkedését, többször is ellenőrizzük a tengelyek irányát. Ha sehogy nem azt látjuk amit szeretnénk, írjuk ki a változóink értékét a konzolra, és úgymond szövegesen teszteljük a programot.
* A sugárkövetés nagy hátránya, hogy mivel mi írjuk a "renderelő motort", így igen nehéz a tesztelés és debuggolás, hiszen egy apró hiba miatt is előfordulhat hogy a képen semmit sem látunk. Könnyítsük meg a saját dolgunkat azzal, hogy egy papírra lerajzoljuk a testek elhelyezkedését, többször is ellenőrizzük a tengelyek irányát. Ha sehogy nem azt látjuk amit szeretnénk, írjuk ki a változóink értékét a konzolra, és úgymond szövegesen teszteljük a programot.


===OpenGL rész===
==== OpenGL rész ====
* Sugárkövetésnél OpenGL függvényt csak a kész kép kirajzolásához használunk, a következő módon:
* Sugárkövetésnél OpenGL függvényt csak a kész kép kirajzolásához használunk, a következő módon:
<pre>
<pre>
393. sor: 427. sor:
* A 600*600 pixel nem véletlen, a keretben ez az ablak fixen megadott mérete.
* A 600*600 pixel nem véletlen, a keretben ez az ablak fixen megadott mérete.


===Osztályok===
==== Osztályok ====
* Megkönnyítjük a saját dolgunkat, ha az alábbi osztályokat létrehozzuk, és azokhoz megfelelő operátorokat készítünk:
* Megkönnyítjük a saját dolgunkat, ha az alábbi osztályokat létrehozzuk, és azokhoz megfelelő operátorokat készítünk:
** '''Vector/Coordinate/Point'''
** '''Vector/Coordinate/Point'''
408. sor: 442. sor:
** '''Mesh''' - háromszögekből álló test, mely egy közös metszéspont kereső függvényt definiál, az összes háromszög metszéspontjai közül azt adja vissza, amelyiknek legkisebb a távolsága (de még pozitív), tehát amit legelőször talál el a sugár.
** '''Mesh''' - háromszögekből álló test, mely egy közös metszéspont kereső függvényt definiál, az összes háromszög metszéspontjai közül azt adja vissza, amelyiknek legkisebb a távolsága (de még pozitív), tehát amit legelőször talál el a sugár.


===Metszéspontok, önárnyékolás és az EPSILON===
==== Metszéspontok, önárnyékolás és az EPSILON ====
<div id="AnchorOnarnyekolas"></div>
<div id="AnchorOnarnyekolas"></div>
* TODO
* TODO


===Sugár indítások, egy és kétirányú sugárkövetés===
==== Sugár indítások, egy és kétirányú sugárkövetés ====
* TODO: egy/kétirányú: ...
* TODO: egy/kétirányú: ...
* Az indítandó sugarak létrehozásához nekünk kell definiálnunk a perspektivikus kamerát, hasonlóan ahhoz, ahogy az openGL 3D perspektivikus leképzését definiáljuk: TODO: ...
* Az indítandó sugarak létrehozásához nekünk kell definiálnunk a perspektivikus kamerát, hasonlóan ahhoz, ahogy az openGL 3D perspektivikus leképzését definiáljuk: TODO: ...


===Színek, fények, optikai modellek===
==== Színek, fények, optikai modellek ====
<div id="AnchorToneMap"></div>
<div id="AnchorToneMap"></div>
* Tone Map
* Tone Map
425. sor: 459. sor:
*** Egyik fontos eleme, hogy figyelembe veszi a három színkomponens fényességének eltérését, és a következő kísérleti alapon megállapított intenzitásképletet használja: ''Y = 0.2126 R + 0.7152 G + 0.0722 B''
*** Egyik fontos eleme, hogy figyelembe veszi a három színkomponens fényességének eltérését, és a következő kísérleti alapon megállapított intenzitásképletet használja: ''Y = 0.2126 R + 0.7152 G + 0.0722 B''


==3D alapok==
=== 3D alapok ===
<div id="AnchorZFighting"></div>  
<div id="AnchorZFighting"></div>  
* TODO: kamera, Z-buffer VS. clipping pane, árnyalás VS. normálvektorok, glut tesszellátorok
* TODO: kamera, Z-buffer VS. clipping pane, árnyalás VS. normálvektorok, glut tesszellátorok




==3D extrák==
=== 3D extrák ===
* TODO: fények, csillanás, textúrázás
* TODO: fények, csillanás, textúrázás


== Hibakezelés ==  
=== Hibakezelés ===  


-- [[BlackGhost|BlackGhost]] - 2011.04.05.
-- [[BlackGhost|BlackGhost]] - 2011.04.05.