Prohlášení o autorství

Prohlašuji, že tato práce je mým původním autorským dílem, které jsem vypracoval samostatně. Všechny zdroje, prameny a literaturu, které jsem při vypracování používal nebo z nich čerpal, v práci řádně cituji s uvedením úplného odkazu na příslušný zdroj.

Vedoucí práce: Mgr. Jiří Chmelík, Ph.D. Poděkování

Chtěl bych tímto způsobem poděkovat Mgr. Jiřímu Chmelíkovi, Ph.D. za to, že v dobách hledání, strádání a nejistoty nejen, že odhodlaně přijal pozici garanta této práce, ale hlavně plně projevil svou benevolenci a shovívavost týkající se mého přístupu v průběhu celého procesu. Dále bych chtěl poděkovat MgA. Heleně Lukášové v pozici konzultanta za její nadšení a optimismus, ale i za hlas, který mne neustále motivoval k tomu, abych všechny tyto a veškeré následující řádky doopravdy sepsal. První kapitolu bych jen těžko koncipoval nebýt serveru www.root.cz a jeho seriálu Historie vývoje počítačových her, který výtečně zdokumentoval nejdůležitější milníky herního průmyslu a nesmírně mi pomohl nastínit a představit vývoj vlasů u her vytvořených během sedmdesátých a osmdesátých let. Bc. Rudolfu Burdovi patří zvláštní dík za poskytnutí své scény při převodu do herního enginu Unreal Engine 4 a následné kontrole možného poklesu výkonu během vykreslování v reálném čase. V neposlední řadě bych chtěl poděkovat svým rodičům, svým relativně silným nervům a vlastně i všem svatým za to, že jsem se vůbec narodil, zvládl vyrůst po téměř všech stránkách s důstojností sobě vlastní a dokázal se relativně ve zdraví dožít tohoto vzácného okamžiku. Shrnutí

Tato práce analyzuje historii a moderní principy tvorby a následného vykreslování vousů, vlasů a účesů v počítačových hrách a přináší nový postup využívající bodových a polygonových modifikátorů. Text práce popisuje návrh a dokumentuje implementaci mé metody, jejíž výsledek je kvalitativně i kvantitativně srovnán vůči hlavním postavám deseti známých a komerčně či cenově úspěšných her posledních let.

Klíčová slova

model, modelování, vlasy, vousy, displacement, shader, Blender, 3D, digitální hry Obsah

1 Úvod...... 5 2 Historie technik vykreslování vlasů...... 6 2.1 Pixelové zobrazení/pixelizace...... 6 2.2 Kresebné zobrazení...... 8 2.3 3D hry druhého tisíciletí...... 9 2.4 Texturové zobrazení...... 10 2.5 Polygonové zpracování a rozšíření texturového zobrazení...... 12 2.6 Alpha blend/test/to coverage...... 13 2.7 Marschnerova metoda...... 14 2.8 Sadeghiho/Disney metoda...... 15 2.9 NVIDIA HairWorks a přiblížení hair strands...... 16 2.10 DirectX 12 a Tress FX 3.0/NVIDIA HairWorks...... 17 3 Návrh a implementace vlastní metody...... 18 3.1 Vlas v reálném světě...... 18 3.2 Tvorba pramenů vlasů...... 19 3.2.1 Displacement...... 20 3.2.2 Subdivision Surface...... 22 3.2.3 Curve...... 23 3.2.4 Decimate...... 23 3.2.5 Souhrn...... 24 3.3 Pokožka...... 27 3.4 Složení materiálu...... 28 3.4.1 Průhlednost a průsvitnost...... 28 3.4.2 Barevnost...... 29 3.4.3 Ovlivnění v závislosti na textuře...... 29 3.4.4 Kombinace a doladění...... 31 4 Převod do reálného času...... 33 4.1 Unreal Engine 4...... 33 4.2 Export objektů...... 34 4.3 Import a stavba materiálů...... 34 4.4 Srovnání a test FPS...... 36 4.5 Aproximace Cycles materiálů...... 38 5 Kvalitativní a kvantitativní srovnání...... 40 5.1 Základní přehled...... 40 5.2 Výběr deseti nejlepších her...... 41 5.2.1 Deus Ex: Human Revolution...... 42 5.2.2 The Last of Us...... 43 5.2.3 GTA V...... 44 5.2.4 Ryse: Son of Rome...... 45 5.2.5 Herní série Metal Gear...... 46 5.2.6 : Inquisition...... 48 5.2.7 The Order: 1886...... 49 5.2.8 Final Fantasy XV...... 50 5.2.9 Star Citizen...... 51 5.3 Anketa...... 52 6 Závěr ...... 53 6.1 Na začátku cesty...... 53 1 Úvod

Vlasy, potažmo chlupy a srst, byly z hlediska evolučního dříve jedním z nejpodstatnějších termoregulačních faktorů udržujících tělesnou teplotu jedince v mezích životnosti. Postupem času svou prvotní funkci ztratily, nicméně se staly důležitou součástí estetického či psychologického vnímání osob. Jak v podrobně zaznamenané historii, tak i dnes dokáží určit společenské postavení, náboženské či politické přesvědčení, psychickou vyrovnanost i labilitu. Každým dnem vizuálně reflektují a dotvářejí naši osobnost. I v mnohých počítačových hrách máme často možnost upravit vzhled a charakter ovladatelných postav. Standartem moderních titulů jsou velmi bohaté možnosti úprav – formování tvaru postavy a jednotlivých částí obličeje, výběr barvy očí, tvar a pozice jizev a tetování či nastavení barvy a kvality pokožky. Nicméně v oblasti vizualizace a výběru vlasů a účesů jsme stále velmi limitováni. Před samotným zpracováním studie a související bakalářské práce jsem osobně mezi svými přáteli z herní komunity provedl neoficiální průzkum, abych zjistil, co je podle nich z vizuálního hlediska při tvorbě postav nejslabším článkem. Nejčastější odpovědi se týkaly především zpracování vlasů a s tím spojených herních účesů. Jedním z hlavních nedostatků je dle dotázaných hráčů omezená volnost při výběru účesů. Během provádění průzkumu jsem si uvědomil, že nevhodné či zastaralé zpracování vlasů v počítačových hrách může být jedním ze skrytých problémů, který není dostatečně adresován, důsledkem čehož nedochází k potřebnému a žádoucímu pokroku grafického zpracování počítačových her. Z výsledků také vyplynulo, že hráči by byli pro větší volnost, případně jistou formu nezávislosti při tvorbě účesů pro své postavy i za cenu větší časové i výpočetní náročnosti. Proto jsem se v této práci rozhodl danou problematikou zabývat. Kapitola 2 zrekapituluje historii vlasů v počítačových hrách včetně metod, které se v daných desetiletích používaly; následně přejdeme k technikám moderním, přičemž nastíníme jejich možné výhody, nevýhody a jejich budoucí potenciální využití. Ve třetí kapitole představím svůj vlastní postup tvorby vlasů, kde vysvětlím teorii, na jejichž základech je vybudován a čím se od moderních technologií liší. Protože byl tento postup vytvořen pomocí modifikátorů a deformátorů modelovacího prostředí Blender, součástí práce je dokumentace změn programem užívaného oficiálního open source kódu, která vysvětluje přínos k úpravě výstupu a nachází se v příloze D. Výsledný model bude následně převeden do volně dostupného herního enginu Unreal Engine 4 pro ověření použitelnosti v reálném čase, což je popsáno ve čtvrté kapitole. Pátá kapitola předkládá anketu sloužící k porovnání vizualice vlasů pomocí popsané metody vůči zpracování vlasů v deseti úspěšných nebo po grafické stránce inovativních či zapamatováníhodných moderních hrách v závislosti zároveň na dosaženém vzhledu i polygonální náročnosti. Závěr zhodnotí úspěšnost zpracování na základě zmíněné ankety, potvrdí či vyvrátí tezi ohledně využitelnosti metody v reálném čase a nastíní nutné budoucí úpravy ve vytvořeném prototypu.

5 2 Historie technik vykreslování vlasů

2.1 Pixelové zobrazení/pixelizace

Přestože vznik počítačových her lze datovat k přelomu čtyřicátých a padesátých let (ať se jedná o rok 1948, kdy Thomas T. Goldsmith Jr. a Estle Ray Mann vytvořili první hru využívající katodových trubic [1], nebo o rok 1952, kdy Alexander S. Douglas pomocí počítače EDSAC [2] vytvořil hratelné piškvorky OXO [p1] ovladatelné ciferníkem známým z bakelitových telefonů), vlasy se u ovladatelných postav objevují až v první polovině osmdesátých let u produktů pro herní konzoli Atari 2600 [p2]. Ta jako první využívala mikroprocesory, konkrétně modifikovaný osmibitový MOS 6502 [p3], díky jehož revolučně nízké ceně (25 dolarů za kus místo až 300 dolarů za kus v případě mikroprocesoru Motorola MC6800 [p4]) mohla být distribuována za relativně nízké a přijatelné ceny. Jako jeden z důležitých milníků herní historie je považován rok 1982, kdy na světlo světa přichází hra Pitfall! [p5] společnosti Activision. Je to jedna z prvních her, kde je hráč viděn z boku, přičemž se pohybuje jak horizontálně, tak vertikálně, a jako taková nastavuje styl zobrazení a možnosti pohybu pro mnoho her následujících dekád, jelikož de facto utváří žánr plošinovek. Díky upravenému vykreslovacímu enginu bylo možné zobrazovat více barev v reálném čase, což umožnilo vykreslit nejen komplexnější pozadí, ale i vícebarevného hráče. Ten měl kromě zelených kalhot, modrého trika a růžové kůže také hnědé vlasy. Protože se jedná o jednu z prvních her užívajících vícebarevného hráče (ne-li první) a protože je těžko dohledatelné, že by existovala starší, leč zapomenutá hra podobného ražení, je Pitfall! považován za první hru, ve které se objevuje postava s rozpoznatelnými vlasy. Poté, co společnost Atari světu předvedla skutečný potenciál herních konzolí, začalo se jejich vývojem intenzivněji zabývat více firem. Zatímco některé z nich postrádaly komerční úspěch (např. Magnavox Odyssey2 [p6]) a jiné se vydaly svým na danou dobu specifickým a revolučním směrem (osmibitová konzole Vectrex [p7] se zabudovaným vektorovým displejem), konzolím osmdesátých let dominovaly krom Atari firmy a Sega. Obě firmy v roce 1983 uvedly na trh vlastní konzoli (shodou okolností s rozdílem hodin), konkrétně Sega Game 1000 (SG-1000) [p8] a Nintendo Entertainment System (NES) [p9]. NES byla komerčně úspěšnější a dodnes je považována za nejúspěšnější osmibitovou herní konzoli v historii. Díky tomu pro ni byl vytvořen nespočet her, z nichž se mnohé pro herní komunitu staly nepřekonatelnými legendami. Jednou z takových legend je i herní série Donkey Kong [p10]. Přestože (případně právě proto, že) první hra vznikla v roce 1981 jako klasická arkáda, svůj největší úspěch zažila po přeportování na NES. Název může být poněkud zavádějící - na rozdíl od jiných her pojmenovaných po hlavních hrdinech nese tato jméno hlavního antagonisty. Hratelnou postavou je zde Jumpman, malý kníratý muž v červených montérkách a kšiltovce, relativně záhy znám jako Mario. Dodnes se vedou spory o tom, zda je Jumpman skutečně Mario či spíše jeho nepojmenovaný příbuzný (nejpravděpodobněji otec), faktem však zůstává, že roku 1983 získává Mario vlastní hru (Mario Bros.) a roku 1985 svou ikonickou vizáž v pokračování Super Mario Bros. [p11]. Nejen, že se prostřednictvím této hry Mario stal vlajkovou lodí společnosti Nintendo, díky mnohem vyššímu rozlišení postavy také posunul laťku vykreslování rozeznatelných účesů a vousů. Nicméně forma vykreslení vlasů se od úspěchu hry Pitfall! v průběhu osmdesátých let již nezměnila. Protože samotné účesy jsou tvořeny shluky několika barevných pixelů, lze tuto metodu nazvat vykreslováním pixelovým, případně pixelizací. Jedná se o nejstarší metodu kresby herních vlasů, která vznikla v dobách, kdy detaily, vyhlazování obrazu, vrstvy průhlednosti či odlesky nebyly v reálném čase technicky proveditelné.

6 Obrázek 2.1: Hlavní hrdina hry Pitfall! [p12].

Obrázek 2.2: Donkey Kong a první Mario [p13].

7 Obrázek 2.3: Mario ve hře Super Mario Bros 2 [p13].

2.2 Kresebné zobrazení

Díky stále se zdokonalujícím technologiím mohly hry využívat většího rozlišení a lepšího vykreslování, což může být asi nejlépe doložitelné oficiálním maskotem konkurenční společnosti Sega, superrychlým ježkem Sonicem. Ten se na herních obrazovkách poprvé objevil 23. června 1991 v 16-bitové verzi a 25. října téhož roku v 8-bitové verzi hry Sonic the Hedgehog [p14]. Sonic má na rozdíl od Maria vyhlazenější hrany, jasně nadefinovaný tvar štětin a viditelné stínování srsti. Přestože jde také o hru v dvourozměrném prostředí, po grafické stránce je mnohem sofistikovanější a zdařile vytváří iluzi třetího rozměru.

Obrázek 2.4: Ukázka ze hry Sonic the Hedgehog [p15].

8 S příchodem stolních počítačů a CD-ROMů schopných zálohovat data v řádech megabajtů přichází další grafická revoluce v podobě kreslených 2D her (zejména adventur), které svůj největší úspěch zažily převážně ve druhé polovině devadesátých let. Jedním z nejznámějších představitelů je třetí díl jedné z nejúspěšnějších herních sérií Monkey Island – The Curse of Monkey Island [p16] vydaný roku 1997. Ten využil moderních technologií a dodal hře oproti předchozím dílům zcela nový vizuál, který po mnoha stránkách připomínal moderní komiksy a kreslené televizní seriály (tzv. Cartoons). Nejen tato hra, ale i její grafické pojetí se staly duchovními otci mnoha her následujících let, ne-li desetiletí, z těch českých například série Polda [p17] či Horké léto [p18]. Jedná se o hry založené na dvourozměrném zobrazení prostoru, kde je na rozdíl od her trojrozměrných pozadí vůči poloze hráče statické. Scény lze přirovnat k interaktivním obrazům, postavy jsou ve většině případů zpracovány obdobným vizuálem, jejich animace je řešena posloupností snímků zobrazujících potřebný pohyb. Vlasy jsou tvořeny formou kresby a oproti pixelovému vykreslování je touto metodou dosaženo velmi detailního zobrazení, které díky několikanásobně obsáhlejší barevné paletě umožňuje definovat stíny, odstíny i přechody na úrovni jednotlivých pramínků.

Obrázek 2.5: Ukázka ze hry The Curse of Monkey Island [p19].

2.3 3D hry druhého tisíciletí

U trojrozměrných her samozřejmě také docházelo k pokrokům, ale zcela logicky se hledělo spíše na výkon než na vizuální zpracování. Zatímco u dvourozměrných her byla většina scény statická či jasně definovaná (přemisťování pixelových sloupců o určitý parametr u posuvných her), takže k výpočtům ohledně překreslování docházelo převážně u postav během jejich pohybu, třetí herní rozměr přidával výpočetní komplexitu také ve změně pohledu postav a vnímání bezprostřed- ního prostoru v závislosti na ovládání hráče. Perspektivní vykreslování není triviální záležitostí, o to časově náročnější bylo v dobách, kdy grafické karty a procesory nebyly tak rychlé a sofistikované jako dnes. Z toho důvodu docházelo k nutným kompromisům na úkor vykreslení a proto všechny trojrozměrné hry vypadaly oproti dvourozměrným protějškům téže doby relativně zastarale. Dokázaly to však výborně kompenzovat svou hratelností, která, ač místy hektická, byla v mnoha případech téměř návyková. Klasickým příkladem jsou legendy FPS her Wolfenstein 3D (1992), Doom (1993) a Duke Nukem 3D (1996) či RPG série Might and Magic. Obrázek 2.6 názorně zobrazuje pro tehdejší hry klasické vykreslování trojrozměrných prostředí v kombinaci s dvou-

9 rozměrnými předrenderovanými postavami na pozicích, kde v závislosti na jejich či hráčově akci byla přehrána předem určená animace. Díky tomu se z hlediska vykreslování vlasů používaly stejné postupy jako u dvourozměrných her (pixelový, potažmo kresebný).

Obrázek 2.6: Ukázka ze hry Duke Nukem 3D [p20].

2.4 Texturové zobrazení

Teprve kolem roku 2000 se začínají objevovat první skutečně trojrozměrné postavy. Ty sice tvůrcům přidělávaly další problémy ve formě animací při pohybu a otáčení, nicméně z hlediska výpočetního díky stálému rapidnímu pokroku nedocházelo k nepříjemným a nepřiměřeným prodlevám. Bylo to zapříčiněno také tím, že kromě konstantního vývoje u stolních počítačů došlo také k revolučnímu skoku u herních konzolí, který reprezentovala především Sony PlayStation 2, která stejného roku nahradila PlayStation 1 z roku 1994 a zaplnila tak šestiletou mezeru v oblasti konzolových výpočetních technologií. Nejstaršími a nejklasičtějšími herními příklady dané doby jsou například revoluční Metal Gear Solid (1998) či Deus Ex (2000). Obzvlášť Metal Gear Solid je znám tím, že vyšel už před rokem 2000 ještě na PlayStation 1, čímž předběhl dobu vzestupu 3D postav po vydaní PlayStation 2. Nutno podotknout, že za sérií MGS stojí , známý především svým revolučním a nekonvenčním přístupem, díky kterému dokázal již v minulosti vytvářet nové herní trendy, a využíváním výpočetně levných metod dosahujících bezchybného technického i vizuálního zpracování, o kterém více v podkapitole 5.2.5 Herní série Metal Gear. Herní postavy dané doby se vyznačují svým nízkým polygonovým (low-poly) zpracováním. Během následujících tří let se začaly objevovat první polygonově bohaté (high-poly) postavy (například Vietcong z roku 2003), přičemž u většiny kvalitních her s nízkou polygonovou kvalitou lze téměř vždy jednoznačně určit, že byly vyrobeny přibližně v letech 2000 - 2003 s tolerancí maximálně dvou let. Důvod, proč je tato informace v práci zmíněna, je ten, že právě low-poly kvalita postav nastavila trend pro tvorbu vlasů minimálně na dalších deset let (základní koncept je užíván dodnes). Hlava i vlasy jsou součástí jednoho sošného modelu (v prvních fázích bylo celé tělo uceleným modelem, ale postupem času se herní vývoj postav dopracoval do podoby oddělené hlavy a těla pro různě detailní formy vykreslování a také pro snazší animaci hlavy v závislosti na pohybu myši/ovladače), na který byla aplikována textura obličeje a účesu (v praxi to znamená, že textura vlasů byla součástí textury hlavy). Tento postup lze sledovat prakticky celé desetiletí nezávisle na komplexitě provedení postav u komerčně úspěšných i kritiky oceněných herních titulů, z nej-

10 známějších viz Mafia (2002), výše zmíněný Vietcong (2003), Far Cry (2004), God of War (2005), Call of Duty 4: Modern Warfare (2007), Fallout 3 (2008), Borderlands (2009) nebo Assassin's Creed: Brotherhood (2010). Všechny tyto hry byly ve své době známy tím, že jako AAA produkty (označení pro špičkové tituly) posunuly hranice herního vizuálu na zcela novou a doposud nepřekonanou úroveň, přesto tvorba vlasů v tomhle ohledu zůstala téměř nepozměněna. Protože se to z užitého tvůrčího procesu nabízí, označme tuto metodu z pozice vykreslování jako texturové zobrazení.

Obrázek 2.7: Ukázka ze hry Mafia [p21].

Obrázek 2.8: Ukázka ze hry Assassin's Creed: Brotherhood [p22].

11 2.5 Polygonové zpracování a rozšíření texturového zobrazení

Ke zlomu začíná docházet kolem roku 2009, kdy se z hlediska tvorby herních účesů největší senzací stala hra 2 a její velmi detailní zpracování hlavní postavy Nathana Drakea. Přestože se o podobnou metodu možná pokusili mnozí i předtím, byla to právě hra Uncharted 2, která na sebe dokázala strhnout pozornost díky nové technologii tvorby vlasů, kdy jsou na model hlavy a jeho případný základní účes napojovány jednotlivé polygonální útvary (buď samotný , nebo polygonový pruh) podpořeny alpha mapou (černobílá či šedotónní textura určující průhlednost) a texturou pramenů vlasů. Tím lze za určitou polygonální cenu získat komplexnější účesy, hlavně různé typy rozcuchů a krátkých ježatých vlasů. Platí zde pravidlo, že čím detailnější textury a čím komplexnější model (skládající se tímto způsobem jen na vlasech z desítek až stovek objektů), tím realističtěji daný účes vypadá. Nazvěme tento způsob polygonovým zpracováním. Jeho výhodou je úspěšné napodobení realismu vlasů (zvlášť za užití detailní textury a případných odlesků), nevýhodou je, že tento účes je vytvořen přesně pro danou postavu a jako takový je téměř statický (mnoho her na polygonech simuluje lehké záchvěvy vlasů tvořené animací hrany/bodů polygonu – pohyb s objektem – nicméně tato metoda může být výpočetně náročná, viz Tomb Raider z roku 2013). RPG žánr se vydal jinou cestou. Protože se jedná o hry, kde jedním z hlavních prvků je přenechání tvorby a utváření charakteru herní postavy na hráči samotném, musí být vytvořeny až desítky účesů, ze kterých si hráč může vybrat. Jsou to většinou samostatné modely následně překrývající povrch holohlavé postavy využívající texturového zobrazení. Tento postup má samozřejmě nespornou výhodu ve vysoké variabilitě, kterou hráč při tvorbě postavy získává, nicméně každý rub má i svůj líc a ten se zde projevuje ve formě kvality jednotlivých modelů. Krom několika her (například Dragon Age: Inquisition), kde je barva vlasů brána jako externí položka, kterou si hráč může namíchat dle vlastních představ, jsou pro každou přednastavenou barvu vlasů vytvořeny vlastní textury. Pokud bychom tedy měli třicet účesů, pro každý z nich dvacet barev, získali bychom šest set textur jen na pokrytí vlasů. Dnešní metody jsou pochopitelně sofistikovanější (ideálně jako u výše popsaného DA:I), ale například v dobách prvních dvou Mass Effectů (2007 a 2010) tohle byla relativně reálná praktika. U her tohoto typu se z hlediska vývoje upřednostňuje především příběh (jeho komplexita), tvorba a vyváženost vlastností/schopností herní postavy a vytvoření originálního, co možná nejzajímavějšího a nejotevřenějšího herního světa, takže je poměrně pochopitelné, že tvorbě kvalitních modelů a textur pro vlasy se příliš času nevěnuje. A i když jsou model i textura kvalitní, stále může nastat situace, ve které se vkus tvůrců neshoduje s vkusem hráčů a ona variabilita, ač velmi vítaná, v takovém případě zvýrazní omezenost volby ve hře. Netřeba dodávat, že takový účes, i kdyby byl zkombinován s metodou polygonových pruhů, je z hlediska pohybu i růstu převážně statický.

Obrázek 2.9: Hlavní postava hry Uncharted 2 a zobrazení metody polygonových pruhů [p23].

12 2.6 Alpha blend/test/to coverage

Metody popsané v předešlé kapitole fungují díky možnosti průhlednosti (transparency) textur skrze využití alpha map/kanálů (textura průhlednosti je tvořena pouze bílou a černou barvou, případně jejich šedotonní kombinací). Existuje více způsobů, jak alpha mapu zpracovat, v moderní počítačové grafice se používají především tyto tři: alpha blend, alpha test a alpha to coverage. Alpha blend je jemnou, hodnoty interpolující metodou průhlednosti, která často využívá celého šedotonního spektra jako hodnot pro nastavení různých úrovní průhlednosti či průsvitnosti. Alpha blend, stejně jako ostatní zmíněné metody alpha mappingu, považuje bílou za zcela neprůhlednou a černou za zcela průhlednou, přičemž vypočítává šedotonní hodnotu každého pixelu. Čím je pixel tmavší, tím je průhlednější. Tato metoda má jisté klady v tom, že výsledek vypadá při správném užití přirozeně a v případě potřeby lze vytvořit zcela jemné hrany. Problém však může nastat u mnoha překrývajících se objektů využívajících alpha blend (typickým příkladem mohu být listy, tráva, případně vlasy a srst), kdy je každý pixel, který ve výsledném obrazu tyto objekty vykresluje, v závislosti na jednotlivých průhlednostech stále přepočítáván a překleslován, což často snižuje počet vykreslených snímků za vteřinu (framerate), který přímo ovlivňuje plynulost her. Alpha test šedotonního spektra nevyužívá a proto jsou ovlivněné pixely buď zcela viditelné, nebo zcela průhledné. V případě užití šedotonní textury využívá hraniční hodnoty (světově známé pod názvem threshold), kdy všechny pixely, jejichž šedotonní hodnota je vyšší, než hraniční hodnota, jsou zcela viditelné, všechny ostatní pixely jsou průhledné. Díky užití absolutních stavů nemůže dojít k opakovanému překleslování jako u alpha blendu, výsledkem čehož je každý pixel zpracován pouze jednou, zároveň však nedochází k vyhlazení hran, což může působit velmi rušivě. Alpha to coverage funguje prakticky stejně jako alpha test. Využívá však mnohonásobného vyhlazení (MSAA), které dokáže zjemnit hrany podobným způsobem jako při užití alpha blend. Této metody lze však využít pouze u modernějších grafických karet (NVIDIA sedmé třídy, AMD/Intel ekvivalenty či novější), protože pro vykreslení je potřeba minimálně čtyřnásobné vyhlazení (4x MSAA).

Obrázek 2.10: Srovnání alpha test (vlevo), alpha blend (uprostřed) a alpha to coverage (vpravo) [p24].

13 2.7 Marschnerova metoda

Roku 2003 vytvořil a publikoval Stephen R. Marschner metodu tvorby a vykreslení vlasového materiálu založeného na naměřených hodnotách rozptylu světla skrze jednotlivé vlasy různých barev [3]. Na rozdíl od předešlých vykreslovacích modelů tento do výsledku započítaval zároveň průsvitnost, vnitřní odrazivost i světelnou absorpci vlasových pramenů. Tím dokázal nasimulovat nejen odlesk při dopadu světelného paprsku na model vlasu (R), ale i sekundární odlesk způsobený odrazy paprsku uvnitř vlasu (TRT) a průchod světla skrze model vlasu bez odlesku (TT). K dosažení přesných měření rozptylu světla bylo měření prováděno nejen v rovině, ve které se reálný vlasový pramen nacházel, ale i v celé hemisféře nad pramenem. Následně byl na model válce s natočenými šupinami simulující stavbu vlasu aplikován shader simulující naměřené vlastnosti skrze podélnou a azimutální funkci rozptylu, kde je odraz R barvy světla a odraz TRT díky průchodu vlasem získává jeho barevné vlastnosti. Zároveň lze díky možnosti průchodu světla simulovat vysoký jas vlasů při nasvětlení vůči kameře. Marschnerova metoda tvoří teoretický základ mnoha moderních metod pro vykreslování vlasů, například [4, 5, 6].

Obrázek 2.11: Výsledky měření rozptylu na černém, blonďatém a syntetickém vlasu (nahoře). Srovnání metody vlevo s fotografií reálných vlasů (dole) [3].

14 2.8 Sadeghiho/Disney metoda

Zatímco se mnoho vývojářů snažilo navrhnout co nejpřesnější model lesku, odrazivosti, absorpce a propustnosti vlasového materiálu, tým kolem Imana Sadeghiho se začal zabývat neméně důležitým úkolem zjednodušení ovladatelnosti fyzicky orientovaných shaderů [7]. Sadeghi jako tvůrce animovaných filmů u společnosti Walt Disney Animation Studios plně chápal potenciál přesných fyzikálně orientovaných shaderů, poukázal však na těžkou operabilitu nastavitelných vlastností při použití ve filmovém, případně herním průmyslu. Nejdůležitějšími prvky, které těmto shaderům doposud chyběly, byly intuitivní ovládání a chování shaderu, oddělení jednotlivých vizuálních funkcí a omezená možnost tvorby fyzikálně nepřesných shaderů. Proto vytvořil shader vizuálně podobný fyzikálně orientovanému, sepsal však vlastní nepřesnou funkci rozptylu, která umožnila dosáhnout jak reálných, tak uměleckých výsledků. Dále vytvořil uživatelsky přívětivé nastavení, které určovalo primární odlesk, sekundární odlesk, podružné odlesky a barvu prosvítajícího světla. Toto nastavení úzce korelovalo s Marschnerovou metodou zpracování rozptylu světla pomocí odrazu R, vnitřního odlesku TRT a průchodu TT. Narozdíl od nastavování koeficientů absorpce, odrazivosti či průsvitnosti, které určovaly barvu vlasů a odlesků či jejich vizuální tloušťku, Sadeghiho shader lze nastavit pomocí vybrané barvy, intenzity, pozice a šířky odlesků, což je uživatelsky mnohem přívětivější a požadovaný výsledek je snadno nastavitelný.

Obrázek 2.12: Srovnání fotografie reálných vlasů, Sadeghiho nového shaderu a vědeckého shaderu založeného na Marschnerově metodě (nahoře). Ukázka 2D konceptu účesu postavy převedeného do 3D a vykresleného pomocí Sadeghiho shaderu (dole) [7].

15 2.9 NVIDIA HairWorks a přiblížení hair strands

S příchodem DirectX 11 a trojúhelníkové teselace [8] začala firma NVIDIA vytvářet vlastní systém Hairworks. Ten podporuje pokročilou simulaci a vykreslování vlasů včetně různých úrovní detailu. Sama společnost tvrdí, že se tvorbou systému zabývala zhruba osm let [9]. Výsledkem je celkem realistické, leč graficky náročné vykreslování až desítek tisíc vlasů/pramenů vlasů (hair strands). Hair strands jsou ve své podstatě renderovatelné křivky (často Beziérovy [10]), u kterých lze snadno nastavit jejich tvar a aplikovat na ně fyzikální zákony. Křivky se v počítačové grafice užívají poměrně dlouho, nicméně právě NVIDIA přišla na to, jak snadno a výpočetně levně je vykreslit přímo ve hře. Hair strands se aplikují skrze samotný objekt – přidá se mu vlastnost tzv. emitteru (zdroje). Ten může buď vyzařovat částice (světla, kouře, atd.), nebo být zdrojem pro křivky reprezentující vlasy (odkazuji se přímo na funkci emitteru v Blenderu [11]). Při nastavování směru či délky nepracujeme se všemi vlasy, nýbrž pouze s reprezentativními řídícími prvky (parents). Docílíme tak snazší úpravy všech požadovaných křivek, které se při vykreslení transformují na řídící vlasy. Mnohdy je ovšem takové pokrytí příliš řídké, proto se využívá vykreslení instancí (children). Tvar instancí nelze přímo upravovat, jsou to kopie řídících objektů. Od skutečného duplikátu objektu se ovšem instance liší také tím, že přebírají všechny vlastnosti hlavního objektu, přičemž procesor je s touto informací obeznámen, nemusí tak zpracovávat stejné informace pro dva různé objekty. Stačí pouze zpracovat informace o pozici, rotaci a měřítku instance a na jejich základě vykreslit již zpracovaný objekt. Tím se šetří bodová/polygonová zátěž (příklad: schodiště tvořené stem oddělených schodů, každý tvořen osmi body a šesti polygony – skrze kopie či separátní objekty zpracovává procesor osm set bodů a šet set polygonů včetně jednotlivých pozic, skrze hlavní objekt a devadesát devět instancí pouze osm bodů, šest polygonů a devadesát devět pozic kopií), což umožňuje plynulejší hratelnost. Hairworks takto fungujících hair strands dokáže plně využít a krom úpravy barvy a směru růstu simuluje i poryvy větru či vykreslování stínů jak vůči jednotlivým vlasům/chlupům, tak vůči tělu a okolí. Nevýhodou je už výše zmíněná náročnost. U alpha blendu jsme narazili na pojem framerate. Pro připomenutí se jedná o počet vykreslených snímků za vteřinu a moderní hry se snaží dosáhnout hodnoty 60 fps (frames per second – snímky za vteřinu). Následující video [p25] zobrazuje porovnání vykreslování se zapnutým i vypnutým systémem Hairworks ve hře Witcher 3. Když je systém HairWorks vypnutý, lze s výkonnou grafickou kartou snadno dosáhnout 60 fps, po jeho zapnutí dochází k poklesu až o 20 fps, čehož si můžeme názorně všimnout na nepřirozeně trhaném pohybu hlavní postavy. Podobným způsobem a s relativně stejnými výsledky jak do vizualizace, tak do výkonu pracovaly i původní verze konkurenčního TressFX od AMD.

. Obrázek 2.13: NVIDIA HairWorks a aplikace hair strands [12].

16 2.10 DirectX 12 a TressFX 3.0

V červenci roku 2015 Microsoft Windows uvedl společně s Windows 10 na trh zcela nové API ovladače DirectX 12. Ty podle všeho umožňují vykreslovat komplexnější scény v relativně nízkých časech (podle oficiálních zdrojů dokáže ve stejném čase vykreslit až dvanáckrát více polygonů než DirectX 11 [p26]). Pro herní i vývojářskou komunitu to znamená především detailnější a realističtější hry, což se týká i konceptu tvorby a vykreslení vlasů. 26. ledna 2016 vydala společnost AMD softwarovou knihovnu pro pokročilé vykreslování vlasů a srsti s názvem TressFX 3.0. Dřívější verze TressFX byla využita především u nových her série Tomb Raider, kde na skutečně výkonných herních konzolích a počítačích dokázala nasimulovat pohyb vlasů. TressFX 3.0 tuto simulaci posouvá o krok dál, ovšem v době psaní této bakalářské práce je známa jediná hra využívající tuto knihovnu, a to Deus Ex: Mankind Divided společnosti ze srpna roku 2016. Zde se používá základního modelu vlasů v kombinaci s prameny vlasů (hair strands), což účesům dodává realističtější nádech. Protože je ovšem tato iterace v kombinaci se skutečným potenciálem ovladačů DirectX 12 teprve v pomyslných plenách, nelze ji dostatečně zdokumentovat a není jisté, zda tak, jak je vytvořena a jak bude dnes již zavedenými herními studii používána, zvládne nasimulovat také dynamický růst vlasů a tvorbu jakéhokoli účesu.

Obrázek 2.15: Ukázka využití TressFX 3.0 při tvorbě hry Deus Ex: Mankind Divided [p27].

17 3 Návrh a implementace vlastní metody

Druhá kapitola znázornila, jak rychle technika tvorby postav a vlasů ve skutečnosti postupuje. Jak nám však nastínil aktuální vývoj nejmodernějších metod, stále je co zlepšovat. Zavedené postupy mohou být vizuálně přívětivé, osobně však nejsem zcela přesvědčen, že nejlepším způsobem simulace trojrozměrné dynamiky vlasů je uspořádání na sobě nezávislých dvourozměrných objektů či graficky náročné fyzikální vykreslování hair strands. Tyto metody navíc doposud nepodporují růst vlasů, z hlediska realismu v tomhle ohledu všechny zaostávají. Proto jsem začal hledat nový postup, který by reflektoval reálný svět a z hlediska zobrazení a výpočetní složitosti by byl zlatou střední cestou mezi moderními metodami. K jeho pochopení je třeba práci rozdělit na dílčí úseky. U každého nejprve přiblížím základní myšlenku či užitou teorii a následně popíši grafické postupy, kterými požadovaný výsledek získat.

3.1 Vlas v reálném světě

Pokud se podíváme na tělo z čistě biologického hlediska, zjistíme, že vlas je pevně přichycen ve škáře (dermis) pod pokožkou (epidermis) a dle zavedených definic lze jeho stavbu rozdělit na dvě základní části: vlasový stvol (scapus pili) a vlasový kořen (radix pili), přičemž růst probíhá od cibulky (bulbus, nejhlubší část kořene) pod pokožkou ke stvolu nad pokožkou. Je jedno, jak je vlas dlouhý, zakřivený či na povrchu polámaný - na hlavě nám drží právě díky svému kořenu. Podle absence či presence vlasového kořene můžeme dokonce de facto určit dva druhy plešatosti, totiž přirozený a uměle vytvořený. Důležité však je, že při uměle vytvořeném stavu plešatosti (nejčastěji vyholením vlasů) onen vlasový kořen pod pokožkou stále existuje a vlas má ve skutečnosti nenulovou délku (od cibulky po pokožku). Proto pokud budou výpočty metody pracovat s nulovou délkou, je tím myšlena pozice imaginární vlasové cibulky pod pokožkou, nikoli průnik vlasu s modelem hlavy. Zohlednění přibližné pozice zakořenění a skutečného způsobu růstu vlasu kombinované s následným provedením lze považovat za základní kámen této technologie a zároveň za největší odlišení od dosavadních široce užívaných metod. Nejprve je třeba vysvětlit užitý princip pro samotný růst vlasů. Předně základní parametry vlasů jako takových: v knize 'Přehledy věd přírodních. Dílu I. část 1. Tělověda-zoologie-botanika' [13] se dočteme, že průměrný jedinec má v daný moment mezi osmdesáti až sto čtyřiceti tisíci vlasy, přičemž průměrná tloušťka by měla být do sta mikrometrů a hustota až tři sta vlasů na centimetr čtvereční. To znamená, že v bodě průniku vlasů s povrchem skrze póry lze mluvit o velmi hustém a relativně konstantním pokrytí pokožky. S přibývající délkou si lze zcela snadno povšimnout, že vlasy rostoucí blízko u sebe nerostou nezávisle na sobě, nýbrž se stmelují do pramene. Takové pramínky vlasů se na hlavě vyskytují v řádech tisíců a mohou, ale nemusí jeden druhý vzájemně překrývat. Tím můžeme ztratit původní vizuální hustotu, nicméně ta je stále dostatečná. Nesmíme však zapomínat, že i v prameni vlasů roste každý vlas individuálně a proto může v určitém bodě růst jiným směrem. Nejlépe je to vidět u konečků, kdy se pramen vlasů jeví roztřepeně a opět ztrácí na vizuální hustotě. Celkově tedy můžeme naivně odvodit určitý typ nelineární rovnice úbytku vizuální hustoty v závislosti na délce vlasů. Z grafického hlediska tedy bude potřeba vypočítat a nadefinovat systém růstu, který požadovaný objekt modifikuje na dynamické vlasové prameny, a následně vytvořit materiál, který bude při vykreslení věrně reprezentovat vlasy včetně vizuálního úbytku hustoty.

18 3.2 Tvorba pramenů vlasů

Abychom mohli při tvorbě vlasů vycházet z cibulek pod pokožkou, je nutné během modelování charakteru rozmyslet jejich polohu (obrázek 3.1). Objekt vpravo je klasickým modelem pro užití textur/shaderů a tvorbu animace, kterou užívají všechny metody. Objekt vlevo je redukcí původního modelu a po odstranění segmentů, které reprezentují vlasy či srstí nepokryté úseky hlavy, dostatečně přesně reprezentuje oblast výskytu vlasových cibulek. Obrázek 3.1 dole zobrazuje, jak hluboko pod pokožkou se budou vyskytovat planární objekty, ze kterých budeme danou dále popsanou metodou přímo vytvářet vlasové prameny - na rozdíl od emitteru tak model při tvorbě využije nejen všech svých polygonů, ale také všech bodů, které budou hrubou reprezentací pramenů vlasů. Po vizuálním zjemnění a doladění vhodně vytvořeným shaderem bude mít výsledný výstup vzhledové a trojrozměrné vlastnosti obdobné systémům užívajícím hair strands, protože se však jedná o ucelený model, očekává se, že zpracování vykreslení jednotlivých objektů bude oproti hair strands časově snazší a v případě vhodného užití shaderu bude časová složitost prakticky nepodstatná. Nutno však dodat, že ačkoli realistická animace jednotlivých pramenů je proveditelná, momentálně naimplementována není a její absence může výpočet pozitivně ovlivnit.

Obrázek 3.1: Ukázka modelu výskytu vlasových cibulek a modelu pokožky (nahoře). Ukázka vzájemné polohy obou modelů (dole). Snímky obrazovky z programu Blender.

19 3.2.1 Displacement U růstu vlasů jsem se opět nechal inspirovat přírodou a uvědomil si, že vlasy jsou od cibulek skrze pokožku doslova protlačeny na povrch, přičemž tento proces je z logiky růstu neustálý. Nová metoda tedy podobným způsobem vytvoří ze skrytého modelu jednotlivé prameny, které budou protínat model hlavy, tedy v závislosti na čase snadno modifikovat tvar a velikost modelu. To je možné díky principu a funkci grafického modifikátoru, potažmo způsobu využití textur k získání reálné plasticity, známého pod termem Displacement [p28]. Jedná se o proces aplikace šedotónní textury na zpracovávaný objekt a změnu jeho tvaru v závislosti na odstínu. Jako střední hodnota se využije světlost padesátiprocentní šedé (RGB 127,127,127). Čím světlejší textura na určitém místě je, tím více se body či polygony posunou ve směru normálového vektoru. Stejně tak čím tmavší je textura oproti barvě reprezentující střední hodnotu, tím více se objekt prohloubí. Program Blender obsahuje interní Displace modifikátor [14], u kterého lze nastavit jak sílu určující maximální vzdálenost upravených bodů od původního objektu, tak směr růstu (buď klasicky dle normálového vektoru, nebo dle jedné ze tří základních os) či umístění střední hodnoty. Zaveďme konvenci, že růst vlasů budeme ovlivňovat pouze po ose Y (Direction:Y). Nová pozice každého bodu objektu bude vypočtena na základě kódu case MOD_DISP_DIR_Y: vertexCos[i][1] += delta ; break; kde vertexCos[i][1] značí souřadnice bodu na ose Y a proměnná delta sílu modifikátoru. Vypočtená hodnota je následně násobena v závislosti na užité textuře a hodnotě šedotonní textury v dané pozici. Celý kód lze nalézt pod odkazem [15] či v elektronické příloze, jeho modifikaci v příloze D.

Obrázek 3.2: Rozhraní modifikátoru Displace.

Aby mohl být Displace adekvátně využit, musel jsem vytvořit texturu. Její výsledná podoba, zachycená na obrázku 3.3 vlevo dole, je důsledkem následující úvahy: existuje-li model, který má definované krátké vlasy či vousy, je možné z daného kusu modelu vytvořit displacement mapu, na které ony budou v závislosti na detailu modelu kvalitně zaznamenané. Jediným problémem jest přítomnost dané části pokožky, na které se vlasy či vousy nachází. Lze však snížit jas a upravit kontrast dané textury tak, aby plocha reprezentující pokožku byla relativně rovnoměrná a absolutně černá, a u modifikátoru v Blenderu nastavit střední hodnotu na nulovou, což ve výsledku zaručí, že vše, co je černé (RGB 0, 0, 0), zůstane na svém místě, vše světlejší bude při klasickém nastavení růst vektorovým směrem, tedy od modelu oblasti výskytu vlasových cibulek na povrch. Protože však u textury ani v takovém případě nelze absolutně zaručit, že negativně neovlivní hrany upravovaného objektu, jsou základní modely vlasových pramenů prostřednictvím klasických transformačních modifikátorů (užit je konkrétně pohyb a změna velikosti) vnořeny pod povrch na úroveň oblasti výskytu cibulek (na obrázku 3.1 znázorněna čtyřbarevným modelem). Tím je eliminován potenciální problém odklopení objektu od modelu hlavy, který by kazil celkový dojem.

20 Obrázek 3.3 zachycuje postup a průběžné výsledky tvorby potřebné textury. Prvně byl vytvořen detailní model postavy včetně vousů a vlasů (původně v programu Blender, detailnější reprezentace na obrázku byla dotvořena v programu Zbrush). Následně byl dosazen objekt výskytu, na který byl skrze modelovou projekci načten tvar vousů a vlasů. Po exportování displacement mapy upraveného objektu byla textura modifikována za pomoci programu Adobe Photoshop. Pro zachování většiny dat byl textuře ponechán původní jas, který byl snížen až v Blenderu.

Obrázek 3.3: Kompozice postupu tvorby textury: původní displacement textura (vlevo nahoře), upravená textura (vlevo dole), zobrazení nastavení textury v Blenderu (vpravo).

Všimněme si upravené textury vlevo dole. Ačkoli se může zdát, že jde o jednolitou šedou plochu, ve skutečnosti se jedná o velmi jemnou texturu, ve které byly všechny podstatné informace nahuštěny do úzkého šedotonního spektra. Důvodem je lepší operabilita při nastavení parametru síly a souběžně s tím kvalitnější vyhlazení a zjemnění světlých vrcholů. Následující příklad se pokusí problematiku přiblížit: Existuje displacement mapa se dvěma světlými body reprezentujícími jednotlivé vlasy (jeden z nich má všechny hodnoty nastaveny na 230, druhý na 240). Při aplikační síle 1.0 je za adekvátně užitého měřítka rozdíl v nárůstu jeden milimetr. Tato odchylka je při nízké aplikační síle zanedbatelná, protože je však metoda koncipována tak, aby pracovala i s aplikační silou 50.0, rozdíl může dosáhnout pěti centimetrů, což není žádoucí. Proto je celá displacement mapa regulována na úzké šedotónní pásmo – pro snadný názorný výpočet uvažme převod všech 256 odstínů do pásma složeného z osmi hodnot. Každých 32 odstínů staré škály je nahrazeno jedním odstínem nové škály, proto se všechny hodnoty v rozmezí 223-255 transformují do stejného odstínu. Rozdíl v nárůstu mezi těmito dvěma body bude při aplikaci nové škály nulový jak při aplikační síle 1.0, tak při síle 50.0. Zároveň je v závislosti na jednotce síly nárůst několikanásobně menší, lze tedy využít vyšších hodnot a díky upravené škále získat také jemnější interpolovaný růst.

21 Obrázek 3.4: Kompozice výsledků užití modifikátoru Displace. Objekt bez užití modifikátoru či užití o síle 0.0 (nahoře), použití modifikátoru Displace o síle 5.0 (veprostřed), použití modifikátoru Displace o síle 30.0 (dole).

3.2.2 Subdivision Surface Zbývá ještě nadefinovat optickou přirozenost směru růstu, tedy přidat iluzi gravitace a dané polygony vhodným způsobem prohnout. Aby bylo dosaženo nutné úrovně detailu, je třeba mezi kořínky a konečky přidat dostatečné množství bodů, které budou kopírovat křivku určující směr růstu. Tento krok je zaručen modifikátorem Subdivision Surface[16], který pro daný objekt na každé hraně a na každém polygonu vytvoří nový bod a tyto body spojí tak, aby každý nový polygon byl podmnožinou polygonu starého. Při výpočtu polohy nových bodů je užita metoda Catmull- Clark[17], která kromě zhuštění polygonové sítě objekt zároveň vyhlazuje. Díky tomu je zaoblení podle křivky jemnější. Celý kód pod odkazem [18] a v elektronické příloze, modifikace v příloze D.

Obrázek 3.5: Kompozice výsledků užití modifikátoru Subdivision Surface. Objekt bez užití modifikátoru či užití řádu 0 (vlevo), použití modifikátoru Subdivision Surface řádu 1 (veprostřed) a 3 (vpravo).

22 3.2.3 Curve Každý vlasový pramen je ovládán jednou beziérovou křivkou. Ta skrze modifikaci řídících bodů zaručuje nejen profil a tloušťku jednotlivých segmentů pramenů, ale také možnost jejich animace. Aby však závislost pramenů na řídící křivce fungovala správně, musí být zaručeny dvě věci: pivot křivky musí mít stejné souřadnice jako pivot ovládaného pramene a daný pramen musí obsahovat modifikátor Curve[19].

Obrázek 3.6: Rozhraní modifikátoru Curve.

Ten zprostředkovává propojení mezi oběma objekty a jejich vzájemnou interakci. Protože jsme u modifikátoru Displacement zavedli růst po ose Y, je třeba vybrat osu Y i pro projekci na křivku. Za položku Object musíme zvolit řídící křivku, jinak kvůli prázdnému vstupu k deformaci nedojde. Kód pod odkazem [20] a v elektronické příloze, modifikace v příloze D.

Obrázek 3.7: Kompozice výsledků užití modifikátoru Curve. Objekt bez užití modifikátoru (vlevo), použití modifikátoru Curve se Subdivision řádu 0 (vpravo), použití modifikátoru Curve se Subdivision řádu 3 (dole).

3.2.4 Decimate V této fázi je vlasový pramen hotový, plně funkční, s podporou růstu a lehkou ovladatelností skrze řídící křivku. Protože je však třeba užít subdivize několikátého řádu (možnost srovnání na obrázku 3.7), dosahuje polygonální náročnost jednoho pramene hodnot v řádu statisíců. Aby byla metoda použitelná v herním designu, kde podobných hodnot dosahují kompletní postavy, je třeba celý pramen následně zredukovat. Toho dosáhneme přidáním modifikátoru Decimate[21], který podporuje hned několik metod redukce objektů. Metoda Planar redukuje geometrii objektů na planární polygony na základě vstupu o úhlu, přičemž redukuje právě ty hrany, které svírají úhel nižší, než je vstupní hodnota. Metoda UnSubdivide redukuje objekt na základě algoritmu, který pro

23 každý polygon vybere jednu úhlopříčku takovým způsobem, aby všechny úhlopříčky mohl spojit do nové sítě a smazat síť starou, přičemž každé dvě iterace metody UnSubdivide negují jeden řád metody subdivison. Metoda Collapse na základě vstupního faktoru vypočítává novou polygonální síť tak, aby byla složená ze zlomku polygonů určeného tímto vstupem. Na rozdíl od obou předchozích metod však generuje novou síť se záměrem zachování co nejvíce detailů, proto je pro náš vlasový objekt a jeho členitost tím nejvhodnějším řešením. Je důležité zmínit, že informace Faces udává počet polygonů, ze kterých se objekt skládá, přičemž tato redukce pracuje na základě redukce trojúhelníků. To znamená, že pokud nastavíme decimační faktor na desetinu, zredukuje se na desetinu počet trojúhelníků. Protože se však základní model vlasového objektu skládá ze čtyřúhelníků, bude informace Faces zredukována na pětinu a klasické polygony budou nahrazeny trojúhelníky. Proto je při modelování a následné redukci vhodné uvažovat v počtu trojúhelníků. Celý kód k nalezení pod odkazem [22] či v elektronické příloze, modifikace v přiloze D.

Obrázek 3.8: Rozhraní modifikátoru Decimate.

Obrázek 3.9: Kompozice výsledků užití modifikátoru Decimate. Objekt bez užití modifikátoru či s faktorem 1.0 (vlevo), použití modifikátoru Decimate s faktorem 0.1 (vpravo), použití modifikátoru Decimate s faktorem 0.0125 (dole).

3.2.5 Souhrn Celá metoda tvorby vlasů se skládá z vhodného využití několika základních modifikátorů programu Blender. Skrze Displace můžeme ovládat a animovat délku vlasů, modifikátor Curve umožňuje propojení s řídící křivkou, kterou můžeme tvar a směr růstu vlasů upravovat a umožňuje nám možnost následné implementace animace jednotlivých pramenů, Subdivision Surface udává úroveň detailu generovaných vlasů a modifikátor Decimate následně vše redukuje do polygonální náročnosti vhodné pro herní design. Pro více informací ohledně postupu s možností kontroly a testu tvorby vlasového objektu vyhledejte přílohu C na konci bakalářské práce.

24 Obrázek 3.10 na této a další straně dokumentuje dosavadní výsledek získaný modifikacemi včetně několika nastavení délky vousů a vlasů.

25 Obrázek 3.10: Ukázka několika typů účesů a vousů včetně náhledu základního modelu a jeho polygonové mříže.

26 3.3 Pokožka

Na předešlých snímcích lze vidět jen nepatrný zlomek variability, kterou tento systém nabízí, přičemž daných výsledků bylo dosaženo převážně jen přenastavením délky vlasů. Následně byl naimplementován vhodný vlasový materiál, který nejlépe reprezentoval fyzikální vlastnosti reálných vlasů. Abych však měl jistotu, že výsledek koreluje i s natexturovanou hlavou, vytvořil jsem nejprve dvě možnosti zobrazení pokožky. První, jednodušší, využívá složeného shaderu využívajícího podkožní rozptyl světla (Subsurface scattering [p29]) pro dosažení přirozených odlesků, což je výhodné převážně u tvorby mokré či zpocené pokožky. Tyto informace je možné uložit do využitelných textur, takže podobný výsledek lze získat v reálném čase. Druhá rozšiřuje první o další nastavitelné možnosti, její výhodou je využití uzlu Principled BSDF [23], nového typu shaderu funkčního od verze 2.79, který je založen na systému PBR [24, 25] a v porovnání s první metodou je převod výstupu do herních enginu snazší. Protože jsou obě pokožky na vytvoření poněkud komplexnější a zároveň nejsou součástí práce, popis jejich tvorby a jednotlivých funkcí je vynechán.

Obrázek 3.11: Srovnání možností zobrazení pokožky (první možnost nahoře, druhá dole).

27 3.4 Složení materiálu

Vzhledem ke kvalitnějším vizuálním výsledkům a jednoduchému převodu do jiných systémů jsem k následujícím ukázkám skladby vlasového materiálu využil druhý, integrovaný typ. Využil jsem jej i během páté kapitoly, ve které je popisovaný systém kvalitativně i kvantitativně srovnán s ostatními moderními hrami, a také ve výstupech dokumentovaných v příloze B. Samotný materiál vlasů se skládá ze dvou stejně koncipovaných shaderů, přičemž každý je schopen výslednému obrazu přidat jiné vizuální vlastnosti. Následně jsou míchány do jednoho výstupního materiálu, jehož výsledný vzhled lze ovlivnit dvěma vstupními hodnotami ovládajícími interval, na základě kterého systém míchání zpracovává. Shadery jsou tvořeny skrze uzly systému Cycles, rendereru programu Blender. Protože se jedná o poměrně komplexní shader, rozdělil jsem jej do několika pomocných podmnožin v závislosti na funkci.

3.4.1 Průhlednost a průsvitnost

Obrázek 3.12: Schéma prvního pomocného shaderu.

První pomocný shader (na obrázku 3.12) využívá normálového a tangent vektoru (jejich popis a rozdíl mezi nimi v angličtině zde [p30]). Horní větev (červeně) zobrazuje součet absolutní průhlednosti a průsvitnosti v závislosti na normále. Přestože se dle názvu jedná o součet, ve skutečnosti dochází k jemné kombinaci – v místě průsvitnosti je připočítána barva průhlednosti (bílá), která se díky průsvitnosti mírně odráží a výsledná kombinace je lehce světlejší a zářivější než využití samotné průsvitnosti. Dolní větev (modře) využívá tangenty polygonu k nastavení ohraničení jednotlivých vlasů (tangenta je převedena na barevné spektrum z černé do průhledné). Obě větve jsou kombinovány skrze uzel Mix [26] (zeleně). Ten slouží ke smíchání dvou různých shaderů v závislosti na faktoru. Faktor je přednastaven na číselnou hodnotu od nuly do jedné (takže Fac 0.5 míchá shadery jedna ku jedné, Fac 0.4 dvě ku třem atd.), nicméně jeho výhodou je možnost využití externího vstupu, do kterého vložíme tangentu. To zaručí, že průhledná místa vytvořená barevným spektrem nahradíme průsvitností z horní větve. V posledním kroku v poměru jedna ku čtyřem přidáme základní barvu vlasů, čímž průsvitnost získá správný barevný nádech.

28 3.4.2 Barevnost

Obrázek 3.13: Schéma druhého pomocného shaderu.

Funkcí druhého pomocného shaderu (na obrázku 3.13) je do výsledku přidat trochu více barvy. Základ získáme skrze barevné spekrum v levé části obrázku, jehož výstup je závislý na informaci o průniku objektů (červeně). Podle toho, kolik objektů daným úsekem vlasu proniká, předává barevné spektrum informaci do faktoru uzlu ovlivňujícího míchání barev, čímž můžeme ovlivnit barvu kořenů a konečků. Vstupy do uzlu jsou předešlý pomocný shader (modře), jehož vstupem je první barva výsledného shaderu, a třetí barva výsledného shaderu. V pravé části obrázku je schéma Mix uzlů, kterými přidáváme odlesky skrze druhou (zeleně) a čtvrtou (žlutě) barvu výsledného shaderu. Poslední Mix uzel má jeden ze vstupů prázdný, což reprezentuje vstup páté, černé barvy, která přidává negativní odlesk a tmavost skrytých, odstíněných částí vlasů a pomáhá vizuálně definovat interní stíny. Díky nízké hodnotě faktoru se však jedná o malou změnu a absence vstupu slouží k odlehčení výpočtu shaderu.

3.4.3 Ovlivnění v závislosti na textuře Obrázek 3.14 zobrazuje konečnou fázi tvorby shaderu. Dříve naimplementované pomocné shadery kombinujeme pomocí dvou Add [27] uzlů veprostřed obrázku (červeně). Tyto sčítací uzly, se kterými jsme se lehce obeznámili při tvorbě průsvitnosti, lze využít v rámci jediného shaderu. Proto do jednoho z nich zkombinujeme průsvitnost s barevností a do vstupů druhého uzlu vložíme pouze barevný pomocný shader. Mohli bychom očekávat, že po sečtení dojde ke zdvojnásobení RGB hodnot a výsledek bude světlejší. Ve skutečnosti se však sčítá odstín a sytost, takže místo zesvětlení získáme přesycení barev. Tyto dva součty kombinujeme přes Mix uzel, jehož faktorem je průnik s dopadajícím paprskem světla. V závislosti na odražení paprsku určujeme, zda bude daná oblast udržovat více informací o hraně či barvě vlasu. Protože se dopadající paprsek vždy do jisté míry odrazí, máme zaručeno, že výsledek bude skutečně kombinací součtů, nikoli upřednostnění jednoho součtu před druhým. Horní větev (modře) využívá neupravené textury vousů a vlasů (podobu takové textury lze vidět na obrázku 3.3 o úpravě textury v podkapitole 3.2.1 Displacement) a skrze dvě barevná spektra (od černé po průhlednou) z ní vytváří faktor Mix uzlu (zeleně)

29 ovlivňujícího míchání součtů pomocných shaderů s dodatečnou průhledností a s tím související mírné zjemnění vlasových konečků. Změnou pozice pravého bodu druhého barevného spektra lze nastavit jemnost či hrubost vlasů – čím bude poziční interval menší, tím hrubší vlasový materiál získáme. S větším pozičním intervalem naopak lze dosáhnout efektu velmi jemných až průsvitných vlasů vhodných k využití na starších postavách. Před odesláním shaderu na výstup přidáme skrze Mix uzel s faktorem 0.14 barvu nesoucí uzel (zeleně) se vstupem blízkým základním barvám shaderu, které decentně obarví hrany vlasů na pro ně přirozenější odstín.

Obrázek 3.14: Schéma třetího pomocného shaderu.

Obrázek 3.15: Schéma jednoho shaderu.

30 3.4.4 Kombinace a doladění Na obrázku 3.15 je znázorněno schéma celého jednoho shaderu určujícího vzhledové vlastnosti vlasového materiálu. Jak však bylo na začátku kapitoly 3.5 zmíněno, výstup je ovlivněn dvěma shadery této koncepce s nezávisle nastavitelnými vlastnostmi.

Obrázek 3.16: Schéma vstupního intervalu.

Jejich kombinace je docílena spojením do Mix uzlu s faktorem ovlivněným vstupním intervalem znázorněným na obrázku 3.16. Ten obsahuje tři uzly s matematickými operacemi, dva uzly se vstupními informacemi a uzel obsahující informace o objektu, na nějž je materiál aplikován. Ten mimo jiné obsahuje výstup random, který v závislosti na objektových informacích posílá náhodné reálné číslo v intevalu <0;1> a tím dokáže diferencovat výstup materiálu. Protože však chceme mít možnost interval přenastavit, využijeme rovnice ((A - B) * R) + B, kde A značí horní ohraničení intervalu, B značí dolní ohraničení intervalu a R je náhodné číslo z intervalu <0;1>. Prvkem (A - B) definujeme velikost intervalu, proměnnou R v něm nalézáme náhodnou pozici, ke které nakonec přičítáme hodnotu B, aby bylo zajištěno, že interval začíná na správné pozici. V rámci implementace uzlů s matematickými operacemi (Math [28] uzly) v prvním vybereme položku Subtract, do prvního vstupu vložíme vyšší hodnotu a do druhého nižší. Výstup převedeme do vstupu druhé operace, ve které je vybrán Multiply, a do zbývajícího vstupu vložíme výstup Random z objektového uzlu. Ve třetí operaci Add sjednotíme výsledek násobení s nižší vstupní hodnotou a nový výstup odešleme do faktoru Mix uzlu, který propojuje oba shadery. Tímto způsobem dokážeme ovlivnit náhodnost výstupu, kdy má každý vlasový objekt jiné materiální vlastnosti. Lze tak vytvořit unikátní nastavení barvy, jemnosti a odlesků a získat variabilitu podporující iluzi realismu. Kolekce obrázků 3.17 na následující straně znázorňuje náhodnost materiálu na základě odlišného barevného vstupu.

31 Obrázek 3.17: Srovnání obou shaderů a výsledku jejich náhodného smíchání na intervalu <0;1>

32 4 Převod do reálného času

Třetí kapitola představila navrhovanou metodu a shadery, díky kterým lze nadefinovat délku, směr růstu a jemnost vlasů. Přiložené obrázky zobrazily dosažitelnou kvalitu výstupu, ten je nicméně vykreslen v renderovacím, nikoli herním enginu. Rozdíl mezi těmito dvěma typy je ve zpracování k modelům přidružených materiálů a shaderů a interakci světel ve vytvořené scéně. Renderovací engine (např. Cycles v Blenderu) využívá světel podporujících ray tracing, metodu globálního osvětlení, která rekurzivně sleduje dráhu světelného paprsku. Díky implementované podpoře komplexních odrazů, lomů vlnění a rozptylu světla dosahuje tento typ enginu vysoce kvalitních a realistických výsledků, nicméně za vyšší výpočetní cenu (v případě užitého modelu se tato pohybuje v řádech minut). Při každé iteraci vykreslování jsou navíc všechny vlastnosti přepočítávány i v případě, že je jako materiál užita již uložená textura. Herní engine naopak pracuje s již předvypočítanými informacemi, mezi které patří ploché osvětlení, materiály složené z uložených textur či elementární shadery. Engine před prvním spuštěním všechny podněty zkompiluje a pokud není scéna nijak radikálně pozměněna (například přidáním světel či nových herních objektů), každé další spuštění vykreslení bude založeno na této kompilaci. Díky tomu je výpočetní cena minimální (pohybuje se v řádech milisekund), vlastnosti světel i materiálů jsou však silně omezeny. Je implicitně známo, že pokud lze scénu v konečném čase vykreslit v enginu renderovacím, je možné vytvořit engine herní, ve kterém bude vykreslena v čase reálném (viz podkapitola 4.5). Jedním z cílů této práce je však dokázat, že vlasy vytvořené touto metodou je skutečně možné vykreslit v reálném čase a že případný pokles FPS bude nižší, než při užití hair strands. Proto následující kapitola dokumentuje převod modelu z renderovacího do volně dostupného herního enginu a následné testování poklesu FPS v závislosti na užité metodě koncepce materiálů.

4.1 Unreal Engine 4

Pro reprezentaci v reálném čase jsem zvolil herní engine Unreal Engine 4 [p31] společnosti Epic Games. Ten, obdobně jako Blender Cycles, využívá uzlové interpretace relací mezi vstupy, interními funkcemi a parametry k přehlednému nastavení výsledného materiálu. Oproti Cycles ovšem v rámci projektu trpí několika nedostatky, které je třeba zmínit. Předně se jedná o absenci či nevhodnou implementaci převodu shaderů, jejímž důsledkem je nemožnost přímo aplikovat předem vytvořené vlasové shadery. Uzlová interpretace navíc není definována jako jeden ucelený výstup, nýbrž jako soustava jednotlivých kanálů (pro barvu, odlesk, průhlednost atd.), které v závislosti na vybraném typu materiálu jsou přímo společností Epic Games zablokovány. Z toho vyplývá, že materiály je nutné v enginu zrekonstruovat, přičemž některé vlastnosti původních materiálů mohou být ztraceny. Nejpodstatnější ze ztracených vlastností je nastavení různých úrovní průhlednosti. Zatímco engine Cycles řeší průhlednost na základě vzdálenosti bodu od své původní pozice skrze barevná spektra, UE4 žádnou formu spektra nepodporuje a průhlednost lze u materiálu nastavit pouze na konkrétní hodnotu. Proto je užitý shader z hlediska kvality výsledku definován jako vlasový (Shading Model: Hair), přičemž kanál průhlednosti je pro tento materiál neaktivní. V neposlední řadě nastává problém u podpory generování a růstu vlasů. V momentě sepisování stále není jasné, zda se jedná o chybu enginu či o nedostatek z mé strany, nicméně aktuálně není možné načíst a zprovoznit modifikovaný kód ani žádnou jeho abstrakci. Tento problém je prozatím vyřešen převedením objektu vlasů na objekt statický, čímž si ponechává své tvarové vlastnosti, možnost implementace růstu vlasů v daném herním enginu však není funkční.

33 4.2 Export objektů

Materiál je v UE4 tvořen nezávislými kanály starajícími se o barvu, svítivost, průhlednost, hrubost, odlesk, lom a jiné vlastnosti, kterých materiál může nabývat. Do těchto kanálů lze odeslat libovolný vstup, který může být interpretován. Může se jednat o konstantu, proměnnou, logickou operaci, jednolitou plochu či komplexní texturu. Proto je možné zrekonstruovat Cycles materiál hned dvěma způsoby – buď jako kombinaci vhodných textur (každá přidružena jednomu či více kanálům), nebo rekonstrukcí funkce shaderu s počátečními vstupy shodnými v obou enginech. Skrytou možností je kombinace výše zmíněných způsobů. Protože jsem však chtěl docílit lepších vizuálních výsledků a zároveň otestovat náročnost metody, otestoval jsem zobrazení vlasových pramenů skrze shader. Dále je třeba otestovat objektovou náročnost modelu, která může kriticky ovlivnit rychlost vykreslování. Účes testovaného modelu se skládá z 1529 objektů, tato hodnota byla využita jako horní hranice. Stiskem A (výběr všech objektů) a kombinací Alt+C dojde k aplikaci modifikátorů na všech objektech ve scéně, stiskem CTRL+J lze vybrané objekty sdružit. Proto je možné exportovat účes stejného tvaru i vlastností s redukcí objektové náročnosti. Proto byly z Blenderu exportovány tři účesy o náročnosti 19 (redukce dle modelovacích skupin), 307 (redukce na 20%) a 1529 objektů. Jednotlivé objekty byly přes hlavní lištu File/export uloženy do formátu FBX, protože jiné formáty UE4 nepodporuje.

Obrázek 4.1: Znázornění umístění exportu do FBX (modře).

4.3 Import a stavba materiálů

Rozhraní UE4 obsahuje Content browser nacházející se pod náhledem scény. Ten v sobě nezávisle na jejich funkci hierarchicky uchovává veškeré scénou užívané soubory. Prostřednictvím tlačítka import bylo pro zamýšlený test nutné vložit všechny exportované objekty a textury. Skrze pravé tlačítko myši lze do Content browseru přidat nový materiál. Ten byl využit pro rekonstrukci původního shaderu, vzhledem k jinému systému stavby materiálu bylo nutno zrekonstruovat jej ručně.

34 Obrázek 4.2: Schéma rekonstrukce původního shaderu.

Rekonstrukce původního shaderu (na obrázku 4.2) dodržuje obdobné principy jako stavba shaderu v systému Cycles. Vlevo nahoře se nachází nastavení součtu průsvitnosti smíchané se základní barvou v závislosti na tangentě obdobné jako u prvního pomocného shaderu (podkapitola 3.4.1, obrázek 3.12). Dále jsou přes uzly Lerp (alternativa k Mix uzlům v Cycles) přidávány další barevné odstíny, což bylo původně funkcí druhého pomocného shaderu (obrázek 3.13). Nakonec je přes uzel Alpha Offset připojena původní textura do faktoru uzlu Lerp spojující barvu s vyšším jasem, který musí kvůli průhlednosti zvýrazňovat základní smíchanou barvu, uzel je napojen na poslední Lerp pro doladění s poslední barvou kvůli odlesku a výsledná barva je míchána s výstupem druhého shaderu pomocí funkce PerInstanceRandom, která má obdobnou funkci náhodnosti jako položka Random v systému Cycles. Materiál je nastaven na mód Surface, způsob prolínání na Opaque, způsob stínování je nastavený pro materiál vlasů a materiál je oboustranný. Výstup pak vede do kanálů Base Color (barva), Scatter (rozptyl) a Specular (lesk).

35 4.4 Srovnání a test FPS

Obrázek 4.3 zobrazuje výstup dosažený užitým materiálem. Již na první pohled je patrné, že shader vytvořený v UE4 nedisponuje stejnými vlastnostmi jako ten, který byl vytvořen v Blender Cycles. Je otázkou, zda je nastavení materiálu nejlepší možnou interpretací, s odchylkou v realizaci se však počítalo už při popisu nedostatků enginu UE4 v podkapitole 4.1.

Obrázek 4.3: Výstup realizovaný pomocí shaderového materiálu.

Pokud by cílem práce bylo co nejpřesněji interpretovat výstup dosažený v Cycles, použil bych po vzoru herních studií specifický herní engine řešící konkrétní problém. Takové enginy jsou velmi sofistikované, jejich výpočetní časy bývají nedostižné. Můj cíl je však dokázat, že mou metodou vytvořené vlasy lze vykreslit v reálném čase. Proto jsem upřednostnil základní herní engine, který na co nejrychlejší vykreslení snímku není specializován. Pokud bude možné vykreslit na základním enginu v reálném čase celý model s dostatečnou kvalitou, je velmi pravděpodobné, že jej bude možné vykreslit s očekávanou kvalitou na enginu specializovaném. Pro bezchybný běh se počítačové hry snaží udržet nad úrovní 60 FPS. Do UE4 jsem proto načetl základní scénu (podlaha, stěny, schody, světlo), do které jsem vložil model hlavy. Pomocí programu Fraps [p32] specializujícího se na záznam FPS jsem získal skrze tři minutová měření základní náročnost scény. Pro následující měření jsem postupně obměnil tři dříve vyexportované účesy a zjistil pokles snímků za vteřinu na základě užitého shaderu a objektové náročnosti.

Specifika testovaného počítače: Intel(R) Core(TM) i7-6800K (3.4GHz, TB 3,8GHz), 32GB RAM DDR4 2400 Mhz, pevný disk Samsung SSD 750 EVO – 500GB, grafická karta MSI GTX 970 Gaming 4G, operační systém Microsoft Windows 10 Pro 64-bit, rozlišení 1920 x 1080 pixelů.

Bez vlasů:

Měření Počet snímků/min Průměr Maximum Minimum 1 10147 169.117 176 158 2 10286 171.433 176 165 3 10220 170.333 175 161

36 19 objektů:

Měření Počet snímků/min Průměr Maximum Minimum 1 5675 94.583 124 68 2 5744 95.733 127 87 3 5731 95.517 102 84

307 objektů:

Měření Počet snímků/min Průměr Maximum Minimum 1 4412 73.533 98 65 2 4621 77.017 112 67 3 4537 75.617 100 62

1529 objektů:

Měření Počet snímků/min Průměr Maximum Minimum 1 106 1.767 6 0 2 89 1.483 3 0 3 87 1.450 3 0

Z měření objektové náročnosti je patrné, že už při aplikaci nejméně komplexního účesu dochází k poklesu zhruba o 75 snímků za vteřinu, což značí polygonovou náročnost či členitost jednotlivých objektů (v součtu je to zhruba čtyři sta tisíc polygonů, které se však vzájemně prolínají). Co se týče úrovně FPS, při aplikaci účesu o 19 objektech dosahuje scéna průměru 95 snímků, u účesu o 307 objektech průměru přibližně 75 snímků za vteřinu. Tyto případy tedy jsou použitelné v reálném čase. Oproti tomu scéna s účesem o 1529 objektech stěží dosahuje průměru dvou snímků za vteřinu, původní komplexita účesu je v Unreal Enginu nepoužitelná a objektová náročnost zde má markantní vliv. Scéna byla shora omezena na 240 FPS. Daný test byl proveden v základní, nenatexturované scéně. Pro záruku použitelnosti metody v počítačových hrách jsem otestoval model ještě ve scéně obsahující denní cyklus, nemalé množství pomocných světel a plejádu natexturovaných objektů simulující prostředí, ve kterém se hlavní postava bude běžně pohybovat. K následujícímu testu jsem v UE4 načetl středně komplexní scénu (za možnost jejího využití děkuji Bc. Rudolfu Burdovi), u které byla naměřena základní hodnota FPS. Do scény byl následně načten model včetně materiálů a pro zachování objektivního měření byl za obdobně nasimulovaných podmínek pohybu změřen interval FPS pro upravenou scénu.

Bez modelu:

Měření Počet snímků/min Průměr Maximum Minimum 1 5980 99.667 136 64 2 6553 109.217 140 67 3 5878 97.967 131 62 4 6651 110.850 140 67 5 6217 103.617 132 62 6 6015 100.250 136 64 7 6175 102.917 132 62 8 6541 109.017 143 61 9 5726 95.433 130 61 10 6374 106.233 143 61

37 S modelem:

Měření Počet snímků/min Průměr Maximum Minimum 1 5253 87.550 115 55 2 5475 91.257 121 54 3 4865 81.083 122 48 4 5495 91.583 128 56 5 5221 87.017 125 49 6 5068 84.467 120 54 7 5179 86.317 118 51 8 5433 90.550 124 51 9 4770 79.500 113 53 10 5418 90.300 121 53

Z naměřených hodnot vyplývá, že původní scéna s ojedinělými odchylkami bez problémů funguje v rozmezí 100-110 FPS. Průměr naměřených hodnot je přibližně 103.517 FPS, medián hodnot je 103.267. Při použití zrekonstruovaného shaderu je výpočetní výkon zhruba 80-90 FPS. Pokles dle průměru je přibližně 16.555 FPS, pokles dle mediánu je 15.983 FPS. Výpočty tedy ukazují, že vykreslení vlasů je z hlediska výkonu stabilní a dostatečně nenáročné na to, aby mohlo být užito v počítačových hrách. Výsledků bylo navíc dosaženo za užití komplexního shaderu a nejvyšší úrovně detailu základního enginu Unreal Engine 4, lze tedy očekávat kvalitní výsledky a lepší výpočetní časy při aplikaci na specificky zaměřených herních enginech. Při testu užit účes skládající se z 19 objektů, scéna shora omezena na 240 FPS. Výstup programu Fraps v elektronické příloze.

4.5 Aproximace Cycles materiálů

Jak bylo zmíněno v kapitole 4, systém Cycles je enginem renderovacím, k vykreslení výstupu je třeba přepočítat informace s každou iterací a proces vykreslení je proveden v konečném čase, ne však v čase reálném. Na trhu existuje řada ray tracing enginů, které dovedou danou scénu vykreslit v řádech jednotek vteřin (např. Brigade 3.0 [p33]) či komerčních enginů zpracovávajících Cycles materiály a vykreslujících je v semi-reálném čase v závislosti na složitosti shaderu (např. Armory3D [p34]), tvůrci Blenderu však aktuálně přichází s vlastním řešením vykreslení Cycles materiálů v reálném čase. Tím bude možné v reálném čase získat výstupy podobné obrázku 3.12. Inspirací k převodu materiálů se stal experimentální build PBR Viewport Branch [p35] Clémenta Foucaulta, který se poprvé objevil ve verzi 2.71 a interně převádí materiály do formy previzualizace PBR shaderů stavbou podobných materiálům UE4 s výhodou neměnných vstupů. Tyto shadery neměly stejné sofistikované vlastnosti jako při zobrazení skrze systém Cycles, jejich aproximace nicméně byla dostatečně kvalitní a vykreslování probíhalo v reálném čase. PBR Viewport Branch není nadále vyvíjen a podporován, jeho tvůrce byl totiž společností Blender Foundation přijat jako hlavní vývojář nového interního enginu Eevee [p36], který plně využívá Cycles uzlů k tvorbě materiálů a zároveň věrně aproximuje již vytvořené scény. Eevee engine by měl figurovat jako prostředník mezi fyzikálně přesným zobrazením v Cycles a exportem shaderů ve formě výstupů vhodných k rekonstrukci v klasických herních enginech (např. Unreal Engine 4), očekává se však plné nahrazení stávajících interních enginů a využitelnost enginu Eevee buď jako plnohodnotného, nebo základního herního enginu využitelného ke stavbě enginů sofistikovaných. Eevee engine je volně dostupný v experimentálních verzích programu Blender, jeho funkcionalita ovšem není kompletní. Momentálně například není funkční uzel Hair BSDF [29], který je hojně užíván ve stavbě materiálu popsaného v podkapitole 3.5. Tvůrci mají dále v plánu

38 přepracovat systém zobrazení podkožního rozptylu, upravit vlastnosti přímého a nepřímého nasvětlení a vyřešit přesnost a kvalitu odrazů. Plně funkční Eevee engine se objeví ve verzi 2.80, která bude ke stažení pravděpodobně už v roce 2018 [p37]. Na obrázku 4.4 je zobrazeno srovnání fyzikálně orientovaného renderu zachyceného v enginu Cycles a aproximace materiálů v aktuální verzi enginu Eevee. Srovnání je zobrazeno na jiném autorském modelu z důvodů dosavadní absence některých uzlů.

Obrázek 4.4: Srovnání výstupu enginu Cycles (nahoře) s aproximací shaderů skrze aktuální verzi enginu Eevee (dole).

39 5 Kvalitativní a kvantitativní srovnání

V páté kapitole jsem svůj model podrobil dvěma testům – kvalitativnímu a kvantitativnímu. Ještě před několika lety byly hlavním měřítkem kvality postavy detail modelu i textur. S tím souviselo i měřítko kvantitativní – z kolika polygonů se postava skládá. Z obecného hlediska se bralo v potaz, že čím více polygonů, tím lépe pro tvar i detail modelu. O této myšlence je možné říci, že je zároveň pravdivá i nepravdivá. Lze zcela jednoznačně a bez nutných ukázek rozhodnout, že model koule tvořený deseti polygony ji bude připomínat méně než model tvořený tisíci polygony. Na druhou stranu obdelník tvořený jedním polygonem bude mít stejný tvar a detail jako obdelník ze sta polygonů. Záleží tedy na individuální komplexitě daného modelu a na tvůrci, aby rozhodl, jakou polygonální zátěž je v daném případě vhodné použít. Dříve se muselo hledět na limity grafických karet a herních enginů, které tvůrce omezovaly v kreativitě v závislosti na polygonové zátěži. Proto bylo zvykem původní modely polygonálně redukovat a řada detailů byla tvořena pouze normálovými a displacement mapami. Jednou za čas přišla hra, která v dobách dvaceti tisíc polygonů na hlavní postavu slibovala dvakrát tolik (zmíněný Uncharted 2 – postava Nathana Drakea 37 000 polygonů, vlasy 4 000 polygonů), což vyvolávalo diskuze o jejích silných grafických kvalitách. V dnešní době (zvláště s již zmíněným příchodem DirectX 12) jsou díky novým postupům a technologiím tyto limity mnohem vyšší a ne zcela jasně vymezené. Proto je dnes možné a běžné vidět v moderních hrách postavy tvořené stotisícem polygonů. Jiné firmy mají k tvorbě jiný přístup a zdokonalují kvalitu textur, nasvětlení a materiálů, aby jejich postavy mohly být tvořeny co nejméně polygony, které lze využít pro detailnější prostředí či vykreslení více postav (příkladem může být Metal Gear Solid V v podkapitole 5.2.5 Herní série Metal Gear). Postupná eliminace těchto limit má i jistou nevýhodu, která v daném momentě částečně koliduje s náplní této kapitoly. Protože herní designéři nadále nemají tak intenzivní potřebu lákat potenciální hráče na polygonální komplexitu svých her, jsou tyto informace hůře dohledatelné, což omezuje výběr her pro kvantitativní test. Proto se v této kapitole objeví i hry starší, ne však příliš staré, a neobjeví se některé hry moderní, které jsem chtěl pro srovnání využít.

5.1 Základní přehled

Nejprve předkládám souhrn grafu a informací o několika moderních hrách, které nastíní moderní měřítka polygonální komplexity pro nastavení parametrů kvantitativního srovnání.

Obrázek 5.1: Polygonový srovnávací graf pro hlavní postavy několika vybraných her [p38].

40 Následující informace lze ověřit zde [p39]:

The Order 1886 (únor 2015) – přibližně 100 000 polygonů Infamous Second Son (březen 2014) – přibližně 120 000 polygonů Final Fantasy XV (listopad 2016) - přibližně 100 000 + 20 000 polygonů

Další informace ověřitelné zde [p40]:

Metal Gear Solid V: Ground Zeroes (březen 2014) – přibližně 18 000 polygonů Deus Ex: Human Revolution (srpen 2011) – přibližně 26 000 polygonů Uncharted 2 (říjen 2009) – přibližně 37 000 + 4 000 polygonů

Předložená data uvádějí, že počet polygonů tvořících hlavní postavu může být silně variabilní, zhruba od dvaceti do sto dvaceti tisíc. Daný počet polygonů může být závislý na době, kdy byla hra vytvořena (například z roku 2007 versus Ryse z roku 2013), zároveň se však nejedná o jistou formu zákonitosti (Uncharted 2 versus MGS V: GZ). Pokud je užito správných metod, může hlavní postava dosahovat dokonce několikanásobně vyšších hodnot. Příkladem může být hra Horizon: Zero Dawn (2017), která se momentálně pyšní největším užitým počtem polygonů na postavu/bytost – model robota Thunderjaw dle oficiálních informací dosahuje hodnoty pěti set padesáti tisíc polygonů [p41]. Není však jisté, zda se jedná o sít čtyřúhelníkovou či trojúhelníkovou, počet trojúhelníků by tedy mohl dosahovat až dvojnásobné hodnoty. Model postavy i se všemi vlasy se v závislosti na detailu polygonově pohybuje od čtyř set padesáti do pěti set padesáti tisíc trojúhelníků, z hlediska kvantity se tedy jedná o náročnější model, zároveň však nepřekračuje nejvyšší dosaženou polygonovou hranici. Tento způsob je momentálně díky své polygonové náročnosti lehce neefektivní, nebyly však doposud užity žádné metody redukce vykreslovaných polygonů (například occlusion culling [30]) a zmiňovaný DirectX 12 podporující teselaci, která tyto hodnoty činí poměrně zanedbatelnými. Je však třeba připustit, že majoritní podíl na celkové polygonové zátěži modelu mají právě vlasy, které čitají až čtyři sta tisíc polygonů. Z toho důvodu lze říci, že z kvantitativního hlediska je tento systém tvorby vlasů pravděpodobně nejnáročnější (nebereme-li v potaz složitost hair strands). Pro kvalitativní srovnání je třeba srovnat model se specifickými hrami.

5.2 Výběr deseti nejlepších her

Do výběru deseti nejlepších se dostaly moderní hry, které v době vydání svým vizuálem oslnily herní svět či dokázaly nastavit nebo udržet laťku pro vývoj následujících let. Vybranými kandidáty jsou:

Deus Ex: Human Revolution (srpen 2011) Metal Gear Rising: Revengeance (únor 2013) The Last of Us (červen 2013) GTA V (září 2013) Ryse: Son of Rome (listopad 2013) Metal Gear Solid V: Ground Zeroes (březen 2014) Dragon Age: Inquisition (listopad 2014) The Order: 1886 (únor 2015) Final Fantasy XV (listopad 2016) Star Citizen (stále ve vývoji)

41 5.2.1 Deus Ex: Human Revolution

Protože tyto hry bude lepší procházet převážně chronologicky, začneme rozborem nejstarší hry na seznamu Deus Ex: Human Revolution [p42] z roku 2011. Toto netradiční kyberpunkové RPG, volně navazující na a doplňující příběh původního Deus Ex z roku 2000, je výsledkem spolupráce herních studií Eidos Montreal, Nixxes Software a Feral Interactive vydaným společností Square Enix. Získalo velmi vysoká hodnocení u světově známých a uznávaných herních serverů (Metacritic 90/100, Eurogamer 9/10, Game Informer 8.5/10, IGN 9/10) a bylo mimo jiné nominováno na cenu Spike VGX [p43] za nejlepší RPG a na BAFTA Games Award [p44] za nejlepší strategii a akční hru. Častým tématem byla i grafická stránka hry, která svým barevným tónem, temnou a ponurou atmosférou či hustotou interaktivních objektů dodávala noirově laděnému příběhu patřičnou hloubku. Modely postav byly zvláštní tím, že jejich pokožka nereagovala na světlo a byla pouze otexturovaná, nicméně samotná textura zvýrazňovala hrany a rysy a výběrem barev dodávala iluzi nasvětlení. Řekl bych však, že hlavním problémem grafického zpracování ústřední postavy byly právě vlasy. Ty byly součástí modelu hlavy, takže byly statické a postrádaly objem. To by ničemu nevadilo, horší byla úroveň kvality a detailu vlasové textury, která umělecký zážitek ze hry lehce snižovala.

Obrázek 5.2: Srovnání modelu s hlavním představitelem hry Deus Ex: Human Revolution (originál na [p45])

Ústřední postava Adama Jensena (na obrázku 5.2) byla tvořena 25 953 polygony [p40], což je zhruba dvacetinová zátěž našeho modelu. Je samozřejmě potřeba brát v potaz i šestiletý rozdíl mezi oběma modely a přístupnými technologiemi, nicméně už i při zběžném srovnání lze na našem modelu vyčíst jemnost vlasů a plasticitu vousů včetně reakce na světelné podněty. Podobných výsledků mohla hra dosáhnout již v době svého vydání skrze lepší otexturování a detailnější model (pokud by na vlasy hlavní postavy byl vymezen obdobný polygonový rozpočet jako u o dva roky staršího Uncharted 2, výsledek by i bez polygonových pruhů díky dodání třetího rozměru u vlasů vypadal realističtěji a celková polygonová zátěž by nepřesáhla hranici třiceti tisíc).

42 5.2.2 The Last of Us

Druhým kandidátem je hra The Last of Us [p46] studia , tvůrců herní série Uncharted. Bez nadsázky lze říci, že se jedná o jednu z nejlepších her nejen roku 2013, ale také celé herní historie. K podložení těchto slov stačí výčet ocenění - BAFTA Games Award za nejlepší hru, akční adventuru, příběh, herecký výkon; Spike VGX za nejlepší hru pro Play Station, nejlepší mužský výkon, studio roku; Kerrang! Award [p47] za nejlepší videohru. Její kvalita se odráží i ve velmi vysokých hodnoceních – Metacritic 95/100, Eurogamer 10/10, Game Informer 9.5/10, IGN 10/10. Chvály se dočkala také vizuální stránka hry, a to jak po grafické, tak po umělecké stránce. Ve své době byla označována jako nejlepší a nejrealističtější hru vytvořenou na konzoli PlayStation 3 [p48, p49]. Zvláště hlavní postavy byly zpracovány velmi detailně.

Obrázek 5.3: Srovnání modelu s hlavní představitelkou hry The Last of Us (originál na [p50])

Hlavní hrdinka Ellie (obrázek 5.3) je tvořena 31 537 trojúhelníky [p50]. Vlasy jsou tvořeny polygonovými pásy s texturou užívající průhlednosti (varianta metod Alpha blend/test/to coverage). Ze srovnávacího výstupu je patrné, že tvůrci užili velmi detailní vlasové textury, díky které může výstup působit lehce kresebně, ale dokonale koreluje s užitým stylem grafického zpracování. Oproti našemu modelu je díky textuře dosaženo silnějšího ohraničení pramenů vlasů a přestože nejsou reálné, z uměleckého hlediska jsou odlesky výraznější a dodávají účesu zcela nový rozměr.

43 5.2.3 GTA V

Třetí srovnávanou hrou je momentálně nejaktuálnější díl série Grand Theft Auto, akční adventura GTA V [p51] od tvůrčí a vydavatelské firmy a jejích přidružených studií (Rockstar North, Rockstar San Diego, Rockstar Toronto, Rockstar Leeds, Rockstar London, Rockstar New England). Stejně jako obě předchozí, i tato hra získala velmi pozitivní ohlasy (Metacritic 97/100, Eurogamer 9/10, Game Informer 9.75/10, IGN 10/10) a řadu ocenění – BAFTA Games Award za nejlepší britskou hru, design, multiplayer; Spike VGX za nejočekávanější hru, hru roku, soundtrack. Graficky je GTA V velmi zdařilým počinem, který využívá prvků realismu s lehce komixovým nádechem znatelným zejména na texturách zvýrazněných záhybů oblečení (podobné směsi využívá GTA V i v příběhu, který hráči připomíná každodenní život okořeněný přehnanými, absurdními situacemi).

Obrázek 5.4: Srovnání modelu s hlavní postavou hry Grand Theft Auto V (originál na [p52])

Problémem, který můžeme brát také jako stylistycký podpis her od společnosti Rockstar, je forma výsledného zobrazení postav i prostředí evokující jistou úroveň umělosti, která se projevuje také na výsledném vzhledu vlasů. Na přiloženém obrázku vlevo dole za naším modelem můžeme vidět, že vlasy jsou samostatným objektem, který lze v závislosti na hráčových rozhodnutích změnit. Proto je záhadou nevyužitý potenciál při tvorbě vlasů viditelný nejen v relativně nízké, leč stále dostačující polygonové kvalitě objektu, ale zejména v nízké a prameny nespecifikující textuře. Místy modely vyvolávají dojem, že k zobrazení vlasů bylo užito pouze nereflektujícího jedno- barevného materiálu, což může korelovat s domnělou komixovou vizualizací. Hlavní postava Michaela De Santy (na obrázku 5.4) je tvořena 30 914 polygony [p52].

44 5.2.4 Ryse: Son of Rome

Ryse: Son of Rome [p53] vytvořená společností Crytek byla v době svého vývoje považována za jednu z her s největším polygonovým rozpočtem na hlavní postavu (před optimalizací byla tvořena zhruba sto padesáti tisíci polygony). I po následné redukci na přibližně osmdesát pět tisíc polygonů se jednalo o nadstandartní polygonový rozpočet, jež měl za úkol ukázat sílu konzole XBOX ONE a svým detailním zpracováním měl zaujmout i počítačové hráče. Přestože nevyhrála žádná ocenění a získala spíše průměrná hodnocení (Metacritic 60/100, Eurogamer 5/10, Game Informer 6/10, IGN 6.8/10), svým grafickým závazkům jako jedna z vlajkových lodí pro XBOX ONE hra Ryse: Son of Rome dostála.

Obrázek 5.5: Srovnání modelu s hlavní postavou hry Ryse: Son of Rome (originál na [p54])

Díky nedostatečně specifikovaným informacím nelze říci, z kolika polygonů se hlavní postava Maria Tita (na obrázku 5.5) skládá. Oficiálně se mluví o přibližně osmdesáti pěti tisících polygonech. Problém nastává ve výkladu termínu polygon při tvorbě počítačových her. Ve valné většině případů jsou polygony myšleny čtyřúhelníky, někdy se však i přes rozdílné označení mluví o trojúhelnících. Díky oficiálnímu materiálu [p55] ke hře je možné, že se při zmínce o polygonech jedná o trojúhelníky místo čtyřúhelníků. V takovém případě by hlavní postava byla tvořena přibližně čtyřiceti dvěma tisíci polygony. Nezávisle na kvantitativním srovnání si lze povšimnout detailního zpracování vlasů, které je tvořeno polygony či polygonovými pruhy s průhledností skrze texturu (obdobně jako u hry The Last of Us). Všimněme si na okamžik jemnosti jednotlivých pramenů na boku hlavy. Kaskádovitým způsobem pokládání polygonů lze úspěšně docílít realistického vzhledu překrývajících se vlasů.

45 5.2.5 Herní série Metal Gear

Metal Gear Rising: Revengeance [p56] a Metal Gear Solid V: Ground Zeroes [p57] s naším modelem porovnáme dohromady. Obě hry byly vytvořeny studiem Kojima Productions a vydány společností Konami jako součást série Metal Gear tvůrce Hidea Kojimy. Tato série je známá především komplexitou a nelineárním vyprávěním svého příběhu či poněkud netradičním přístupem k hratelnosti během velkých soubojů (v případě prvního dílu Metal Gear Solid se například jednalo o přepojení ovladače do jiného konzolového portu). Srovnáním obou her během jedné podkapitoly můžeme zároveň nahlédnout na více metod grafického zprxacování vytvořených stejným studiem.

Obrázek 5.6: Model hlavní postavy hry Metal Gear Rising: Revengeance a srovnání s modelem (originál na [p58])

46 Metal Gear Rising: Revengeance (Metacritic 80/100, Eurogamer 9/10, Game Informer 7.75/10, IGN 8.5/10) je hra zaměřená na bojový aspekt celé série, jedná se o lineární akční hack and slash hru. Díky omezenému hernímu prostředí má postava Raidena (na obrázku 5.6) oproti ostatním dílům poměrně bohatý polygonální rozpočet – 68 016 trojúhelníků, tedy přibližně třicet čtyři tisíc polygonů (zdroj pro ověření k nalezení na hypertextovém odkazu u přiloženého obrázku), které využívá k detailnímu zpracování a zobrazení základního modelu. Dle skladby a výsledného zobrazení lze usoudit, že vlasy jsou kombinací klasického modelu s polygonovými pruhy.

Obrázek 5.7: Srovnání modelu s hlavní postavou hry Metal Gear Solid V: Ground Zeroes (originál na [p59])

Metal Gear Solid V: Ground Zeroes (Metacritic 75/100, Eurogamer 9/10, Game Informer 7.0/10, IGN 8.0/10) je naopak hra s otevřeným herním prostředím zabývající se především taktickou a špionážní stránkou série, ústřední postava Snake/Big Boss (obrázek 5.7) je tedy polygonálně levnější, na všeobecné poměry dokonce střídmá – pouhých 18 210 polygonů [p52]. Pro zobrazení detailu užívá model kombinaci světla a klasických/modifikačních textur. I zde dokážeme rozeznat polygonové pruhy s průhledností skrze texturu.

V obou případech lze říci, že přes svou nízkou či průměrnou kvantitativní hodnotu tyto hry dosahují vysoké grafické kvality. Důvodem je cit pro detail ve fázi aplikace textur a vhodných metod post-processingu [p60] (především různé úrovně rozmazání). Tímto způsobem dokáže studio Kojima productions skrýt nedostatky svých nízkopolygonálních modelů (vhodnými normálovými a displacement texturami lze zjemnit hrany modelu, dalšího zjemnění je dosaženo rozmazáním). Místy tyto nedostatky (zvláště hranatost a zubatost vlasů hrdiny obrázku 5.7) lze detekovat, nicméně na první pohled patrné nejsou.

47 5.2.6 Dragon Age: Inquisition

Sedmou hrou na našem seznamu je Dragon Age: Inquisition [p61] (Metacritic 85/100, Eurogamer 8/10, Games Informer 9.5/10, IGN 8.8/10) od herního studia Bioware. Tito vývojáři mají za sebou několik úspěšných hermích sérií se zaměřením na tvorbu a vývoj vlastní postavy (RPG), mezi nejznámější krom Dragon Age patří mimo jiné Baldur's Gate, Neverwinter Nights či Mass Effect. Jejich znalosti a zkušenosti proto hře Dragon Age: Inquisition přinesly několik ocenění (The Game Award [p62] za nejlepší RPG a hru roku, GLAAD Media Award [p63] – zvláštní uznání). Dvě desetiletí v popředí herního designu se projevily i na pohádkově laděném vizuálu či na velmi pokročilé tvorbě herní postavy (jak graficky, tak variabilitou).

Obrázek 5.8: Srovnání modelu s tvorbou postavy ve hře Dragon Age: Inquisition (originál na [p64])

Celkový dojem na jinak skvěle vytvořeném modelu bohužel kazí právě vlasy. Z obrázku lze vyčíst, že se jedná o polygonální pruhy aplikované na model hlavy s texturou vlasů. Rozdíl mezi texturou na hlavě a pruzích je barevně zřetelný, překrytí hlavy polygonovými pruhy je poměrně odbyté. Zalomení vlasů viditelné na účesu vlevo nahoře je nepřirozené, společně s pravou části ukazuje nedokonalosti v podobě hranatosti a zubatosti způsobené nedostatečným detailem objektů. Slabá kvalita vlasové textury tyto nedokonalosti o to více zvýrazňuje.

48 5.2.7 The Order: 1886

Titulem The Order: 1886 [p65] se dostáváme ke hrám dosahujícím či přesahujícím hranice sta tisíc polygonů. Můžeme tedy očekávat velký posun v grafickém zpracování. A The Order: 1886 studií Ready at Dawn a SCE je pro to dobrým odrazovým můstkem. Přes smíšená a průměrná hodnocení (Metacritic 63/100, Eurogamer bez hodnocení, Game Informer 7.75/10, IGN 6.5/10) se většina herních kritiků shodla, že silnou stránkou hry je její atmosféra silně podpořena velmi kvalitním grafickým zpracováním.

Obrázek 5.9: Srovnání modelu s hlavní postavou hry The Order: 1886 (originál na [p66])

Z přiloženého obrázku 5.9 to v rámci velikosti a rozlišení není patrné, ale podíváme-li se na originál, uvidíme hlavně na vlasech kolem ucha a vzadu na hlavě, že jsou opět vytvořeny skrze kombinaci modelu hlavy a polygonových pruhů. Při tvorbě vlasových textur dle mého názoru došlo buď k použití nízkého rozlišení, nebo špatné metodě nastavení průhlednosti (pravděpodobně Alpha test), protože jednotlivé vlasy jsou velmi zubaté. Protože jsme se díky roku vydání a překročení sta tisíc polygonů přiblížili kvalitám našeho modelu, podívejme se na něj zblízka. Na rozdíl od hlavního protagonisty hry The Order:1886 nemá naše postava zubaté konečky. Díky užití shaderu místo textury nemůže dojít k nízkému rozlišení na jednotlivých pramenech (v případě užití textury na našem modelu by ona nesla pouze informaci o barvě a celkové viditelnosti/průhlednosti). Jak jsme si ukázali v podkapitole 3.4.3 Ovlivnění v závislosti na textuře, můžeme nastavit jemnost či tvrdost vlasů, čímž dokážeme případnou zubatost zjemnit či vizuálně zcela eliminovat.

49 5.2.8 Final Fantasy XV

Nejnovějším vydaným titulem našeho Top Ten seznamu je dosud poslední díl herní série Final Fantasy. Final Fantasy XV [p67] vývojářů Square Enix, XPEC Entertainment, HexaDrive, Umbra a Streamline Studios byl vydán 29. listopadu roku 2016. Tato akční RPG adventura získala mnoho ocenění od uznávaných herních serverů a magazínů (mimo jiné i šest ocenění za nejlepší hru roku) a stihla sesbírat velmi kladná hodnocení (Metacritic 82/100, Game Informer 8.5/10, IGN 8.2/10). Dá se říci, že po grafické stránce patří série Final Fantasy mezi to nejlepší, co může východní herní průmysl světu nabídnout.

Obrázek 5.10: Srovnání modelu s jednou z hlavních postav hry Final Fantasy XV (originál na [p68])

Moderní asijská grafická kultura (komix, animovaný film, hra) se u postav vyznačuje jemnými rysy a extravagantními účesy. Proto nelze očekávat realistický výstup, ale můžeme se podívat na realistickou formu texturového a materiálového zpracování. Videorecenze [p69] demoverze hry ukazuje v čase 4:49 průsvitnost vlasového materiálu proti světelným paprskům, což je oproti dosavadním hrám na našem seznamu příjemná změna, je tomu tak ovšem pouze u hlavního hrdiny. Jedním z důvodů, proč je Final Fantasy XV svým fyzikálním zobrazením omezena pouze na hratelnou postavu, je více způsobů tvorby vlasů. Vlasy hrdiny jsou tvořeny metodou Hair strands (kvůli nedostatku informací nelze určit, zda použitý Luminous Studio engine používá interní systém či modifikové NVIDIA Hairworks), ostatní postavy užívají převážně polygonové pruhy s texturou (vizme hrdinu veprostřed obrázku 5.10). Ty světlo nepropouští a užitá textura převážně v přední části účesu vyvolává dojem umělosti, což v kontrastu s účesem tvořeným hair strands působí nelichotivě, zvlášť při vymezení dvaceti tisíc polygonů na účes. Jedním z důvodů této volby může být již zmíněná grafická náročnost hair strands.

50 5.2.9 Star Citizen

Posledním příspěvkem pro srovnání je stále vyvíjený vesmírný simulátor Star Citizen [p70] od vývojářského studia Cloud Imperium Games. Jeho zajímavostí je, že je zcela financován fanoušky hry a celkový rozpočet ke konci roku 2017 přesahuje 173 milionů amerických dolarů. Díky tomu mohou tvůrci užívat unikátních metod modelování (u postav se jedná o detailní skeny hlav, u kterých dle slov tvůrců lze měnit jednotlivé prvky – oči, uši, nos – nezávisle na pleti [p71]). Tvůrce videa zároveň poznamenává, že vývojáři momentálně nemají vyřešenu metodu realistického zobrazení vlasů. Z následujícího obrázku se lze přesvědčit, že vlasy u postav jsou momentálně výsledkem skenování postavy a přidání textury.

Obrázek 5.11: Srovnání modelu s jednou z hlavních postav hry Star Citizen (originál na [p66])

Vlasy i vousy mají díky skenu poměrně realistický vzhled, ale postrádají plasticitu. Nutno znovu podotknout, že se jedná o hru ve vývoji a zobrazení vlasů není dosud vyřešeno. Dovedu si však představit, že hra využívající realistických skenů a lodí o celkové kvantitativní hodnotě několika milionů polygonů využije metody, kterou dosáhne nejlepších výsledků. Pokud navíc upřednostňuje hráčovu svobodu, mohla by užít variabilního systému účesů, který by mohl fungovat podobným způsobem jako ten, který jsem v této práci popsal.

51 5.3 Anketa

V rámci kvalitativního srovnání byla vytvořena anketa, kterou vyplnilo 25 respondentů. Jednalo se o muže (16) a ženy (9) převážně ve věku 20 – 29 let (22 z 25 dotazovaných) s různou zkušeností ohledně hraní počítačových her (7 častých hráčů, 6 občasných hráčů, 8 příležitostných hráčů a 4 lidé, kteří hry nehrají). Těm bylo prvně předloženo několik otázek ohledně spokojenosti a požadavků na grafické zpracování a volnost při tvorbě herních postav. Na otázku „Jste spokojeni s výběrem a zpracováním účesů v počítačových hrách/hrách s možností tvorby vlastní postavy?“ odpovědělo 8 respondentů kladně, 7 záporně, 3 v závislosti na hře, 2 lidé problematiku neřeší a 5 dotazovaných se zdrželo odpovědi. U otázky „Chtěli byste mít ve hře možnost tvorby vlastních účesů?“ se 10 dotazovaných vyjádřilo kladně, 3 záporně, 2 respondenti nejsou rozhodnuti a 10 z nich je to jedno. Poslední otázka „Chtěli byste ve hrách podporu růstu vlasů?“ získala 13 kladných hlasů, 2 záporné hlasy, dále 5 nerozhodných hlasů a 8 respondentům je to jedno. Následně dotazovaní odpovídali na deset otázek týkajících se srovnání z hlediska zpracování vlasů. Zohledněn byl především detail, komplexita, realistické zobrazení a celkový dojem. Hry byly srovnávány s výstupem programu Blender pomocí výběru snímků a známky na škále 1 až 9.

Srovnávaná hra Hlasů pro hru Hlasů pro metodu Deus Ex: Human Revolution 5 (6) 20 (17) The Last of Us 9 (6) 16 (15) GTA V 7 (7) 18 (16) Ryse: Son of Rome 14 (13) 11 (9) Metal Gear Solid V: Ground Zeroes 7 (5) 18 (17) Dragon Age: Inquisition 7 (3) 18 (18) The Order: 1886 13 (10) 12 (10) Final Fantasy XV 14 (8) 11 (12) Star Citizen 14 (13) 11 (10) Metal Gear Rising: Revengeance 14 (10) 11 (10)

Posledních deset otázek bylo koncipováno stejně jako předešlá série, hry byly ovšem srovnány s texturovým výstupem zpracovaném v Unreal Engine 4. Cílem bylo zjistit, zda i ve své základní a specifickými materiály neupravené formě může testovaná metoda konkurovat metodám běžně užívaným v počítačových hrách.

Srovnávaná hra Hlasů pro hru Hlasů pro metodu Deus Ex: Human Revolution 19 (16) 6 (6) The Last of Us 14 (12) 11 (9) GTA V 17 (16) 8 (7) Ryse: Son of Rome 25 (20) 0 (2) Metal Gear Solid V: Ground Zeroes 14 (10) 11 (12) Dragon Age: Inquisition 15 (11) 10 (9) The Order: 1886 24 (19) 1 (4) Final Fantasy XV 22 (16) 3 (5) Star Citizen 24 (18) 1 (3) Metal Gear Rising: Revengeance 17 (10) 8 (11)

Anketa je dostupná na stránce https://surveynuts.com/surveys/admin?id=137473 (login [email protected], heslo a73eabbecf) nebo v elektronické příloze ve formátech ODF a XLS.

52 6 Závěr

Tato práce především zastává funkci dokumentace systému pro dynamickou a variabilní tvorbu účesů. Zobrazuje proces jeho tvorby a výhody vůči zavedeným principům v herním průmyslu. Srovnává jej s aktuálně datovanými AAA tituly, které byly v době svého vydání oficiálně oceněny či považovány za vrchol grafického zpracování. Budoucím vývojářům může posloužit jako základní kámen či bod, od kterého se mohou odrazit. Testem poklesu snímků za vteřinu bylo prokázáno, že metoda je v reálném čase plně využitelná. Výsledky ankety, které se zúčastnilo 25 respondentů, dokazují využitelnost vytvořené metody v herním průmyslu. Základní a specifickými materiály neupravený výstup v jejich hodnocení skrze výběr snímků konkuroval dvěma hrám a proti osmi zbylým zaostával, při známkování na škále však nad dvěma srovnávanými hrami zvítězil a dvěma konkuroval. Po užití realistických shaderů výstup při srovnání snímků úspěšně předčil pět z deseti her a zbylým konkuroval, při hodnocení na škále zvítězil nad šesti a konkuroval třem hrám. Ze škálového hodnocení byly vynechány hlasy hodnotící známkou 5 jako nerozhodné a za konkurenceschopnost je považován rozdíl v hodnocení maximálně tři hlasy. Dle dotazovaných je tedy metoda konkurenceschopná mezi komerčně úspěšnými tituly. Anketa také dokumentuje požadavky podpory růstu vlasů a tvorby vlastních účesů, které je metoda díky své interní stavbě schopna splnit.

6.1 Na začátku cesty...

V době vydání práce byl daný systém ve vývoji pouze několik měsíců, aktuální iterace se formou tvorby či grafického výstupu může lišit. I přes zdařilé a kvalitní výsledky je systém prakticky na začátku svého vývoje a cílový produkt by měl splňovat následující body:

• správná forma optimalizace modelu vlasů (polygonální redukce) • úprava kódu do formy nezávislého programu • připojení pluginu či metody na přesné a uživatelsky přívětivé ovládání/česání vlasů • vyladění shaderu do tvaru PBR s podporou náhodných šedin a nastavitelných melírů • možnost nastavení typu vlasů dle LOIS nebo FIA klasifikace [p72] • plná podpora tvorby a růstu kudrnatých vlasů bez nutnosti definovat profil pramene • realistické fyzikální simulace aplikované na jednotlivé prameny

I bez splnění těchto podmínek však lze prototyp úspěšně použít pro vývoj her či tvorbu videí. Již v této iteraci dokáže v mnoha ohledech předstihnout mnohé zavedené a užívané postupy, po jeho finalizaci se s trochou štěstí snad stane jedním z milníků ve vývoji dynamiky a variability tvorby herních účesů. Na závěr předkládám poslední náhled aktuální verze v plné velikosti.

53 54 Seznam použité literatury

[1] DU MONT ALLEN B LAB INC, 1948. Cathode-ray tube amusement device. Inventors: Thomas T. GOLDSMITH Jr. a Estle Ray MANN. United States of America. US 2455992 A. 14. 12. [cit. 14. 12. 2017]. Dostupné z: http://www.pong-story.com/2455992.pdf

[2] WILKES, M. V. a RENWICK, W., 1950. The EDSAC (Electronic delay storage automatic calculator). In: Mathematics of Computation [online]. 4(30), 61-65 [cit. 14. 12. 2017]. ISSN 1088-6842. Dostupné z: http://www.ams.org/journals/mcom/1950-04-030/S0025-5718-1950-0037589-7/

[3] MARSCHNER, Stephen R., JENSEN, Henrik Wann, CAMMARANO, Mike, WORLEY, Steve a HANRAHAN, Pat, 2003. Light Scattering from Human Hair Fibers. In: ACM Transactions on Graphics. 22(3) (July 2003), 780-791 [cit. 14. 12. 2017]. Dostupné z: http://www.graphics.stanford.edu/papers/hair/hair-sg03final.pdf

[4] ZINKE, Arno a WEBER, Andreas, 2007. Light scattering from filaments. In: IEEE Transactions on Visualization and Computer Graphics. 13(2) (March 2007), 342 – 356 [cit. 14. 12. 2017]. Dostupné z: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.94.1025&rep=rep1 &type=pdf

[5] ZINKE, Arno, RUMP, Martin, LAY, Tomás, WEBER, Andreas, ANDRIYENKO, Anton a KLEIN, Reinhard, 2009. A practical approach for photometric acquisition of hair color. In: ACM Transactions on Graphics. 28(5) (December 2009), 165:1-165:9 [cit. 14. 12. 2017]. Dostupné z: https://dl.acm.org/citation.cfm?doid=1618452.1618511

[6] D'EON, Eugene, GUILLAUME, Francois, HILL, Martin, LETTERI, Joe a AUBRY, Jean- Marie, 2011. An Energy-Conserving Hair Reflectance Model. In: EGSR '11 Proceedings of the Twenty-second Eurographics conference on Rendering. 1181-1187 [cit. 14. 12. 2017]. Dostupné z: http://www.eugenedeon.com/wp-content/uploads/2014/04/egsrhair.pdf

[7] SADEGHI, Iman, PRITCHETT, Heather, JENSEN, Henrik Wann a TAMSTORF, Rasmus, 2010. An artist friendly hair shading system. In: ACM Transactions on Graphics. 29(4) (July 2010), 56:1-56:10 [cit. 14. 12. 2017]. Dostupné z: http://disney-animation.s3.amazonaws.com/library/a56-sadeghi.pdf

[8] Tessellation Stages, 2017 [online]. Microsoft. [cit. 14. 12. 2017]. Dostupné z: https://msdn.microsoft.com/en-us/library/ff476340(v=VS.85).aspx

[9] NVIDIA HairWorks, 2017 [online]. NVIDIA Corporation. [cit. 14. 12. 2017]. Dostupné z: https://developer.nvidia.com/hairworks

[10] WEISSTEIN, Eric W., 2017. Bézier Curve. In: MathWorld [online]. [cit. 14. 12. 2017]. Dostupné z: http://mathworld.wolfram.com/BezierCurve.html

[11] Particles – Introduction, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://www.blender.org/manual/physics/particles/introduction.html [12] Using NVIDIA HairWorks, 2016 [online]. NVIDIA Corporation. [cit. 14. 12. 2017]. Dostupné z: http://docs.nvidia.com/gameworks/content/artisttools/hairworks/ Using_HairWorks.html

[13] KRANICH, Jan, 1925. Přehledy věd přírodních. Dílu I, část 1. Tělověda-zoologie-botanika [online]. Olomouc: Nakladatelství R. Prombergra. [cit. 14. 12. 2017]. Dostupné z: http://kramerius4.nkp.cz/search/i.jsp?pid=uuid:bc7b36c0-8c0a-11e3-8031- 001018b5eb5c

[14] Displace Modifier, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/modeling/modifiers/deform/ displace.html

[15] DUNBAR, Daniel, ROOSENDAAL, Ton, BATT, Ben, LOMMEL, Brecht van a BARTON, Campbell, 2005. MOD_displace.c. In: Blender Foundation [online]. [cit. 14. 12. 2017]. Dostupné z: https://developer.blender.org/diffusion/B/browse/master/source/blender/ modifiers/intern/MOD_displace.c;7dc328e8a1cea0f1ea0b8848a38ce7521401ca8b$196

[16] Subdivision Surface Modifier, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/modeling/modifiers/generate/ subsurf.html

[17] CATMULL, Edwin a CLARK, Jim, 1978. Recursively generated B-spline surfaces on arbitrary topological meshes. In: Computer Aided Design. 10(6) (November 1978), 350-355 [cit. 14. 12. 2017]. Dostupné z: https://people.eecs.berkeley.edu/~sequin/CS284/PAPERS/CatmullClark _SDSurf.pdf

[18] DUNBAR, Daniel, ROOSENDAAL, Ton, BATT, Ben, LOMMEL, Brecht van a BARTON, Campbell, 2005. MOD_subsurf.c. In: Blender Foundation [online]. [cit. 14. 12. 2017]. Dostupné z: https://developer.blender.org/diffusion/B/browse/master/source/blender/ modifiers/intern/MOD_subsurf.c;7dc328e8a1cea0f1ea0b8848a38ce7521401ca8b

[19] Curve Modifier, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/modeling/modifiers/deform/curve.html

[20] DUNBAR, Daniel, ROOSENDAAL, Ton, BATT, Ben, LOMMEL, Brecht van a BARTON, Campbell, 2005. MOD_curve.c. In: Blender Foundation [online]. [cit. 14. 12. 2017]. Dostupné z: https://developer.blender.org/diffusion/B/browse/master/source/blender/ modifiers/intern/MOD_curve.c;7dc328e8a1cea0f1ea0b8848a38ce7521401ca8b

[21] Decimate Modifier, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/modeling/modifiers/generate/ decimate.html

[22] DUNBAR, Daniel, ROOSENDAAL, Ton, BATT, Ben, LOMMEL, Brecht van a BARTON, Campbell, 2005. MOD_decimate.c. In: Blender Foundation [online]. [cit. 14. 12. 2017]. Dostupné z: https://developer.blender.org/diffusion/B/browse/master/source/blender/ modifiers/intern/MOD_decimate.c;7dc328e8a1cea0f1ea0b8848a38ce7521401ca8b [23] Principled Node, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/render/cycles/nodes/types/shaders/ principled.html

[24] GREENBERG, Donald P., TORRANCE, Kenneth E., SHIRLEY, Peter, ARVO, James, LAFORTUNE, Eric, FERWERDA, James A., WALTER, Bruce, TRUMBORE, Ben, PATTANAIK, Sumanta a FOO, Sing-Choong, 1997. In: SIGGRAPH '97 Proceedings of the 24th annual conference on Computer graphics and interactive techniques. 477-494 [cit. 14. 12. 2017]. ISBN:0-89791-896-7. Dostupné z: http://www.graphics.cornell.edu/pubs/1997/GTS+97.pdf

[25] PHARR, Matt a HUMPHREYS, Matt, 2004. Physically Based Rendering: From Theory to Implementation [online]. Amsterdam: Nakladatelství Elsevier. [cit. 14. 12. 2017]. Dostupné z: https://books.google.cz/books?id=DirOQ_PELlgC&hl=cs&source=gbs_book _other_versions

[26] Mix Node, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://www.blender.org/manual/render/cycles/nodes/types/shaders/mix.html

[27] Add Node, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://www.blender.org/manual/render/cycles/nodes/types/shaders/add.html

[28] Math Node, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/compositing/types/converter/math.html

[29] Hair Node, 2017 [online]. Blender Foundation. [cit. 14. 12. 2017]. Dostupné z: https://docs.blender.org/manual/en/dev/render/cycles/nodes/types/shaders/ hair.html

[30] ZHANG, Hansong, 1998. Effective Occlusion Culling for the Interactive Display of Arbitrary Models. Disertační práce. UNC-Chapel Hill. Department of Computer Science. Dostupné z: http://www.cs.unc.edu/techreports/99-027.pdf Seznam použitých příloh

[p1] OXO, 2017 [online]. Wikipedia. Poslední změna 11. 9. 2017 22:45 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/OXO

[p2] Atari 2600 History, 2017 [online]. AtariAge. [cit. 14. 12. 2017]. Dostupné z: www.atariage.com/2600/

[p3] The MOS 6502 and the Best Layout Guy in the World, 2011 [online]. swtch.com. Poslední změna 3. 1. 2011 [cit. 14. 12. 2017]. Dostupné z: https://research.swtch.com/6502

[p4] Motorola 6800 microprocessor family, 2017 [online]. CPU-World. Poslední změna 22. 10. 2017 [cit. 14. 12. 2017]. Dostupné z: www.cpu-world.com/CPUs/6800/

[p5] Pitfall!, 2017 [online]. AtariAge. [cit. 14. 12. 2017]. Dostupné z: www.atariage.com/software_page.html?SoftwareLabelID=360

[p6] Magnavox Odyssey2 \ Philips Videopac, 2016 [online]. Video Game Console Library. [cit. 14. 12. 2017]. Dostupné z: www.videogameconsolelibrary.com/pg70-odyssey2.htm

[p7] GCE Vectrex, 2016 [online]. Video Game Console Library. [cit. 14. 12. 2017]. Dostupné z: www.videogameconsolelibrary.com/pg80-vectrex.htm

[p8] SG-1000, 2017 [online]. Sega Retro. Poslední změna 20. 10. 2017 13:39 [cit. 14. 12. 2017]. Dostupné z: www.segaretro.org/SG-1000

[p9] Nintendo Entertainment System, 2016 [online]. Giant Bomb. Poslední změna 3. 6. 2016 13:57 [cit. 14. 12. 2017]. Dostupné z: www.giantbomb.com/nintendo-entertainment-system/3045-21/

[p10] Donkey Kong, 2011 [online]. RetroGames.cz. [cit. 14. 12. 2017]. Dostupné z www.retrogames.cz/recenze_001.php

[p11] Super Mario Bros., 2011 [online]. RetroGames.cz. [cit. 14. 12. 2017]. Dostupné z: www.retrogames.cz/recenze_005.php

[p12] TIŠNOVSKÝ, Pavel, 2011. Historie vývoje počítačových her (8.část – nejznámější hry vytvořené pro herní konzoli Atari 2600). In: Root.cz [online]. 29. 12. 2011 [cit. 9. 12. 2017]. Dostupné z: https://www.root.cz/clanky/historie-vyvoje-pocitacovych-her-8-cast- nejznamejsi-hry-vytvorene-pro-herni-konzoli-atari-2600/?ic=serial-box&icc=text-title

[p13] TIŠNOVSKÝ, Pavel, 2012. Historie vývoje počítačových her (24.část – hry pro konzoli NES). In: Root.cz [online]. 26. 4. 2012 [cit. 14. 12. 2017]. Dostupné z: https://www.root.cz/clanky/historie-vyvoje-pocitacovych-her-24-cast-hry-pro- konzoli-nes/?ic=serial-box&icc=text-title

[p14] Sonic the Hedgehog, 2017 [online]. GameSpot. [cit. 14. 12. 2017]. Dostupné z: www.gamerankings.com/genesis/454495-sonic-the-hedgehog/index.html [p15] TIŠNOVSKÝ, Pavel, 2012. Historie vývoje počítačových her (22.část – hry pro konzoli Sega Master System). In: Root.cz [online]. 12. 4. 2012 [cit. 14. 12. 2017]. Dostupné z: https://www.root.cz/clanky/historie-vyvoje-pocitacovych-her-22-cast-hry-pro- konzoli-sega-master-system/?ic=serial-box&icc=text-title

[p16] Recenze hry: The Curse of Monkey Island, 2008 [online]. Game2k. [cit. 14. 12. 2017]. Dostupné z: www.game2k.cz/the-curse-of-monkey-island/recenze-pocitacove-hry.html? id=the_curse_of_monkey_island_pc

[p17] Polda – Oficiální web, 2016 [online]. Zima Software Games Development. [cit. 14. 12. 2017]. Dostupné z: www.polda5.cz

[p18] Horké léto, 2017 [online]. Česká Databáze Her. [cit. 14. 12. 2017]. Dostupné z: www.cdh.cz/pc/Horke-leto-13978/

[p19] SMITH, Graham, 2016. Have You Played... The Curse Of Monkey Island? In: Rock Paper Shotgun [online]. Poslední změna 5. 11. 2016 15:30 [cit. 14. 12. 2017]. Dostupné z: https://www.rockpapershotgun.com/2016/11/05/have-you-played-the-curse-of- monkey-island/

[p20] Duke Nukem 3D, 2017 [online]. 3D Realms. [cit. 14. 12. 2017]. Dostupné z: https://3drealms.com/catalog/duke-nukem-3d_27/

[p21] Salieri Crime Family, 2017 [online]. Mafia Wiki. [cit. 14. 12. 2017]. Dostupné z: http://mafiagame.wikia.com/wiki/Salieri_Crime_Family

[p22] Teodora Contanto, 2017 [online]. Assassin's Creed Wiki. [cit. 14. 12. 2017]. Dostupné z: http://it.assassinscreed.wikia.com/wiki/Teodora_Contanto

[p23] Real-time game characters, 2017 [online]. Pinterest. [cit. 14. 12. 2017]. Dostupné z: https://cz.pinterest.com/anderliza/real-time-game-characters/

[p24] Transparency map, 2015 [online]. Polycount. Poslední změna 10. 4. 2015 8:31 [cit. 14. 12. 2017]. Dostupné z: http://wiki.polycount.com/wiki/Transparency_map

[p25] On vs Off! Nvidia HairWorks The Witcher 3 Wild Hunt Gameplay at Maximum Graphical Settings PC 1080p, 2015 [online]. YouTube. [cit. 14. 12. 2017]. Dostupné z: https://www.youtube.com/watch?v=tB2RcvWRh40&feature=youtu.be

[p26] CROSSLEY, Rob, 2015. DirectX 12 Can Render “up to 12 Times More Polygons“ Than DX11. In: GameSpot [online]. 1. 5. 2015 15:35 [cit. 14. 12. 2017]. Dostupné z: http://www.gamespot.com/articles/directx-12-can-render-up-to-12-times-more- polygons/1100-6427026/

[p27] PAPADOPOULOS, John, 2015. Dawn Engine – First Screenshots Revealed Showcasing AMD's TressFX 3.0. In: Dark Side Of Gaming [online]. 17. 3. 2015 [cit. 14. 12. 2017]. Dostupné z: http://www.dsogaming.com/screenshot-news/dawn-engine-first-screenshots- revealed-showcasing-amds-tressfx-3-0/ [p28] RUSSELL, Eddie, 2015. Elliminate Texture Confusion: Bump, Normal and Displacement Maps. In: Digital-Tutors [online]. [cit. 14. 12. 2017]. Dostupné z: blog.digitaltutors.com/bump-normal-and-displacement-maps/

[p29] MASTERS, Mark, 2014. Understanding Subsurface Scattering – Capturing the Appearance of Translucent Materials. In: Digital-Tutors [online]. [cit. 14. 12. 2017]. Dostupné z: blog.digitaltutors.com/understanding-subsurface-scattering-capturing- appearance-translucent-materials/

[p30] What are normal, tangent and binormal vectors and how are they used?, 2017 [online]. Game Development. [cit. 14. 12. 2017] Dostupné z: http://gamedev.stackexchange.com/questions/51399/what-are-normal-tangent- and-binormal-vectors-and-how-are-they-used

[p31] Unreal Engine, 2017 [online]. Epic Games. [cit. 14. 12. 2017]. Dostupné z: https://www.unrealengine.com/what-is-unreal-engine-4

[p32] Fraps, 2017 [online]. Wikipedia. Poslední změna 23. 8. 2017 7:08 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/Fraps

[p33] Brigade, 2017 [online]. OTOY Inc. [cit. 14. 12. 2017]. Dostupné z: https://home.otoy.com/render/brigade/

[p34] Armory3D, 2017 [online]. Armory3D [cit. 14. 12. 2017]. Dostupné z: http://armory3d.org/

[p35] VELDHUIZEN, Bart, 2016. Blender PBR Viewport v0.4 update. In: BlenderNation [online]. 6. 6. 2016 [cit. 14. 12. 2017]. Dostupné z: https://www.blendernation.com/2016/06/06/blender-pbr-viewport-v0-4-update/

[p36] FELINTO, Dalai, 2017. Eevee Roadmap. In: blender.org [online]. 22. 3. 2017 [cit. 14. 12. 2017]. Dostupné z: https://code.blender.org/2017/03/eevee-roadmap/

[p37] 2.8, 2017 [online]. Blender Foundation [cit. 14. 12. 2017]. Dostupné z: https://www.blender.org/2-8/

[p38] PIRZADA, Usman, 2013. Ryse Polygon Count Comparison with Other AAA Titles – Star Citizen, Crysis 3 and More. In: wccftech [online]. 28. 9. 2013 [cit. 14. 12. 2017]. Dostupné z: http://wccftech.com/ryse-polygon-count-comparision-aaa-titles-crysis-star- citizen/

[p39] Polycounts in next gen games thread!, 2014 [online]. Polycount. [cit. 14. 12. 2017]. Dostupné z: http://polycount.com/discussion/141061/polycounts-in-next-gen-games-thread

[p40] Metal Gear Solid V Graphics Discussion Thread, 2014 [online]. Metal Gear Solid Forums. Poslední změna 22. 11. 2015 18:53 [cit. 14. 12. 2017] Dostupné z: http://mgsforums.com/topic/7695350/60/ [p41] UPDATED: Horizon: Zero Dawn's Thunderjaw Consists Of 550k Polygons & Stands 24x9 Meters Tall, 2015 [online]. wccftech. Poslední změna 25. 9. 2015 [cit. 14. 12. 2017] Dostupné z: https://wccftech.com/horizon-dawns-thunderjaw-consists-550k-polygons- stands-24x9-meters-tall/

[p42] KALIŠ, Karel, 2011. Deus Ex: Human Revolution – nářez jako zastrara (recenze). In: Doupě.cz [online]. 26. 8. 2011 [cit. 14. 12. 2017]. Dostupné z: doupe.zive.cz/clanek/deus-ex-human-revolution--narez-jako-zastara-recenze

[p43] , 2017 [online]. Wikipedia. Poslední změna 12. 12. 2017 22:06 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/Spike_Video_Game_Awards

[p44] British Academy Games Awards, 2016 [online]. Wikipedia. Poslední změna 17. 10. 2017 19:50 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/British_Academy_Games_Awards

[p45] Deus-ex-human-revolution-adam-jensen.jpg, 2016 [online]. Fandom. [cit. 14. 12. 2017]. Dostupné z: http://massfanon.wikia.com/wiki/File:Deus-ex-human-revolution-adam- jensen.jpg

[p46] MALIAROV, Michal, 2013. The Last of Us – když hra potká film (recenze). In: Doupě.cz [online]. 7. 6. 2013 [cit. 14. 12. 2017]. Dostupné z: https://doupe.zive.cz/clanek/the-last-of-us--kdyz-hra-potka-film-recenze

[p47] Kerrang! Awards, 2016 [online]. Wikipedia. Poslední změna 9. 12. 2017 3:45 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/Kerrang!_Awards

[p48] HELGESON, Matt, 2013. The Last of Us. In: Game Informer [online]. 5. 6. 2013 9:00 [cit. 14. 12. 2017]. Dostupné z: www.gameinformer.com/games/the_last_of_us/b/ps3/archive/2013/06/05/the- last-of-us-review-naughty-dogs-grim-masterpiece.aspx

[p49] MORIARTY, Colin, 2013. The Last of Us review. In: IGN [online]. 5. 6. 2013 [cit. 14. 12. 2017]. Dostupné z: www.ign.com/articles/2013/06/05/the-last-of-us-review

[p50] “Yes, but how many polygons?“ An artist blog entry with interesting numbers, 2007 [online]. Beyond3D. Poslední změna 21. 8. 2017 [cit. 14. 12. 2017]. Dostupné z: https://forum.beyond3d.com/threads/yes-but-how-many-polygons-an-artist- blog-entry-with-interesting-numbers.39321/page-84

[p51] MALIAROV, Michal, 2013. Grand Theft Auto V: sandbox šitý na míru (recenze). In: Doupě.cz [online]. 17. 9. 2013 [cit. 14. 12. 2017]. Dostupné z: doupe.zive.cz/clanek/grand-theft-auto-v-sandbox-sity-na-miru-recenze

[p52] “Yes, but how many polygons?“ An artist blog entry with interesting numbers, 2007 [online]. Beyond3D. Poslední změna 21. 8. 2017 [cit. 14. 12. 2017]. Dostupné z: https://forum.beyond3d.com/threads/yes-but-how-many-polygons-an-artist- blog-entry-with-interesting-numbers.39321/page-83 [p53] MALIAROV, Michal, 2013. Akční rubačka Ryse se bude hrát sama, ovladač nepotřebujete. In: Doupě.cz [online]. 14. 6. 2013 [cit. 14. 12. 2017]. Dostupné z: doupe.zive.cz/clanek/akcni-rubacka-ryse-se-bude-hrat-sama-ovladac- nepotrebujete

[p54] FAILES, Ian, 2014. The tech of Crytek's Ryse: Son of Rome. In: fxguide.com [online]. 20. 3. 2014 [cit. 14. 12. 2017]. Dostupné z: https://www.fxguide.com/featured/the-tech-of-cryteks-ryse-son-of-rome/

[p55] IMTIAZ, Khurram, 2013. Ryse downgrade officially confirmed by Crytek CEO. In: GearNuke [online]. 27. 9. 2013 [cit. 14. 12. 2017]. Dostupné z: gearnuke.com/ryse-downgrade-officially-confirmed-crytek-ceo/

[p56] BAUM, Petr, 2013. Metal Gear Rising: Revengeance – poctivá japonská řezničina (recenze). In Doupě.cz [online]. 29. 3. 2013 [cit 14. 12. 2017]. Dostupné z: doupe.zive.cz/clanek/metal-gear-rising-revengeance--poctiva-japonska- reznicina-recenze

[p57] MALIAROV, Michal, 2014. Metal Gear Solid V: Ground Zeroes – demo za všechny prachy (recenze). In: Doupě.cz [online]. 29. 3. 2014 [cit. 14. 12. 2017]. Dostupné z: doupe.zive.cz/clanek/metal-gear-solid-v-ground-zeroes--demo-za-vsechny- prachy-recenze

[p58] negotiated study 1 – beginning the project, 2013 [online]. WordPress.com. Poslední změna 23. 10. 2013 [cit. 14. 12. 2017]. Dostupné z: https://tullimation.wordpress.com/2013/10/23/negotiated-study-1-beginning- the-project/

[p59] BROWN, Peter, 2014. Kept you waiting, huh? In: GameSpot [online]. 18. 3. 2014 [cit. 14. 12. 2017]. Dostupné z: http://www.gamespot.com/reviews/metal-gear-solid-5-ground-zeroes- review/1900-6415701/

[p60] Video post-processing, 2016 [online]. Wikipedia. Poslední změna 4. 10. 2017 19:33 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/Video_post-processing

[p61] MALIAROV, Michal, 2014. Dragon Age: Inquisition – veď je nebo zemři (recenze). In: Doupě.cz [online]. 30. 11. 2014 [cit. 14. 12. 2017]. Dostupné z: https://doupe.zive.cz/clanek/dragon-age-inquisition--ved-je-nebo-zemri-recenze

[p62] , 2016 [online]. Wikipedia. Poslední změna 12. 12. 2017 22:26 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/The_Game_Awards

[p63] GLAAD Media Award, 2017 [online]. Wikipedia. Poslední změna 4. 4. 2017 21:39 [cit. 14. 12. 2017]. Dostupné z: https://en.wikipedia.org/wiki/GLAAD_Media_Award [p64] KULASINGHAM, Gajan, 2014. Dragon Age: Inquisition – Gameplay Feature: Character Creation. In: GameSpot [online]. 30. 9. 2014 [cit. 14. 12. 2017]. Dostupné z: http://www.gamespot.com/videos/dragon-age-inquisition-gameplay-feature- character-/2300-6421589/

[p65] MALIAROV, Michal, 2015. The Order: 1886 – filmový film (recenze). In: Doupě.cz [online]. 19. 2. 2015 [cit. 14. 12. 2017]. Dostupné z: doupe.zive.cz/clanek/the-order-1886--filmovy-film-recenze

[p66] Squadron 42 vs The Order 1886, 2016 [online]. GameSpot. Poslední změna 27. 7. 2016 [cit. 14. 12. 2017]. Dostupné z: http://www.gamespot.com/forums/system-wars-314159282/squadron-42-vs- the-order-1886-33297593/

[p67] BROWN, Peter, 2016. Heavy is the head that wears the crown. In: GameSpot [online]. 28. 11. 2016 [cit. 14. 12. 2017]. Dostupné z: www.gamespot.com/reviews/final-fantasy-15-review/1900-6416579/

[p68] BROWN, Peter, 2015. Final Fantasy 15 Release Date Confirmed for 2016. In: GameSpot [online]. Poslední změna 6. 8. 2015 10:57 [cit. 14. 12. 2017]. Dostupné z: http://www.gamespot.com/articles/final-fantasy-15-release-date-confirmed-for- 2016/1100-6429527/

[p69] Outside Xbox, 2016. Let's Play Final Fantasy 15 – WHAT IS GOING ON (Xbox One Gameplay) [online]. Youtube. [cit. 14. 12. 2017]. Dostupné z: https://www.youtube.com/watch?v=5HB9ZLGsmJY [p70] Star Citizen, 2017 [online]. In: Roberts Space Industries [online]. [cit. 14. 12. 2017]. Dostupné z: https://robertsspaceindustries.com/

[p71] Tactical Advance, 2016. Star Citizen » Character Creation [online]. Youtube. [cit. 14. 12. 2017]. Dostupné z: https://www.youtube.com/watch?v=AYOt2Ps7KMM

[p72] The Only Hair Typing System Article You'll Ever Need, 2011 [online]. Curl Centric. [cit. 14. 12. 2017]. Dostupné z: www.curlcentric.com/hair-typing-system/ Přílohy

Příloha A – seznam elektronických příloh

• MOD_displace.c – původní kód modifikátoru Displace • MOD_subsurf.c – původní kód modifikátoru Subdivision Surface • MOD_curve.c – původní kód modifikátoru Curve • MOD_decimate.c – původní kód modifikátoru Decimate • Upravene_kody.rar – seznam modifikovaných kódů • HairMat.blend – soubor programu Blender obsahující shader vlasů a vousů • HairTex.png – textura sloužící k tvorbě vlasových pramenů • References.zip – archiv vybraných autorských obrázků k náhledu v plné velikosti • Výsledky ankety.ods/.xls – tabulkový záznam ankety z podkapitoly 5.3 • Mereni_FPS.rar – grafické záznamy průběhu měření poklesu FPS z podkapitoly 4.4 Příloha B - grafické výstupy

Obrázek B001: Ukázka výstupů vytvořených pomocí popisované metody. Obrázek B002: Ukázka detailu modelu vlasů po aplikaci vytvořeného shaderu. Obrázek B003: Srovnání pramenů vlasů v závislosti na faktoru funkce Decimate (zleva faktor 0.01, 0.02, 0.03, 0.04, 0.05; subdivize řádu 3).

Obrázek B004: Srovnání pramenů vlasů v závislosti na řádu funkce Subdivision Surface (zleva subdivize řádu 2, 3, 4, 5, 6; všechny prameny stejné polygonové náročnosti). Obrázek B005: Srovnání pramenů vlasů v závislosti na rozdílných průměrech jednotlivých segmentů řídící křivky.

Obrázek B006: Srovnání jednotlivých pramenů v závislosti na řezech provedených na planárním objektu (všechny prameny mají stejnou polygonovou náročnost). Příloha C - manuál

Následující manuál je sepsán tak, aby reflektoval pracovní postup tvorby vlasového pramene od vytvoření nového planárního objektu po úspěšné zavedení do Unreal Engine 4. Užity byly verze Blender 2.79 a Unreal Engine 4.15, rozvržení editorů či postup se v jiných verzích mohou lišit.

Spusťte program Blender, který automaticky načte přednastavenou scénu (C001). Stiskem klávesy X a následným zakliknutím položky Delete vymažte původní soubor, kombinací kláves SHIFT+A otevřete kontextové menu pro vkládání objektů a navigací do Mesh → Plane vložte do scény čtverec. Klávesou 3 na numerické klávesnici otočte scénu a klávesou 5 přepněte perspektivu tak, abyste byli v pohledu Right Ortho. Stiskem TAB se přepněte do Edit módu pro transformaci bodů, hran a ploch, stiskem R a udáním parametru 90 orotujte celý objekt o 90 stupňů po směru hodinových ručiček (C002).

C001

C002 Klávesou U vyvolejte kontextové menu pro vytváření UV mapování a vyberte možnost Unwrap. Stiskem W a výběrem možnosti Subdivide s nastavením 18 řezů rozčleňte objekt na 400 bodů (C003). Lze přidat více řezů – čím členitější nemodifikovaný objekt, tím více pramenů bude následně vygenerováno. Pro záruku dobrého výsledku celý krok zopakujte a mezi polygony vložte další 2 řezy. Klávesou TAB se přepněte zpět do objektového módu a vyberte záložku Modifiers (C004, červeně). Skrze výběr Add Modifier vložte modifikátor Displace, nastavte Midlevel na hodnotu 0.000, Direction na Y, stiskem New vytvořte nový odkaz na texturu, Texture coordinates nastavte na možnost UV a přejděte do záložky Texture (C004, modře). V podsložce Image vyberte možnost Open a načtěte přiloženou texturu HairTex. V podsložce Colors nastavte Brightness na 0.600 a Contrast na 0.700. Vraťte se do záložky modifiers a nastavte Strength na 30. Po provedení všech zmíněných kroků byste měli dosáhnout výsledku podobného pomocnému obrázku C005.

C003

C004 C005

Z výběru Add Modifier přidejte modifikátor Subdivision Surface. Ve výběru Subdivisions nastavte úroveň View a Render na hodnotu 3. Čím vyšší hodnota je nastavena, tím lépe daný objekt kopíruje křivku, která bude určovat směr růstu, zároveň však dochází k náročnějším výpočtům. Proto při experimentování s úrovní detailu postupujte obezřetně. Kombinací kláves SHIFT+A a výběrem Curve → Bezier vložte do scény křivku, která bude určovat směr růstu. Je důležité, aby pivoty obou objektů sdílely stejné souřadnice, proto je pro jistotu zkontrolujte a v případě potřeby upravte v záložce Object (C005, červeně). Klávesou TAB vstupte do Edit módu, kolečkem myši ovládejte scénu, pravým tlačítkem vybírejte řídící body, následně šipkami ve scéně či klávesou G nastavte tvar křivky dle uvážení. Chcete-li zvýšit členitost křivky, opětovným stiskem A vyberte všechny body, klávesou W a možností Subdivide přidejte další řídící body. Při tvarování křivky je vhodné vložit řídící bod reprezentující kořen na pozici pivotu a sledovat směr šipek zobrazených na křivce. Vedou-li směrem od kořenového bodu, je vše nastaveno správně, v opačném případě vyberte všechny body a v menu Curve → Segments zvolte možnost Switch Direction (C006).

C006 Skrze Add Modifier vložte modifikátor Curve. Deformation Axis nastavte na Y a do pole Object vyberte do scény vloženou křivku. Po zaplnění pole Object se model začne deformovat ve směru křivky. V případě, že by se deformoval směrem od křivky, lze tento problém vyřešit dvěma způsoby – buď přenastavte Deformation Axis na -Y, nebo po stisku 3 (Right Ortho) nebo 7 (Top Ortho) orotujte objekt klávesou R a nastavením parametru 180 objekt o 180 stupňů. Po provedení operací by interakce objektu a křivky měla vypadat obdobně jako na obrázku C007.

C007

Naposledy navštivte menu Add Modifier a přidejte modifikátor Decimate. Položka Faces zobrazuje aktuální počet polygonů objektu, přičemž počet trojúhelníků je dvojnásobný. Při aplikaci decimátoru ovšem dochází k triangulaci, takže chcete-li nastavit konečný počet na desetinu, je třeba Ratio nastavit na 0.05. Nastavte Ratio na 0.0125.

Nyní je vše nastaveno na práci s vlasovým pramenem. Parametrem Strength v modifikátoru Displace lze nastavit délku, modifikátorem Subdivison Surface úroveň detailu a řídícími body křivky směr růstu vlasů. Pokud je plocha příliš velká, stiskem S lze nastavit velikost. Pokud by odezva byla příliš pomalá, vypněte na chvíli modifikátor Decimate skrze ikonu oka (C007, červeně), po aplikaci velikosti jej opět zapněte. Pro redukci dlouhých chlupů vstupte do Edit módu, klávesou C a držením lévého tlačítka myši vyberte body, pravým tlačítkem výběr ukončete, stiskem klávesy P a výběrem možnosti Selection vytvořte nový objekt odebráním ze starého a úpravou hodnoty Strength přenastavte délku. Pro manipulaci s vlasovým pramenem vyberte pravým tlačítkem nejprve křivku a následně objekt, stiskněte CTRL+P a vyberte možnost Object. Následně vyberte pramen a upravte jej klávesami G, R a S. Je důležité operovat s pramenem a nikoli se křivkou, abyste zachovali stejné informace pro oba pivoty a tím i tvar objektu v závislosti na křivce.

Přidejte objektu materiál. Stiskem SHIFT+F1 vyvolejte okno přiřazení, najděte soubor HairMat.blend, otevřete jej a ve složce Material vyberte položku HairMat. Otevřete seznam existujících materiálů (C008, červeně) a vyberte HairMat. K úpravě barvy vlasů otevřete nastavení editoru (C008, modře), vyberte Node editor a změňte vstupní parametry/barvy materiálu. Výsledný materiál můžete kontrolovat v náhledu (C008, zeleně). Až budete s materiálem spokojeni, přepněte se prostřednictvím nastavení editoru zpět do 3D View a ke kontrole výstupu v Blenderu stiskněte kombinaci SHIFT+Z. Výstup by měl korespondovat s obrázkem C008. V menu File → Export vyberte formát FBX a zkontrolujte, že je zaškrtnuta možnost Apply Modifiers (C009, červeně). Nyní můžete soubor exportovat. C008

C009

Spusťte editor programu Unreal Engine 4 a načtěte scénu, do které chcete objekt vložit. Stiskněte v Content Browseru tlačítko Import (C010, červeně) a nalezněte cestu k vyexportovanému souboru. Zkontrolujte, že je zaškrtnuta možnost Import Materials (C010, modře), a stiskněte tlačítko Import All. Vyberte v Content Browseru požadovaný objekt a přetáhněte jej do scény. Dvojklikem otevřete materiál HairMat a ručně jej nastavte dle schématu na obrázku C011. Po provedení změn klikněte na ikonu Apply (C011, červeně) a okno s materiálem zavřete. Pod šipkou u ikony Build (C012, červeně) nastavte v Lighting Quality úroveň osvětlení na Production a vyberte možnost Build Lighting Only. Po kompilaci světel v závislosti na nově vložených informacích je základní proces převodu do Unreal Engine 4 hotový a výsledek by měl odpovídat obrázku C012. C010

C011

C012 Příloha D – dokumentace modifikovaných kódů

Displace:

/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. * * Contributor(s): Daniel Dunbar * Ton Roosendaal, * Ben Batt, * Brecht Van Lommel, * Campbell Barton * * ***** END GPL LICENSE BLOCK ***** * */

/** \file blender/modifiers/intern/MOD_displace.c * \ingroup modifiers */

#include "DNA_meshdata_types.h" #include "DNA_object_types.h"

#include "BLI_utildefines.h" #include "BLI_math.h" #include "BLI_task.h"

#include "BKE_cdderivedmesh.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_image.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_texture.h" #include "BKE_deform.h" #include "BKE_object.h"

#include "depsgraph_private.h" #include "MEM_guardedalloc.h"

#include "MOD_util.h"

#include "RE_shader_ext.h" /* Displace */ // inicializace vstupniho objektu // static void initData(ModifierData *mddi) { DisplaceModifierData *dimd = (DisplaceModifierData *) mddi;

// zmena vstupu strength, direction a midlevel //

dimd->texture = NULL; dimd->strength = 10; dimd->direction = MOD_DISP_DIR_Y; dimd->midlevel = 0.0; dimd->space = MOD_DISP_SPACE_LOCAL; } static void copyData(ModifierData *mddi, ModifierData *target) { #if 0 DisplaceModifierData *dimd = (DisplaceModifierData *) mddi; DisplaceModifierData *tdimd = (DisplaceModifierData *) target; #endif

modifier_copyData_generic(mddi, target); } static void freeData(ModifierData *mddi) { DisplaceModifierData *dimd = (DisplaceModifierData *) mddi; if (dimd->texture) { id_us_min(&dimd->texture->id); } } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *mddi) { DisplaceModifierData *dimd = (DisplaceModifierData *)mddi; CustomDataMask dataMask = 0;

/* ask for vertexgroups if we need them */ if (dimd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;

/* ask for UV coordinates if we need them */ if (dimd->texmapping == MOD_DISP_MAP_UV) dataMask |= CD_MASK_MTFACE;

if (dimd->direction == MOD_DISP_DIR_CLNOR) { dataMask |= CD_MASK_CUSTOMLOOPNORMAL; }

return dataMask; } static bool dependsOnTime(ModifierData *mddi) { DisplaceModifierData *dimd = (DisplaceModifierData *)mddi;

if (dimd->texture) { return BKE_texture_dependsOnTime(dimd->texture); } else { return false; } } static bool dependsOnNormals(ModifierData *mddi) { DisplaceModifierData *dimd = (DisplaceModifierData *)mddi; return ELEM(dimd->direction, MOD_DISP_DIR_NOR, MOD_DISP_DIR_CLNOR); } static void foreachObjectLink(ModifierData *mddi, Object *ob, ObjectWalkFunc walk, void *userData) { DisplaceModifierData *dimd = (DisplaceModifierData *) mddi;

walk(userData, ob, &dimd->map_object, IDWALK_CB_NOP); } static void foreachIDLink(ModifierData *mddi, Object *ob, IDWalkFunc walk, void *userData) { DisplaceModifierData *dimd = (DisplaceModifierData *) mddi;

walk(userData, ob, (ID **)&dimd->texture, IDWALK_CB_USER);

foreachObjectLink(mddi, ob, (ObjectWalkFunc)walk, userData); } static void foreachTexLink(ModifierData *mddi, Object *ob, TexWalkFunc walk, void *userData) { walk(userData, ob, mddi, "texture"); } static bool isDisabled(ModifierData *mddi, int UNUSED(useRenderParams)) { DisplaceModifierData *dimd = (DisplaceModifierData *) mddi; return ((!dimd->texture && dimd->direction == MOD_DISP_DIR_RGB_XYZ) || dimd->strength == 0.0f); } static void updateDepgraph(ModifierData *mddi, DagForest *forest, struct Main *UNUSED(bmain), struct Scene *UNUSED(scene), Object *UNUSED(ob), DagNode *obNode) { DisplaceModifierData *dimd = (DisplaceModifierData *) mddi;

if (dimd->map_object && dimd->texmapping == MOD_DISP_MAP_OBJECT) { DagNode *curNode = dag_get_node(forest, dimd->map_object);

dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier"); }

if (dimd->texmapping == MOD_DISP_MAP_GLOBAL || (ELEM(dimd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) && dimd->space == MOD_DISP_SPACE_GLOBAL)) { dag_add_relation(forest, obNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Displace Modifier"); } } static void updateDepsgraph(ModifierData *mddi, struct Main *UNUSED(bmain), struct Scene *UNUSED(scene), Object *ob, struct DepsNodeHandle *node) { DisplaceModifierData *dimd = (DisplaceModifierData *)mddi; if (dimd->map_object != NULL && dimd->texmapping == MOD_DISP_MAP_OBJECT) { DEG_add_object_relation(node, dimd->map_object, DEG_OB_COMP_TRANSFORM, "Displace Modifier"); } if (dimd->texmapping == MOD_DISP_MAP_GLOBAL || (ELEM(dimd->direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ) && dimd->space == MOD_DISP_SPACE_GLOBAL)) { DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Displace Modifier"); } } typedef struct DisplaceUserdata { /*const*/ DisplaceModifierData *dimd; struct ImagePool *pool; MDeformVert *dvert; float weight; int defgrp_index; int direction; bool use_global_direction; float (*tex_co)[3]; float (*vertexCos)[3]; float local_mat[4][4]; MVert *mvert; float (*vert_clnors)[3]; } DisplaceUserdata;

// hlavni funkce kodu provadejici operace na objektu // static void displaceModifier_do_task(void *userdata, const int iter) { DisplaceUserdata *data = (DisplaceUserdata *)userdata; DisplaceModifierData *dimd = data->dimd; MDeformVert *dvert = data->dvert; float weight = data->weight; int defgrp_index = data->defgrp_index; int direction = data->direction; bool use_global_direction = data->use_global_direction; float (*tex_co)[3] = data->tex_co; float (*vertexCos)[3] = data->vertexCos; MVert *mvert = data->mvert; float (*vert_clnors)[3] = data->vert_clnors;

const float delta_fixed = 1.0f - dimd->midlevel; /* when no texture is used, we fallback to white */

TexResult texres; float strength = dimd->strength; float delta; float local_vec[3]; if (dvert) { weight = defvert_find_weight(dvert + iter, defgrp_index); if (weight == 0.0f) { return; } } if (dimd->texture) { texres.nor = NULL; BKE_texture_get_value_ex(dimd->modifier.scene, dimd->texture, tex_co[iter], &texres, data->pool, false); delta = texres.tin - dimd->midlevel; } else { delta = delta_fixed; /* (1.0f - dimd->midlevel) */ /* never changes */ }

if (dvert) { strength *= weight; }

// omezeni vstupu ovlivnujiciho silu aplikovaneho modifikatoru (chceme zamezit negativnim hodnotam a rustu dovnitr objektu, zaroven shora omezujeme k urceni maximalni delky) //

delta *= strength; CLAMP(delta, 0, 200);

// k zaruceni spravne funkce i po zmene puvodniho smeru je kod modifikovan tak, aby pracoval vzdy stejne //

switch (direction) { case MOD_DISP_DIR_X: if (use_global_direction) { vertexCos[iter][0] += delta * data->local_mat[0][1]; vertexCos[iter][1] += delta * data->local_mat[1][1]; vertexCos[iter][2] += delta * data->local_mat[2][1]; } else { vertexCos[iter][1] += delta; } break; case MOD_DISP_DIR_Y: if (use_global_direction) { vertexCos[iter][0] += delta * data->local_mat[0][1]; vertexCos[iter][1] += delta * data->local_mat[1][1]; vertexCos[iter][2] += delta * data->local_mat[2][1]; } else { vertexCos[iter][1] += delta; } break; case MOD_DISP_DIR_Z: if (use_global_direction) { vertexCos[iter][0] += delta * data->local_mat[0][1]; vertexCos[iter][1] += delta * data->local_mat[1][1]; vertexCos[iter][2] += delta * data->local_mat[2][1]; } else { vertexCos[iter][1] += delta; } break; case MOD_DISP_DIR_RGB_XYZ: if (use_global_direction) { vertexCos[iter][0] += delta * data->local_mat[0][1]; vertexCos[iter][1] += delta * data->local_mat[1][1]; vertexCos[iter][2] += delta * data->local_mat[2][1]; } else { vertexCos[iter][1] += delta; } break; case MOD_DISP_DIR_NOR: if (use_global_direction) { vertexCos[iter][0] += delta * data->local_mat[0][1]; vertexCos[iter][1] += delta * data->local_mat[1][1]; vertexCos[iter][2] += delta * data->local_mat[2][1]; } else { vertexCos[iter][1] += delta; } break; case MOD_DISP_DIR_CLNOR: if (use_global_direction) { vertexCos[iter][0] += delta * data->local_mat[0][1]; vertexCos[iter][1] += delta * data->local_mat[1][1]; vertexCos[iter][2] += delta * data->local_mat[2][1]; } else { vertexCos[iter][1] += delta; } break; } }

/* dm must be a CDDerivedMesh */ static void displaceModifier_do( DisplaceModifierData *dimd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { MVert *mvert; MDeformVert *dvert; int direction = dimd->direction; int defgrp_index; float (*tex_co)[3]; float weight = 1.0f; /* init value unused but some compilers may complain */ float (*vert_clnors)[3] = NULL; float local_mat[4][4] = {{0}}; const bool use_global_direction = dimd->space == MOD_DISP_SPACE_GLOBAL;

if (!dimd->texture && dimd->direction == MOD_DISP_DIR_RGB_XYZ) return; if (dimd->strength == 0.0f) return;

mvert = CDDM_get_verts(dm); modifier_get_vgroup(ob, dm, dimd->defgrp_name, &dvert, &defgrp_index);

if (dimd->texture) { tex_co = MEM_callocN(sizeof(*tex_co) * numVerts, "displaceModifier_do tex_co"); get_texture_coords((MappingInfoModifierData *)dimd, ob, dm, vertexCos, tex_co, numVerts);

modifier_init_texture(dimd->modifier.scene, dimd->texture); } else { tex_co = NULL; } // nasledujici operand if byl zredukovan, aby se zamezilo nechtenym odlisnym vysledkum zpusobenym vyberem smeru Normal a Custom Normal //

if (ELEM(direction, MOD_DISP_DIR_X, MOD_DISP_DIR_Y, MOD_DISP_DIR_Z, MOD_DISP_DIR_RGB_XYZ, MOD_DISP_DIR_CLNOR, MOD_DISP_DIR_NOR) && use_global_direction) { copy_m4_m4(local_mat, ob->obmat); } DisplaceUserdata data = {NULL}; data.dimd = dimd; data.dvert = dvert; data.weight = weight; data.defgrp_index = defgrp_index; data.direction = direction; data.use_global_direction = use_global_direction; data.tex_co = tex_co; data.vertexCos = vertexCos; copy_m4_m4(data.local_mat, local_mat); data.mvert = mvert; data.vert_clnors = vert_clnors; if (dimd->texture != NULL) { data.pool = BKE_image_pool_new(); BKE_texture_fetch_images_for_pool(dimd->texture, data.pool); } BLI_task_parallel_range(0, numVerts, &data, displaceModifier_do_task, numVerts > 512);

if (data.pool != NULL) { BKE_image_pool_free(data.pool); }

if (tex_co) { MEM_freeN(tex_co); }

if (vert_clnors) { MEM_freeN(vert_clnors); } } static void deformVerts(ModifierData *mddi, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag)) { DerivedMesh *dm = get_cddm(ob, NULL, derivedData, vertexCos, dependsOnNormals(mddi));

displaceModifier_do((DisplaceModifierData *)mddi, ob, dm, vertexCos, numVerts);

if (dm != derivedData) dm->release(dm); } static void deformVertsEM( ModifierData *mddi, Object *ob, struct BMEditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = get_cddm(ob, editData, derivedData, vertexCos, dependsOnNormals(mddi));

displaceModifier_do((DisplaceModifierData *)mddi, ob, dm, vertexCos, numVerts);

if (dm != derivedData) dm->release(dm); } ModifierTypeInfo modifierType_Displace = { /* name */ "Displace", /* structName */ "DisplaceModifierData", /* structSize */ sizeof(DisplaceModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* applyModifier */ NULL, /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ foreachTexLink, };

Subdivision Surface:

/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. * * Contributor(s): Daniel Dunbar * Ton Roosendaal, * Ben Batt, * Brecht Van Lommel, * Campbell Barton * * ***** END GPL LICENSE BLOCK ***** * */

/** \file blender/modifiers/intern/MOD_subsurf.c * \ingroup modifiers */

#include

#include "DNA_scene_types.h" #include "DNA_object_types.h" #ifdef WITH_OPENSUBDIV # include "DNA_userdef_types.h" #endif

#include "BLI_utildefines.h"

#include "BKE_cdderivedmesh.h" #include "BKE_depsgraph.h" #include "BKE_scene.h" #include "BKE_subsurf.h"

#include "MOD_modifiertypes.h"

#include "intern/CCGSubSurf.h"

// inicializace konstant // static const int view = 3; static const int render = 3;

// inicializace vstupniho objektu // static void initData(ModifierData *mdss) { SubsurfModifierData *smd = (SubsurfModifierData *) mdss;

// zmena vstupu levels a renderLevels k nastaveni vhodne urovne detailu //

smd->levels = view; smd->renderLevels = render; smd->flags |= eSubsurfModifierFlag_SubsurfUv; } static void copyData(ModifierData *mdss, ModifierData *target) { #if 0 SubsurfModifierData *smd = (SubsurfModifierData *) mdss; #endif SubsurfModifierData *tsmd = (SubsurfModifierData *) target;

modifier_copyData_generic(mdss, target);

tsmd->emCache = tsmd->mCache = NULL; } static void freeData(ModifierData *mdss) { SubsurfModifierData *smd = (SubsurfModifierData *) mdss;

if (smd->mCache) { ccgSubSurf_free(smd->mCache); } if (smd->emCache) { ccgSubSurf_free(smd->emCache); } } static bool isDisabled(ModifierData *mdss, int useRenderParams) { SubsurfModifierData *smd = (SubsurfModifierData *) mdss; int levels = (useRenderParams) ? smd->renderLevels : smd->levels;

return get_render_subsurf_level(&mdss->scene->r, levels, useRenderParams != 0) == 0; } static DerivedMesh *applyModifier(ModifierData *mdss, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag flag) { SubsurfModifierData *smd = (SubsurfModifierData *) mdss; SubsurfFlags subsurf_flags = 0; DerivedMesh *result; const bool useRenderParams = (flag & MOD_APPLY_RENDER) != 0; const bool isFinalCalc = (flag & MOD_APPLY_USECACHE) != 0;

#ifdef WITH_OPENSUBDIV const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0; #endif bool do_cddm_convert = useRenderParams || !isFinalCalc;

if (useRenderParams) subsurf_flags |= SUBSURF_USE_RENDER_PARAMS; if (isFinalCalc) subsurf_flags |= SUBSURF_IS_FINAL_CALC; if (ob->mode & OB_MODE_EDIT) subsurf_flags |= SUBSURF_IN_EDIT_MODE;

#ifdef WITH_OPENSUBDIV /* TODO(sergey): Not entirely correct, modifiers on top of subsurf * could be disabled. */ if (mdss->next == NULL && allow_gpu && do_cddm_convert == false && smd->use_opensubdiv) { if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) { modifier_setError(mdss, "OpenSubdiv is disabled in User Preferences"); } else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) { modifier_setError(mdss, "OpenSubdiv is not supported in paint modes"); } else if ((DAG_get_eval_flags_for_object(mdss->scene, ob) & DAG_EVAL_NEED_CPU) == 0) { subsurf_flags |= SUBSURF_USE_GPU_BACKEND; do_cddm_convert = false; } else { modifier_setError(mdss, "OpenSubdiv is disabled due to dependencies"); } } #endif

result = subsurf_make_derived_from_derived(derivedData, smd, NULL, subsurf_flags); result->cd_flag = derivedData->cd_flag;

if (do_cddm_convert) { DerivedMesh *cddm = CDDM_copy(result); result->release(result); result = cddm; }

return result; } static DerivedMesh *applyModifierEM(ModifierData *mdss, Object *UNUSED(ob), struct BMEditMesh *UNUSED(editData), DerivedMesh *derivedData, ModifierApplyFlag flag) { SubsurfModifierData *smd = (SubsurfModifierData *) mdss; DerivedMesh *result; /* 'orco' using editmode flags would cause cache to be used twice in editbmesh_calc_modifiers */ SubsurfFlags ss_flags = (flag & MOD_APPLY_ORCO) ? 0 : (SUBSURF_FOR_EDIT_MODE | SUBSURF_IN_EDIT_MODE); #ifdef WITH_OPENSUBDIV const bool allow_gpu = (flag & MOD_APPLY_ALLOW_GPU) != 0; if (mdss->next == NULL && allow_gpu && smd->use_opensubdiv) { modifier_setError(mdss, "OpenSubdiv is not supported in edit mode"); } #endif

result = subsurf_make_derived_from_derived(derivedData, smd, NULL, ss_flags);

return result; } static bool dependsOnNormals(ModifierData *mdss) { #ifdef WITH_OPENSUBDIV SubsurfModifierData *smd = (SubsurfModifierData *) mdss; if (smd->use_opensubdiv && mdss->next == NULL) { return true; } #else UNUSED_VARS(mdss); #endif return false; } ModifierTypeInfo modifierType_Subsurf = { /* name */ "Subsurf", /* structName */ "SubsurfModifierData", /* structSize */ sizeof(SubsurfModifierData), /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs,

/* copyData */ copyData, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* applyModifier */ applyModifier, /* applyModifierEM */ applyModifierEM, /* initData */ initData, /* requiredDataMask */ NULL, /* freeData */ freeData, /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, }; Curve:

/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. * * Contributor(s): Daniel Dunbar * Ton Roosendaal, * Ben Batt, * Brecht Van Lommel, * Campbell Barton * * ***** END GPL LICENSE BLOCK ***** * */

/** \file blender/modifiers/intern/MOD_curve.c * \ingroup modifiers */

#include

#include "DNA_scene_types.h" #include "DNA_object_types.h"

#include "BLI_utildefines.h"

#include "BKE_cdderivedmesh.h" #include "BKE_lattice.h" #include "BKE_library_query.h" #include "BKE_modifier.h"

#include "depsgraph_private.h" #include "DEG_depsgraph_build.h" #include "MOD_modifiertypes.h"

// inicializace vstupniho objektu // static void initData(ModifierData *mdcu) { CurveModifierData *cmd = (CurveModifierData *) mdcu;

// zmena vstupu defaxis //

cmd->defaxis = MOD_CURVE_POSY; } static void copyData(ModifierData *mdcu, ModifierData *target) { #if 0 CurveModifierData *cmd = (CurveModifierData *) mdcu; CurveModifierData *tcmd = (CurveModifierData *) target; #endif modifier_copyData_generic(mdcu, target); } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *mdcu) { CurveModifierData *cmd = (CurveModifierData *)mdcu; CustomDataMask dataMask = 0;

/* ask for vertexgroups if we need them */ if (cmd->name[0]) dataMask |= CD_MASK_MDEFORMVERT;

return dataMask; } static bool isDisabled(ModifierData *mdcu, int UNUSED(userRenderParams)) { CurveModifierData *cmd = (CurveModifierData *) mdcu;

return !cmd->object; } static void foreachObjectLink( ModifierData *mdcu, Object *ob, ObjectWalkFunc walk, void *userData) { CurveModifierData *cmd = (CurveModifierData *) mdcu;

walk(userData, ob, &cmd->object, IDWALK_CB_NOP); } static void updateDepgraph(ModifierData *mdcu, DagForest *forest, struct Main *UNUSED(bmain), Scene *UNUSED(scene), Object *UNUSED(ob), DagNode *obNode) { CurveModifierData *cmd = (CurveModifierData *) mdcu;

if (cmd->object) { DagNode *curNode = dag_get_node(forest, cmd->object); curNode->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;

dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Modifier"); } } static void updateDepsgraph(ModifierData *mdcu, struct Main *UNUSED(bmain), struct Scene *UNUSED(scene), Object *object, struct DepsNodeHandle *node) { CurveModifierData *cmd = (CurveModifierData *)mdcu; if (cmd->object != NULL) { /* TODO(sergey): Need to do the same eval_flags trick for path * as happening in legacy depsgraph callback. */ /* TODO(sergey): Currently path is evaluated as a part of modifier stack, * might be changed in the future. */ struct Depsgraph *depsgraph = DEG_get_graph_from_handle(node); DEG_add_object_relation(node, cmd->object, DEG_OB_COMP_GEOMETRY, "Curve Modifier"); DEG_add_special_eval_flag(depsgraph, &cmd->object->id, DAG_EVAL_NEED_CURVE_PATH); }

DEG_add_object_relation(node, object, DEG_OB_COMP_TRANSFORM, "Curve Modifier"); } static void deformVerts(ModifierData *mdcu, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, ModifierApplyFlag UNUSED(flag)) { CurveModifierData *cmd = (CurveModifierData *) mdcu;

/* silly that defaxis and curve_deform_verts are off by 1 * but leave for now to save having to call do_versions */ curve_deform_verts(mdcu->scene, cmd->object, ob, derivedData, vertexCos, numVerts, cmd->name, cmd->defaxis - 1); } static void deformVertsEM( ModifierData *mdcu, Object *ob, struct BMEditMesh *em, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) { DerivedMesh *dm = derivedData;

if (!derivedData) dm = CDDM_from_editbmesh(em, false, false);

deformVerts(mdcu, ob, dm, vertexCos, numVerts, 0);

if (!derivedData) dm->release(dm); } ModifierTypeInfo modifierType_Curve = { /* name */ "Curve", /* structName */ "CurveModifierData", /* structSize */ sizeof(CurveModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode,

/* copyData */ copyData, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, /* applyModifier */ NULL, /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ isDisabled, /* updateDepgraph */ updateDepgraph, /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ foreachObjectLink, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, }; Decimate:

/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. * All rights reserved. * * Contributor(s): Daniel Dunbar * Ton Roosendaal, * Ben Batt, * Brecht Van Lommel, * Campbell Barton * * ***** END GPL LICENSE BLOCK ***** * */

/** \file blender/modifiers/intern/MOD_decimate.c * \ingroup modifiers */

#include "DNA_object_types.h"

#include "BLI_math.h" #include "BLI_utildefines.h"

#include "MEM_guardedalloc.h"

#include "BKE_modifier.h" #include "BKE_deform.h" #include "BKE_cdderivedmesh.h"

#include "bmesh.h" #include "bmesh_tools.h"

// #define USE_TIMEIT

#ifdef USE_TIMEIT # include "PIL_time.h" # include "PIL_time_utildefines.h" #endif #include "MOD_util.h"

// inicializace konstant // static const float percent = 0.0125; static const float factor = 1.0; // inicializace vstupniho objektu // static void initData(ModifierData *mdde) { DecimateModifierData *demd = (DecimateModifierData *) mdde;

// zmena vstupu percent a defgrp_factor k nastaveni vhodne urovne decimace //

demd->percent = percent; demd->angle = DEG2RADF(5.0f); demd->defgrp_factor = factor; } static void copyData(ModifierData *mdde, ModifierData *target) { #if 0 DecimateModifierData *demd = (DecimateModifierData *) mdde; DecimateModifierData *tdemd = (DecimateModifierData *) target; #endif modifier_copyData_generic(mdde, target); } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *mdde) { DecimateModifierData *demd = (DecimateModifierData *) mdde; CustomDataMask dataMask = 0;

/* ask for vertexgroups if we need them */ if (demd->defgrp_name[0] && (demd->defgrp_factor > 0.0f)) { dataMask |= CD_MASK_MDEFORMVERT; }

return dataMask; } static DerivedMesh *applyModifier(ModifierData *mdde, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { DecimateModifierData *demd = (DecimateModifierData *) mdde; DerivedMesh *dm = derivedData, *result = NULL; BMesh *bm; bool calc_face_normal; float *vweights = NULL;

#ifdef USE_TIMEIT TIMEIT_START(decim); #endif

/* set up front so we dont show invalid info in the UI */ demd->face_count = dm->getNumPolys(dm);

switch (demd->mode) { case MOD_DECIM_MODE_COLLAPSE: if (demd->percent == 1.0f) { return dm; } calc_face_normal = true; break; case MOD_DECIM_MODE_UNSUBDIV: if (demd->iter == 0) { return dm; } calc_face_normal = false; break; case MOD_DECIM_MODE_DISSOLVE: if (demd->angle == 0.0f) { return dm; } calc_face_normal = true; break; default: return dm; } if (demd->face_count <= 3) { modifier_setError(mdde, "Modifier requires more than 3 input faces"); return dm; } if (demd->mode == MOD_DECIM_MODE_COLLAPSE) { if (demd->defgrp_name[0] && (demd->defgrp_factor > 0.0f)) { MDeformVert *dvert; int defgrp_index;

modifier_get_vgroup(ob, dm, demd->defgrp_name, &dvert, &defgrp_index);

if (dvert) { const unsigned int vert_tot = dm->getNumVerts(dm); unsigned int i;

vweights = MEM_mallocN(vert_tot * sizeof(float), __func__);

if (demd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) { for (i = 0; i < vert_tot; i++) { vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index); } } else { for (i = 0; i < vert_tot; i++) { vweights[i] = defvert_find_weight(&dvert[i], defgrp_index); } } } } } bm = DM_to_bmesh(dm, calc_face_normal); switch (demd->mode) { case MOD_DECIM_MODE_COLLAPSE: { const bool do_triangulate = (demd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0; const int symmetry_axis = (demd->flag & MOD_DECIM_FLAG_SYMMETRY) ? Demd- >symmetry_axis : -1; const float symmetry_eps = 0.00002f; BM_mesh_decimate_collapse( bm, demd->percent, vweights, demd->defgrp_factor, do_triangulate, symmetry_axis, symmetry_eps); break; } case MOD_DECIM_MODE_UNSUBDIV: { BM_mesh_decimate_unsubdivide(bm, demd->iter); break; } case MOD_DECIM_MODE_DISSOLVE: { const bool do_dissolve_boundaries = (demd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0; BM_mesh_decimate_dissolve(bm, demd->angle, do_dissolve_boundaries, (BMO_Delimit)demd->delimit); break; } }

if (vweights) { MEM_freeN(vweights); }

/* update for display only */ demd->face_count = bm->totface; result = CDDM_from_bmesh(bm, false); BLI_assert(bm->vtoolflagpool == NULL && bm->etoolflagpool == NULL && bm->ftoolflagpool == NULL); /* make sure we never alloc'd these */ BLI_assert(bm->vtable == NULL && bm->etable == NULL && bm->ftable == NULL);

BM_mesh_free(bm);

#ifdef USE_TIMEIT TIMEIT_END(decim); #endif

result->dirty = DM_DIRTY_NORMALS;

return result; } ModifierTypeInfo modifierType_Decimate = { /* name */ "Decimate", /* structName */ "DecimateModifierData", /* structSize */ sizeof(DecimateModifierData), /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, /* copyData */ copyData, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ NULL, /* updateDepgraph */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, };