. . . . . , . . . . . •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ň