.
.
.
.
.
, . . . . .
•M•A•P•P•i•N•G•
V roce 1995 nám na poli demoscény z ničeho nic vyrostly
brambory, kedlubny a pneumatiky všeho druhu. Některé byly kostrbaté,
jiné zase pěkně zaoblené a ty nejlepší skoro fotorealistické. Prostě
radost pohledět. Některým z nás se při pohledu na opravdu pěkné
exempláře začaly sbíhat sliny a nejradši bychom prezentovanou
digitální zeleninu zkonzumovali jen tak nasyrovo. Mezi lačné slintaly
jsem se počítal i já a při pohledu na dema jako Stars /Nooon, Dope
/Complex, Solsitce /Vallhala, Zweilight zone /Capacala či Disgust
/Cammora jsem jen nevěřícně kroutil hlavou. To, co ultra-rychlým
raytracerům na mém stroji trvalo celé hodiny, se tu náhle
prezentovalo s rychlostí 24 snímků za sekundu. Obrovské objekty
krásně a téměř realisticky vyvedené v Phongově stínování, odrazy
okolního prostředí včetně pohybujících se objektů, světelné efektíky
připomínající železo, zlato či diamant nebo prostorové textury
(bump-mapping), to všechno mi tak učarovalo, že jsem se začal pídit
po oné magické metodě, která tyto zázraky vytvořila. Všude se
objevovaly hlášky jako: "And now comming ENV torus", "ENV-mapping
rulez" nebo "environmet forever." Trvalo mi ještě dlouho, než jsem
sehnal potřebné informace k tomu, abych onu geniální metodu
"environment mapping" pochopil a naprogramoval. Jak tomu obyčejně
bývá, vše geniální je vlastně úplně jednoduché. Pokud pochopíte její
princip, pak se vám všechny zmíněné efekty propojí do jednoho celku
a zjistíte, že to všechno je vlastně úplně triviální záležitost a že
demo jako např. Solstice může nakódovat i průměrný programátor.
Jak to všechno vlastně vzniklo? Pokud jste se už někdy dívali
do nějakých materiálů zabývajících se Phongovým stínováním, tak jste
asi našli, co to vlastně ten pan N. H. Phong vymyslel. Jeho myšlenky
se opírají o jednoduchou teorii, která říká, že pokud se světlo od
námi pozorovaného objektu odrazí tak, že jeho paprsek bude rovnoběžný
s vektorem pohledu našeho oka, bude naše sítnice absorbovat jeho
intenzitu maximálně. Ve skutečnosti je to ovšem nesmysl, ale musíme
si uvědomit, že se jedná o empirickou metodu, jejímž úkolem není
přesně popsat chování světla při srážce s objektem (tím se zabývá
například raytracing nebo radiosita), ale jednoduše aproximovat tento
jev do takové podoby, která by v konečném výsledku dávala téměř reál.
výsledek. Takovéto uvažování je základem celkové optimalizace
jakéhokoli problému, který má být simulován na počítači. Implementace
Phongova modelu je sice jednoduchá, ale na poměry našich pomalých PC
stále moc časově náročná. Žádá si totiž, abychom počítali orientaci
pseudo-normálového vektoru v každém bodě objektu. Možná se to zdá
jako nic, ale v praxi poznáte, že to vyžaduje alespoň jednu odmocninu
na pixel, což už je myslím směrodatné. Jisté ulehčení vykoumal pan
Gouraud, který počítá pseudo-normálu pouze v bodech definujících
elementární plošky, z nichž je objekt sestaven. Výslednou intenzitu
jakéhokoli bodu potom zjistí pomocí lineární interpolace zadaných
intenzit. Jeho vylepšovák je časově velice příznivý, ale má jednu
vadu na kráse. Nikdy totiž nedocílíte efektu, kterému se říká odborně
"hot-spot", tedy onoho odlesku v oblých částech objektu. Někoho
chytrého ale jednoho dne napadlo, že propojí obě metody dohromady
a vytvoří tak metodu novou, která svojí genialitou převyšuje myšlenky
obou vědců.
Jak vypadá intenzita v závislosti na odklonění pseudo-nomály ?
Podstata environment mappingu je následující: stejně jako pan
Gouraud si vypočítám pseudo-normálové vektory v jednotlivých bodech
objektu. Gouraud si z těchto vektorů vzal hodnoty Z a ty zadefinoval
jako intenzity. My si vezmeme zbylé hodnoty X a Y. Co s nimi? No asi
vás napadne, že pomocí dvou čísílek X a Y (aby se to v praxi nepletlo
používá se označení U a V) si můžeme zobrazit na papíře nějaký 2D
bod. Když máme tyto 2D body tři (předpokládám, že pod elementární
ploškou si všichni vybavíte trojúhelník), můžeme si nakreslit
trojúhelník, tak, že je prostě a jednoduše spojíme úsečkami. Výsledný
obrazec nám vymezuje na papíře určitou oblast. Co nám brání, abychom
tuto oblast jednoduše nanesli na elementární plošku, kterou chceme
právě vykreslit. Prostě naneseme texturu. Texturovat už umíme, takže
není problém to vyzkoušet. Akorát ten papír se tady nehodí. Místo něj
zkusíme vzít třeba nějaký obrázek. A co má tento obrázek představovat
? Cokoli. Záleží na situaci a efektu, kterého chceme dosáhnout. Když
si do něj předpočítáme například světelný kužel, bude výsledný objekt
vypadat jako kdybychom použili Phongovo stínování. Nebo můžeme vzít
třeba nějaký obrázek přírodní krajiny. Výsledkem je úchvatný odraz
krajiny na objektu. Celý efekt vypadá jako bychom se dívali od
obrázku na objekt, který má 100% odrazovou schopnost. A můžeme
kombinovat dál. Místo jednoduchého mapování budeme brát hodnoty z
této envirnoment textury pouze jako intenzitu a pomocí předem
předpočítané tabulky korigovat světlost pixelů zrovna mapované
materiálové textury, tím dosáhneme texture-mappingu s Phongovým
stínováním. Dalším způsobem využití je napočítat scénu do envirnoment
textury, a tu jednoduše namapovat na cílový objekt. Dosáhneme tak
odrazu okolního prostředí. Po tomto efektu byla také tato maximálně
variabilní metoda pojmenována a při renderingu ji využívá například
3D Studio. Jak vidíte, fantazii se meze nekladou a tato geniální
metoda lze použít opravdu všude, kde vás to jen napadne. Pokud ale
stále tápate a nedokážete si její podstatu vybavit, mám pro vás
připraven pár jednoduchých vztahů a ukázku výpočtu pseudo-normálových
vektorů v bodech objektu, které tvoří matematický základ celé metody:
Klasická envirnoment textura
Výpočet normálového vektoru elementární plošky (face):
.[x1,y1,z1]
/|
/ |
/ |
[x2,y2,z2], |
\ |
\ |
\|
o[x3,y3,z3]
N(x) = (y2-y1)(z3-z1) - (y3-y1)(z2-z1) ,
N(y) = (z2-z1)(x3-x1) - (z3-z1)(x2-x1) ,
N(z) = (x2-x1)(y3-y1) - (x3-x1)(y2-y1) .
Výpočet pseudo-normálového vektoru bodu (vertex) v závislosti na
okolních ploškách, jimž tento bod definuje jeden vrchol:
+ +
pN(x) = | N[a](x) + N[b](x) + N[c](x) + ... + N[n](x) | / N ,
+ +
+ +
pN(y) = | N[a](y) + N[b](y) + N[c](y) + ... + N[n](y) | / N ,
+ +
+ +
pN(z) = | N[a](z) + N[b](z) + N[c](z) + ... + N[n](z) | / N ,
+ +
kde a,b,c,...,n jsou indexy vybraných plošek, které splňují výše
uvedené kriterium a N je jeich celkový počet.
Jak vypadá takový pseudo-normálový vektor v praxi ?
Normalizace pseudo-normálového vektoru:
pN(x) * Kx
U[i] = npN(x) = -------------------------------- ,
√ [ pN(x) + pN(y) + pN(z) ]
pN(y) * Ky
V[i] = npN(y) = -------------------------------- ,
√ [ pN(x) + pN(y) + pN(z) ]
pN(z) * Kz
W[i] = npN(z) = -------------------------------- ,
√ [ pN(x) + pN(y) + pN(z) ]
kde Kx, Ky, Kz jsou konstanty určující střed env-textury, tedy místo
s největší intenzitou. Vzhledem k tomu, že textura je pouze
dvourozměrná, nemá smysl počítat npN(z), ale tato hodnota se může
hodit při implementaci bump-mappingu. Napočítáme si pro každý vertex
objektu jeho pseudo-normály a kdykoli objekt rotujeme musíme rotovat
i jeho pseudo-normály. Při vykreslování postupujeme klasickým
způsobem. Narotujeme vertexy, napočítáme jejich perspektivu a
seřadíme plošky podle velikosti, eliminujeme neviditilené části a
pomocí malířova algoritmu vykreslujeme jednotlivé trojúhleníčky tak,
že souřadnicím bodů v textuře, kterými vymezujeme mapovaný výřez
budeme přiřazovat hodnoty z polí U a V.
Na závěr ukázka, jak na to v praxi. Vzhledem k tomu, že jsem
přestoupil na GNU-C, rád bych ji prezentoval v jazyce C, ale není
problém si ji přepsat do Pascalu. Jednotlivé názvy proměnných jsou
voleny tak, že není problém určit jejich totožnost a datový typ.
void calc_pn()
ReDox
výheň