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

Rohamcsiga (vitalap | szerkesztései)
Rohamcsiga (vitalap | szerkesztései)
A spekuláris modellnél célszerűbb Blinn-Phongot használnom
1 099. sor: 1 099. sor:
De mit jelent az, hogy a "közelébe"? Mennyire a közelébe? És a normál közelébe mennyivel gyengébb ez a hatás, mint pont a normálban. A lapok irányát egy harang görbe jellemzi. Hogy megtudjuk, hogy abba az irányba a lapok hányadrésze néz, ami a visszatükröződésnek kedvez, be kell helyettesítenünk a normál eloszlás sűrűségfüggvényébe. A képlet nem bonyolult, de van benne egy exponenciális függvény, aminek kiszámítása lassú. Viszont skaláris szorzattal egy koszinuszt ki tudunk számolni, ami egy picit hasonlít a haranggörbére. Ha a koszinusznak vesszük egy polinomját, pl az a*cos(x)^b, azzal nagyon jól közelíteni lehet a haranggörbét.  
De mit jelent az, hogy a "közelébe"? Mennyire a közelébe? És a normál közelébe mennyivel gyengébb ez a hatás, mint pont a normálban. A lapok irányát egy harang görbe jellemzi. Hogy megtudjuk, hogy abba az irányba a lapok hányadrésze néz, ami a visszatükröződésnek kedvez, be kell helyettesítenünk a normál eloszlás sűrűségfüggvényébe. A képlet nem bonyolult, de van benne egy exponenciális függvény, aminek kiszámítása lassú. Viszont skaláris szorzattal egy koszinuszt ki tudunk számolni, ami egy picit hasonlít a haranggörbére. Ha a koszinusznak vesszük egy polinomját, pl az a*cos(x)^b, azzal nagyon jól közelíteni lehet a haranggörbét.  


Az egyik lehetőség, hogy a visszaverődési normál (a fényből a felületi pontba menő, és az abból a szemünk felé mutató egységvektorok átlaga) és a tényleges felületi normál által bezárt szög koszinuszát használjuk. Az előadáson ez szokott elhangozni, mert ez az egyszerűbb módszer, de én egy másik lehetőséget fogok implementálni, mert én azt jobban szeretem.
A leggyakoribb megoldás, a Blinn-Phong modell, a visszaverődési normál (a fényből a felületi pontba menő, és az abból a szemünk felé mutató egységvektorok átlaga) és a tényleges felületi normál által bezárt szög koszinuszát használja. A visszaverődési normál, vagy más nevén a félszög-vektor jele legyen 'H' (mint Half-angle), a normál pedig 'N'.  


Először is ki kell tudnunk számolni, hogy 'N' normálvektorral rendelkező tükör merre ver vissza egy beérkező 'I' sugarat. A visszavert sugarat jelöljük 'R'-el. Azt tudjuk, hogy a három vektor egy síkban van, és a beesési szög megegyezik a visszaverődési szöggel. De mégse így fogunk számolni, egyszerű vektor műveletekkel is ki lehet fejezni.
A koszinusz, amit használni akarunk a <code>dot(H, N)</code> képletből áll elő. A negatív érték nekünk nem jó, és ennek még kell vennünk egy polinómját, így végül a <code>specular_power = pow(max(dot(H, N), 0), shininess)</code> képletet kapjuk.
 
http://i.imgur.com/RsTWJVC.jpg
 
Próbáld a visszavert sugarat csak a négy alapművelet és a skaláris szorzás segítségével kifejezni.
 
A legegyszerűbb megoldás:
 
<br/> <syntaxhighlight lang="c">
inline Vector reflect(Vector I, Vector N) {
  return I - (2.0 * dot(N, I)) * N;
}
</syntaxhighlight> <br/>
 
Ezt felhasználva legyen 'R' (Reflected) legyen a visszaverődő fény iránya, 'V' (View) pedig a felületi pontból a szemünk felé mutató egységvektor. A haranggörbét közelíthetjük e két vektor által bezárt szög koszinuszával is: <code>dot(R, V)</code>. Persze a negatív értékek nekünk nem jók és ennek még a polinómját is kell vennünk.
 
A képlet így <code>specular_power = a * pow(max(0, dot(R, V)), shininess)</code>. Megjegyzés: az 'a' konstans elhagyható, az implicit benne lehet az anyagra jellemző spekuláris színben.


A spekuláris anyag egyben diffúz is. A spekuáris megcsillanás (specular_power * specular_color) hozzáadódik a diffúz megvilágításból származó színhez.
A spekuláris anyag egyben diffúz is. A spekuáris megcsillanás (specular_power * specular_color) hozzáadódik a diffúz megvilágításból származó színhez.
1 124. sor: 1 108. sor:
   
   
<br/> <syntaxhighlight lang="c">  
<br/> <syntaxhighlight lang="c">  
float specular_power =  
Vector L = light.dir.normalize(), V = (camera.pos-inter.pos).normalize();
  pow(
Vector H = (L + V).normalize(), N = inter.normal;
    max(0.0f, dot(
float specular_power = pow(max(dot(H, N), 0.0f), shininess);
      reflect(-light.dir.normalize(), inter.normal),
      (camera.pos-inter.pos).normalize())
    ), shininess
  );
accum_color += specular_power * light.color * specular_color;
accum_color += specular_power * light.color * specular_color;
</syntaxhighlight> <br/>
</syntaxhighlight> <br/>


Itt se feledkezzünk el az árnyékokról. Szerencsére az árnyékszámítás itt is teljesen ugyan az.
Itt se feledkezzünk el az árnyékokról. Szerencsére az árnyékszámítás itt is teljesen ugyan az, ezért célszerű a láthatóságot egy külön függvényben eldönteni.


A 'shininess' meghatározása teljesen mértékben hasra-ütésre, próbálgatással szokott menni. Én személy szerint a kettőhatvány shinnines értékekkel szoktam először próbálkozni (8 - 16 - 32 - 64 a leggyakoribb nálam), és utána esetleg "finom hangolom" az értéket, az alapján, hogy melyik éréték néz ki jól.
A 'shininess' meghatározása teljesen mértékben hasra-ütésre, próbálgatással szokott menni. Én személy szerint a kettőhatvány shinnines értékekkel szoktam először próbálkozni (8 - 16 - 32 - 64 a leggyakoribb nálam), és utána esetleg "finom hangolom" az értéket, az alapján, hogy melyik éréték néz ki jól.
1 142. sor: 1 122. sor:
Például: [[Média:Grafpp_raytrace_specular_highlights.cpp‎|Spekuláris megcsillanás egy kockán]]
Például: [[Média:Grafpp_raytrace_specular_highlights.cpp‎|Spekuláris megcsillanás egy kockán]]


http://i.imgur.com/me1hGMY.png
http://i.imgur.com/VBb5ODK.png


=== A tökéletes tükör ===
=== A tökéletes tükör ===
1 148. sor: 1 128. sor:
A mikroszkopikus tükrök figyelembevételével a fényforrások fénye tükröződni tud. De mi van a valódi tükrökkel? Amikben más objektumok képeit is látjuk, nem csak a fényforrások hatását? Sugárkövetéssel ilyen tükröket renderelni meglepően egyszerű. Az egyetlen dolog amit a tükör tulajdonságú anyag csinál a modellünkbe az az, hogy a tükröződés irányába továbblövi a sugarat.
A mikroszkopikus tükrök figyelembevételével a fényforrások fénye tükröződni tud. De mi van a valódi tükrökkel? Amikben más objektumok képeit is látjuk, nem csak a fényforrások hatását? Sugárkövetéssel ilyen tükröket renderelni meglepően egyszerű. Az egyetlen dolog amit a tükör tulajdonságú anyag csinál a modellünkbe az az, hogy a tükröződés irányába továbblövi a sugarat.


Implementálni ezt nagyon egyszerű, pl.:
Először is ki kell tudnunk számolni, hogy 'N' normálvektorral rendelkező tükör merre ver vissza egy beérkező 'I' sugarat. Azt tudjuk, hogy a három vektor egy síkban van, és a beesési szög megegyezik a visszaverődési szöggel. De mégse így fogunk számolni, egyszerű vektor műveletekkel is ki lehet fejezni.
 
http://i.imgur.com/RsTWJVC.jpg
 
Próbáld a visszavert sugarat csak a négy alapművelet és a skaláris szorzás segítségével kifejezni.
 
A legegyszerűbb megoldás:
 
<br/> <syntaxhighlight lang="c">
inline Vector reflect(Vector I, Vector N) {
  return I - (2.0 * dot(N, I)) * N;
}
</syntaxhighlight> <br/>
 
Ezt felhasználva a tükröződést implementálni már egyszerű, pl.:


<br/> <syntaxhighlight lang="c">  
<br/> <syntaxhighlight lang="c">