••••• Lineární texture-mapping ••••• Ve Výhni #2 jsem do rubriky programování zařadil článek o lineárním texture-mappingu se speciální optimalizací pro tzv. DOOMoidní případy, tedy kreslení podlah a stěn. Pokusím se tímto příspěvkem navázat na zmíněný článek a především ukázat poněkud složitější implementaci lineárního texture-mappingu pomocí Bresenhamova algoritmu, s jehož teoretickými a praktickými základy se můžete seznámit v Bulbově článku. Zároveň navazuji na gigantický Titaniův 3D tutorial z minulého čísla, kde se sice o mapování textur zmiňuje, ale jeho implementace není zrovna rychlá a prakticky nepoužitelná. Mapování textur je v porovnání s klasickými metodami vykreslování objektů poněkud časově náročnější. Optimalizací tohoto problému se už po dlouhou dobu zabývá řada počítačových grafiků. Bylo vyvinuto mnoho metod, které hledají kompromis mezi rychlostí a realističností. Jak možná tušíte, nejde jen o to nacpat určitý výřez z textury do vymezené oblasti na obrazovce, ale také je třeba uvažovat určité zkreslení, které způsobuje skutečné umístění polygonu v prostoru. Na počátku byl nejjednodušší přístup, a to zanedbání perspektivní podstaty mapovaného polygonu. Jedná se o nejrychlejší možný způsob, kterak pokrýt objekt texturou. Byl nazván: lineární texture-mapping. Vývoj šel samozřejmě dál a s nástupem výkonnějších procesorů přišla možnost perspektivní korekce v reálném čase. Nejpomalejší korekcí je přímá hyperbolická interpolace, která zajišťuje v podstatě reálný výstup, ale vyžaduje obecně jedno dělení na pixel, takže se používá pouze na strojích, které si podobné zatížení mohou dovolit. Další celoplošnou korekcí, kterou s úspěchem využívají mnohé grafické karty s hardwarovým mapováním textur nebo některé starší typy počítačů od firmy Silicon Graphics, je kvadratická interpolace. Využívá se toho, že funkce f(x):y=x² má v určitém intervalu podobný průběh jako funkce g(x):y=1/x. Nahrazením hyperboly parabolou tedy zaměníme dělení za násobení na jeden pixel, což znamená například pro platfomru Pentia až čtyřnásobné zrychlení. Zkreslení je opravdu minimální a proto je tato metoda asi nejlepší kompromis mezi rychlostí a realističností i pro velké texturované plochy. • původní vzorek: 1234567890987654321 \ | / \ | / \ | / \ | / | | | • lineární interpolace: 13579097531 | | | • hyperbolická interpolace: 15789085321 (příklad rozdílu hyperbolické a lineární interpolace) Jak to vypadá v praxi ? Ale stále to není ono. Nedovedu si představit Quaka s parabolickou korekcí, to by si nikdo nezahrál možná ani na MMX. Perspektivní korekce v Quakovi je mnohonásobně rychlejší a výsledky, které dává, jsou opravdu překvapivé. Jedná se o lineární interpolaci mezi perspektivně správnými body. Dělení se tedy provádí pouze občas a jak je vidět na Quakovi, stačí korekci aplikovat každý 16. vykreslovaný pixel. Korekce se sice provádí za účelem zvýšení realističnosti dojmu z namapovaného objektu, ale lidské oko a především mozek jsou v tomto ohledu poněkud shovívavější, než by se mohlo zdát (s podobným flákaním našeho zrakového smyslu se můžete setkat například při pozorování odrazu určitého objektu od zrcadlového předmětu nepravidelného tvaru). Hlavním důvodem, proč se korekce používá, je jasně viditelné klepání lineárně mapovaných textur. Je způsobené tím, že při vykreslování polygonů se textura chová tak, jakobychom ji mapovali na plošku, jejíž normálový vektor je s vektorem pohledu rovnoběžný. Pokud se změní poloha objektu, změní se i rozmístění a orientace jednotlivých plošek, ale textry se mapují stále do stejné roviny. Výsledkem této chyby je zřetelné posouvání textur, které se u velkých polygonů projevuje jako kdyby textura přes objekt tekla. Perspektivní korekce tento syndrom úspěšně eliminuje, a tak můžeme s klidem obdivovat zdánlivě perspektivně správný mapping v Quakovi, i když se pod tím vším vlastně skrývá, podobně jako při vynálezu filmu, optický klam. Ale vraťme se k nejjednodušší a zároveň k nerychlejší metodě texture-mappingu. Samotná podstata je jednoduchá. V elementárním případě máme určitý výřez textury a výřez na obrazovce. Oba dva jsou nadefinované pomocí tři souřadnic. Souřadnice X a Y u výřezu na obrazovce vznikly známou transformací z 3D do 2D: X Y X' = --- a Y' = --- Z Z Jsou to vpodstatě ony dva perspektivně správné body mezi něž budeme interpolovat výřez textury. Na tomto místě je dobré upřesnit, že použití lineárního texture-mappingu je na poměrně malé plošky (do celkové výšky 20 pixelů) velice efektivní. Některé systémy toho využívají, a tak pro vzdálenější polygony používají lineární mapování. Dále vyvstává problém implementovat co možná nejrychlejší interpolaci. Bresenhamův interpolační algoritmus je asi nejlepší volba, ale v dnešní době, kdy se podstatně mění intelovská filozofie instrukčního souboru a s nástupem MMX instrukcí je tento způsob paradoxně pomalejší než klasický DDA algoritmus. Vzhledem k tomu, že agónie Intelu, který se snaží udržet na trhu výrobou stále složitějších procesorů se stále rozsáhlejším instrukčním souborem, brzy skončí a všichni budeme muset přestoupit na architekturu zjednodušování a snižování počtu instrukcí (RISC). Podle mého názoru jedině ona má budoucnost v super-rychlých počítačích budoucnosti, a proto celočíselný Bresenhamův algoritmus jen tak nezestárne. Výpočetní základ už máme a nyní přecházíme k tomu hlavnímu, samotné interpolaci jednotlivých souřadnic. Celý proces můžeme rozdělit na dvě části. V té první provedeme interpolaci souřadnic X,U a V podle změny souřadnice Y. Představte si to, jako byste chtěli kreslit nevyplněný trojúhelník mezi bodu [X1,Y1], [X2,Y2] a [X3,Y3] na obrazovce a [U1,V1], [U2,V2] a [U3,V3] v textuře s tím, že mezi body v textuře se neinterpoluje pomocí souřadnice V, ale obě dvě souřadnice U a V se mění v závislosti na Y. • textura • • trojúhelník • [U1,V2] ,-----------, [U2,U2] . [X1,Y1] \* * * * */ /| \* * * */ /*| \* * */ --------> [X2,Y2] /**| \* */ o\**| \./ \*| [U3,U3] \| o [X3,Y3] Je důležité mít jednu řídící souřadnici, jelikož konečné vykreslování se provádí pouze po vodorovných Y řádkách. Nainterpolované hodnoty si uložíme do polí a přistoupíme k vykreslování jednotlivých řádek trojúhelníku. Na každé scan-line je zapotřebí interpolovat souřadnice v textuře, jelikož na rozdíl od Y řádky nemusí být výsledná scan-line v textuře vodorovná a stejně dlouhá jako scan-line na obrazovce. Celý proces opakujeme pro každou řádku trojúhelníku a výsledkem bude rovnoměrně vyplněná oblast zadaným výřezem textury, který bude patřičně zdeformován. Na závěr to hlavní. Přikládám ukázku implementace Bresenhamova algoritmu optimalizované na 8 různých smyček. Jedná se o 486 optimalizaci. Existuje samozřejmě i optimalizace pro Pentium, která využívá dublování instrukcí a faktu, že přístup do vždy stejného úseku paměti je v podstatě stejně rychlý, jako přístup k registrům procesoru. Dalším příspěvkem je samotná texturovací procedura, sloužící pro texturu velikosti 256x256 a pro grafický režim 320x200x256. Vykreslovací smyčka je taktéž v assembleru, její optimalizace není zrovna ďábelská, ale jako příklad postačí. Doufám, že princip lineárního texture-mappingu pochopíte a zkusíte si napsat vlastní texturovací rutinu. V budoucnu možná více rozvedu perspektivní korekci v kombinaci s lineárním mapováním a také navážu na komplexnější využití texture-mappingu při mapování celých objektů geniální metodou environment-mappingu. Bresenhamova interpolace v assembleru Procedure TextureFace ReDox výheň