Jak na textury

Ostatní jazyky Petr Lite 3D grafika Jak na textury

Dávno již je minulostí doba, kdy základem 3D grafiky byla vektorová grafika založená na různobarevných trojúhelníčcích. Bez textur je dnešní 3D grafika neodmyslitelná. Jak však textury správně používat?

Přestože jsou textury běžnými 2D obrázky, musíme je chápat trochu odlišně. Textura není jen obrázek, který se "někam" vykreslí. Jednotlivé grafické body textury jsou zdrojem barevné informace pro renderovací jednotku. Renderovací jednotka chápe texturu jako pole barevných komponent, do kterého nahlíží při každém vykreslovaném bodu. Nejdříve vypočítá pozici renderovaného bodu relativně k vrcholům trojúhelníku (s případnou perspektivní korekcí), tu přepočte na relativní souřadnici odpovídajícího bodu v textuře s využitím UV souřadnic. Proto u textur nepoužíváme označení pixely jako je tomu u 2D obrázků, ale jednotlivé grafické body označujeme texely.

UV souřadnice jsou souřadnice v textuře v daném vrcholu. Textura má v každém směru rozsah souřadnic 0.01.0, nezávisle na fyzickém rozměru textury. Souřadnice jsou počítány tak, jakoby textury byly uspořádány vedle sebe jako dlaždice. Tím je zajištěno opakování textur zadáním souřadnic mimo rozsah 0 až 1.

Texely se adresují jakoby to byly plošky o určitém rozměru. Například v textuře o rozměru 4 x 4 body mají jednotlivé texely rozměr 0.25 x 0.25. Při barvových kalkulacích se jako vztažný bod bere střed texelu.

Provádí-li se renderování textury s vypnutou filtrací textur, použije se v barvových kalkulacích hodnota nejbližšího texelu textury (na předchozím obrázku varianta grafu a) bez filtrace). Na následujících obrázcích vidíte vlevo případ s vypnutou filtrací textur, vpravo je filtrace textur zapnuta. V případě s vypnutou filtrací můžete pozorovat zobrazení samotných texelů textury.

Je-li filtrace textur zapnuta, interpolují se barevné informace mezi sousedními 2 body. Vnitřní body textury jsou jasné, co však krajní body? Zde je problém, neboť není známo, které sousední body použít při výpočtu barvy. Řeší to volba pro nastavení módu adresování textury. Implicitně se textura adresuje jako opakovaná (dlaždicové uspořádání). Je-li např. rozsah UV souřadnic mezi 2 vrcholy 0 až 2.0, textura se zopakuje 2x. Při opakování se okraje textur počítají tak, že se barva interpoluje mezi prvním a posledním texelem textury. To umožní hladké přechody mezi opakovanými texturami. Na předešlém grafu je to varianta c) opakování.

Mód opakování však může v některém případě způsobit komplikace. Na následujících 2 obrázcích vidíte případ použití textur při generování terénu pomocí dlaždic (čtverce). U levého obrázku je povoleno opakování textur. Jak je vidět, interpolací mezi prvním a posledním texelem textury vznikají na hranách dlaždice nepříjemné viditelné artefakty. Řešení vypnutím vyhlazení textur považujeme za nepřijatelné. Máme pro tyto případy další mód adresování textur, ořezání. Na grafech výše je to případ b) ořezání nebo dole je to obrázek vpravo. Okraje textur nejsou interpolovány, barva zůstává nezměněna od posledního známého texelu až po okraj textury. V módu ořezávání je textura vykreslována pouze v rozmezí souřadnic 0 až 1, vše ostatní mimo daný rozsah je ořezáno na okrajovou barvu.

Pokud to však bude možné, budeme se snažit vyhlazování opakováním používat. Jak vidíte na následujících 2 obrázcích, vlevo je zapnuto adresování ořezáním, vpravo adresování opakováním textur. Je zřejmé, že v módu ořezání nedojde k plynulému přechodu mezi okrajovými texely sousedních textur a objevují se viditelné zlomové přechody.

V předešlém případě jsme tento efekt brali jako menší zlo, raději než vznik okrajových artefaktů. I v takovém případě však můžeme najít kompromisní řešení. Připravíme textury tak, že řadu bodů z konců textur zkopírujeme i na začátky textur Samozřejmě myšleno pro stejná spojovací místa textur. Vytvoříme tím jakési navzájem kompatibilní spojovací konektory textur. Pak bude zajištěno, že první a poslední texely sousedních textur jsou vždy stejné a nedochází tak k přechodovým zlomům ani v případě ožezávání textur. Jak vidíte na následujícím obrázku, zlomy se ztratily. Budete-li i po této korekci pozorovat zlomy u vzdálených textur, zkuste zlepšit situaci vypnutím filtrace vzdálených textur nebo ještě lépe nastavením maximální úrovně vzdálených textur. Při úpravách textur pamatujte na zmenšování textur při vyhlazení textur. Např. použijete-li vyhlazení textur 2, musíte kopírovat 2 řady bodů. U Lite verze Petra jsou textury automaticky zmenšeny na maximální rozměr 128.

Uvedený případ filtrace textur se vztahoval především k případu zvětšení textury, kdy se 1 texel zobrazí jako několik grafických bodů na obrazovce. Nastavení filtrace určije přepínač filtrace zvětšených textur. Jiným podobným případem je zmenšení textur, kdy na jeden grafický bod na obrazovce připadá několik texelů. Tento typ filtrace je řízen přepínačem filtrace zmenšených textur. Při zmenšování textur se barva výsledného pixelu získá interpolací dvou nejbližších texelů, podobně jako při zvětšení, pouze v jiném měřítku.

Pokud bychom použili u velmi vzdálených (zmenšených) textur filtr pro zmenšení textur, uplatnily by se ve výsledném obraze vždy jen některé (nejbližší) dva texely, což by mělo za následek zrnitost a problikávání vzdálených objektů. V tomto případě se uplatní technika vzdálených textur, mipmaping. Mipmap textury jsou textury odvozené z původní textury postupným dělením velikosti na polovinu, až po velikost 1 x 1 bod.

Příklad: V programu máme připravenou texturu s rozměry 256 x 256 bodů, s průhledným pozadím. Je to obrázek v Petrovi, proto používá paletový režim 256 barev. Je zvoleno vyhlazení textur 2. Při generování textury se obrázek převede na TrueColor (32 bitů) a zmenší se na rozměr 128 x 128 bodů. Z průhledné barvy se odvodí alfa složka (tedy kanál průhlednosti). Díky tomu, že obrázek byl převeden do barev Petra s využitím ditheringu (což je metoda simulace RGB barvy smícháním několika 8-bitových barev - obrázek je při bližším pohledu tečkovaný), obrázek se po zmenšení na rozměr 128 x 128 velmi blíží TrueColor barvám. Z obrázku se postupně odvozují následující úrobně mipmap řetězce, až po rozměr 1 x 1 bod.

Při renderování textury vyhledá renderovací jednotka podle aktuálního měřítka zobrazení nejbližší mipmap texturu. Je-li zapnut filtr vzdálených textur, získá se výsledná barva interpolací mezi 2 nejbližšími mipmap texturami. Při vypnutém filtru se použije nejbližší mipmap textura. Úroveň rozhodování, která mipmap úroveň textur bude použita, můžeme řídit prvkem zjemnění vzdálených textur. Standardně má hodnotu 0. Hodnota prvku se přičítá k číslu použité úrovně mipmap textur. Nastavením na zápornou hodnotu (lze zadávat i desetinná čísla) se použije větší mipmap textura, obraz se více zaostří. Kladné číslo zajistí větší rozmazání vzdálených textur. Změna filtru o hodnotu 1 způsobí posun mipmap o 1 úroveň (tedy posun na dvojnásobnou nebo poloviční velikost mipmap textur).

Nakonec si popíšeme ještě jeden trik s texturami, bezešvé spojování textur. Dejme tomu, že chcete zobrazit velkou fotografii. Nemůžete použít jedinou texturu kvůli omezení velikosti textur (buď kvůli omezení Lite verze Petra nebo kvůli limitům grafické karty), musíte fotografii rozložit na několik menších částí (segmentů) a namapovat je na několik čtvercových dlaždic. Je samozřejmé, že nemůžete použít mód opakování textur, v místech spojů by se objevily čáry. V případě módu ořezávání textur se v místech spojů budou objevovat zlomové hrany v plynulosti vyhlazení textur. U fotografií nemůžete použít ani trik s opakováním první a poslední řady bodů.

Řešení spočívá v překryvech textur. Obrázek rozdělíme na segmenty sdílející jednu řadu bodů. Texturu každého segmentu namapujeme na plochu jako roztaženou o jeden texel, čili na každé straně bude přečnívat o půl texelu. Okrajové texely tak budou ležet na hranicích ploch a vnější problémová oblast texelů se vůbec nepoužije. To umožní hladké napojování textur bez vzniku artefaktů, dokonce nezávisle na zvoleném módu adresování. Na konci lekce naleznete ukázkový program využívající bezešvé spojování textur k zobrazení fotografií. Metodu si na něm blíže vysvětlíme.

V programu chceme zobrazit fotografie o koncovém rozměru 640 x 512. Budou součástí programu, proto budeme počítat s převodem z 8-bitový barev Petra a vyhlazením textur 2, čili fotografie budou mít v programu rozměr 1280 x 1024 bodů. Použijeme textury s koncovým rozměrem 128 x 128 bodů, což znamená 256 x 256 bodů v 8-bitových barvách. Jedna fotografie se bude skládat z 5 segmentů horizontálně (640 / 128 = 5) a 4 segmentů vertikálně (512 / 128).

Napojované segmenty budou sdílet 1 bod. Střední segmenty efektivně zobrazí 127 texelů, protože první a poslední texel se zobrazí jen do poloviny. U krajních segmentů se zobrazí vnitřní texely do poloviny, ale krajní se musí zobrazit celé. Krajní segmenty tedy zobrazí 127,5 texelů. Když tyto hodnoty sečteme zjistíme, že se z obrázku efektivně zobrazí 636 bodů na šířku a 509 bodů na výšku. Nestalo by se moc kdybychom nadbytečné body z obrázku jen ignorovali, ale protože chceme ukázkově porovnávat metody, obsahuje program obrázky už připravené v korigovaném rozměru 1272 x 1018 bodů.

Rozsekávání obrázku na segmenty se provádí programově, vykreslením segmentu do grafické plochy a sejmutím segmentu do textury. Jeden segment má rozměr 256 bodů, ale okno segmentů je přitom v obrázku posouváno po 254 bodech (kvůli zmenšení textury se nesdílí 1 bod ale 2), čímž se zajistí sdílení bodů mezi segmenty. Zastavíme se podrobněji u horizontálních výpočetních operací pro střední segment, jako příklad.

Obsah proměnné měřítko X mapování textury se použije v příkazu mapování textury pro jeden segment. Nastavením měřítka mapování na zlomek 127/128 se zajistí, že textura se roztáhne přesně o 1 texel (šířka textury po konverzi je 128 bodů). Roztáhnutí se provádí kolem středu, takže se textura roztáhne na každou stranu o 1/2 texelu. U středních segmentů zůstává střed mapování na souřadnici 0.5, což je střed textury. U okrajových textur se nastavuje šířka mapování na hodnotu 127.5/128 (tedy 127 a půl texelu). Je třeba zobrazit krajní texel celý, proto je nutné posunou střed mapování o 1/4 texelu, tedy o hodnotu 0.25/128.

Rozměry segmentů nastavujeme relativně vzhledem k celé skupině (tj. aby výsledný rozměr obrazu měl hodnotu 1). Vnitřní segmenty zobrazují 127 texelů, proto jejich šířka bude (vzhledem k celkové šířce obrázku) 127/636. Šířka krajních segmentů je 127.5/636. Levou hraniční souřadnicí obrazu je hodnota 0.5. Střed prvního segmentu je posunut o 1/2 šířky od levého okraje, proto souřadnice X levého segmentu je (127.5/636)/2 - 0.5. Souřadnice X každého dalšího (vnitřního) segmentu je odsazena od levého okraje o celou šířku prvního segmentu (tj. 127.5/636), o šířky předešlých vnitřních segmentů (každý je široký 127/636) a o polovinu šířky tohoto segmentu.

Na následujících snímcích můžete porovnat účinnost metody. Vlevo je detail obrázku zobrazeného pomocí běžných nepřekryvných segmentů (u segmentů je nastaven mód ořezávání textur), vpravo je zobrazení s využitím bezešvého spojování textur. Budete-li program zkoušet, jsou rozdíly nejvýraznější u obrázku číslo 3, pokud se k němu více přiblížíte. Obzvláště je tato metoda úspěšně využitelná při zobrazení textů, kde se používají textury s malým rozlišením a přechody mezi texturami bývají častým problémem.


 

Stáhnout

Staženo 238x (6.65 MB)
Aplikace je včetně zdrojových kódů v jazyce Petr Lite (jsou obsaženy v EXE souboru, který lze v programu přímo otevřít)

 

  Aktivity (1)

Článek pro vás napsal Panda38
Avatar
Programátor C++, WinAPI, ASM.

Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!


 


Miniatura
Předchozí článek
Lovíme minotaury (6. část, lov)
Miniatura
Všechny články v sekci
3D grafika
Miniatura
Následující článek
Vytváříme textury - 2D objekty

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!