Ray Tracing: Objekty

V reálnom svete môžme v prenesenom význame chápať svetlo ako zväzok lúčov, ktoré dopadajú na sietnicu oka a tým vidíme objekty okolo seba. Týmto spôsobom to funguje aj v ray tracingu v tom duchu a zmysle, že každý viditeľný objekt je zobraziteľný jedine priesečníkom s okolitým prostredím. Žiadnym iným spôsobom nie je možné dané objekty vidieť na obrazovke. Aj keď budeme zobrazovať objekty v priestore, nebude sa jednať o tzv. polygónový mesh, ktorým je možné zobraziť akýkoľvek objekt z reálneho sveta. (obrázok od Wikipedia.org)

ddd

Ako vidieť na obrázku, objekt sa skladá zo svojej najmenšej časti, trojuhoľníka. Týmto spôsobom sme schopný vymodelovať akýkoľvek objekt (nejakým externým editorom, napr. 3D Studio MAX), uložiť ho do súboru a následne prepočítať danú scénu v programe, ktorý ponúka vykresľovanie prostredníctvom metódy sledovania lúčov. Principiálne to funguje podobne v tom zmysle, že počítame priesečníky s daným polygónom a keďže sa jedná o trojuhoľník, tak každý trojuhoľník bude mať svoj normálový vektor, ktorým danú plochu zobrazíme.

Pre naše účely nám bude postačovať zo začiatku objekt gule. Guľová plocha patrí do kategórie tzv. kvadratických útvarov, kde patrí aj napr. elipsoid, hyperboloid a podobne. Teda je možné ich v analytickej geometrii popísať kvadratickými rovnicami. (obrázok od Wikipedia.org)

gulasss

Guľovú plochu je všeobecne možné vyjadriť nasledujúcim výrazom:

\(x^2+y^2+z^2-R^2=0\)

Polomer R sa zvykne prehadzovať na ľavú stranu s tým, aby daná rovnica sa rovnala nule. Takéto vyjadrenie sa nazýva tzv. implicitné vyjadrenie rovnice guľovej plochy.

Do takejto rovnice zavedieme stred guľovej plochy, aby sme boli schopný definovať stred a polomer priamo v rovnici. Teda, gula so stredom \(c = (c_x, c_y, c_z)\) (c, center) a polomerom R (R, radius) bude reprezentovaná nasledujúcou implicitnou rovnicou v tvare:

\((x-s_x)^2+(y-s_y)^2+(z-s_z)^2 – R^2=0\)

Touto rovnicou sme schopný zadefinovať stred gule s polomerom a pracovať s guľou ako s plným objektom v 3D priestore (euklidovskom priestore).

Problém je v tom, že v predošlých častiach sme si definovali vektorový systém. Práve tento systém nám umožní v budúcnosti počítať rôzne fyzikálne deje alebo skôr optické javy. Ako už bolo spomínané, tieto javy by teoreticky bolo možné počítať numericky len pomocou odvodených vzorcov. Lenže z hľadiska náročnosti takéhoto počítania je výhodnejšie použiť vektorový počet. Najmä vtedy, ak pôjde o zložitejšie postupy. Takže z toho dôvodu definujeme stred S ako vektor \vec{c}:

\(\vec{c} = (s_x, s_y, s_z)\)

Ostáva nám ešte zadefinovať bod x, y, z ako vektor p (p, point):

\(\vec{p} = (x, y, z)\)

Teraz môžme prepísať pôvodnú rovnicu guľovej plochy do nasledujúceho vektorového tvaru:

\((\vec{p} – \vec{c}).(\vec{p} – \vec{c}) -R^2= 0\)

Výrazy v zátvorkách sú násobené skalárnym súčinom (nie klasické násobenie), ktorý sme už definovali v predošlých článkoch, teda:

\(\vec{u}.\vec{v} = u_0 v_0 + u_1 v_1 + u_2 v_2\)

Pre naše účely:

\(\vec{p}.\vec{c} = p_0 c_0 + c_1 v_1 + c_2 v_2\)

Z hľadiska implementácie, sme si definovali skalárny súčin takto:

A presne v tomto zápise už priamo napíšeme výsledok pre guľovú plochu:

\(dot((\vec{p} – \vec{c}), (\vec{p} – \vec{c})) = R*R\)

Táto rovnica znamená, že každý bod p, ktorý vyhovuje tejto rovnici sa nachádza na guľovej ploche. Takto sme mohli veľmi rýchlo prekonvertovať analytický zápis priamo do programového kódu.

My potrebujeme vedieť, kedy lúč pretne guľovú plochu v nejakom priesečníku. Teda potrebujeme vedieť, kedy lúč v parametrickom tvare

\(p(t) = A + tB\)

pretne guľovú plochu pre nejaký parameter t, ktorý aj naďalej vyhovuje našej rovnici guľovej plochy. Takže môžme vyjadriť guľovú plochu s naším parametrickým lúčom.

\(dot((\vec{A}+t*\vec{B} – \vec{c}), (\vec{A}+t*\vec{B} – \vec{c})) = R*R\)

A teraz z tohto tvaru potrebujeme odvodiť parameter t ako určitý „priesečníkový parameter“. To znamená, že danú rovnicu roznásobíme a postupne odvodíme paramter t. Aby sa nám ľahšie odvodzovalo, tak skalárny súčin v podobe dot funkcie vynecháme a na konci po odvodení ho pridáme:

\(\vec{A}^2 + \vec{A}t\vec{B} – \vec{A}\vec{c} + \vec{A}t\vec{B} + t^2\vec{B}^2 – \vec{c}t\vec{B} – \vec{c}\vec{A} – \vec{c}t\vec{B} + \vec{c}^2 – R^2 = 0\)
\(t^2(\vec{B}\vec{B}) + 2\vec{B}(\vec{A}-\vec{c})t + \vec{A}^2 – \vec{A}\vec{c} – \vec{A}\vec{c} + \vec{c}^2 – R^2 = 0\)
\(t^2(\vec{B}\vec{B}) + 2\vec{B}(\vec{A}-\vec{c})t + (\vec{A}-\vec{c})(\vec{A}-\vec{c}) – R^2 = 0\)

A na záver dosadíme funkciu dot():

\(t*t*dot(\vec{B}, \vec{B}) + 2*t*dot(\vec{B},\vec{A}-\vec{c}) + dot(\vec{A}-\vec{c}, \vec{A}-\vec{c}) – R*R = 0\)

Tento tvar vyhovuje kvadratickej rovnici \(At^2+Bt+C=0\), pričom z tejto rovnice je možné zistiť pomocou diskriminantu

\(D = B^2 – 4AC\)

počet priesečníkov lúča s guľovou plochou. Pre kladný parameter t dostaneme dva priesečníky, pre záporný parameter nedostaneme žiadne priesečníky a pre nulový parameter dostaneme práve jeden priesečník. (obrázok od ScratchPixel)

rrrazzz

Týmto spôsobom zistíme počet priesečníkov lúča s guľovou plochou a v mieste ich priesečníku necháme zobraziť určitú farbu. Z hľadiska implementácie to bude vyzerať nasledovne:

Každú jednu zložku sme prepísali presne podľa odvodených vzorcov. Následne zmeníme funkciu pre výpočet farieb:

Definovali sme podmienku pre nájdenie priesečníka funkciou hit_sphere(), kde pri pravdivom vyhodnotení vrátime zelenú farbu a pri nepravdivom vyhodnotení vrátime pôvodnú farbu pozadia. Súradnica gule bude pre \(z=-1\), pretože začiatok generovania lúčov je v bode \((0,0,0)\). Principiálne by sme mali dostať rovnaký obraz aj pre \(z=1\), pretože vzdialenosť od stredu je symetrická, teda dostaneme zrkadlový obraz.

r00

Týmto nám v podstate lúče vygenerujú obraz pomocou priesečníkov s objektom. V skutočnosti sa nejedná o objekty v pravom slova zmysle. To znamená, že

Z uvedených rovníc je ďalej možné priamo napísať rovnicu normálového vektoru, ktorý bude slúžiť najmä na výpočet osvetlenia. Takže, ak budeme potrebovať zobraziť tieňe, odrazy a rôzne druhy svetelných zdrojov, tak budeme potrebovať práve normálové vektory. Táto problematika bude predmetom budúcich článkov.

You may also like...