\chapter{Vývoj hry}
\label{chap:main}

Přenos starého projektu na~další major verzi~UE nebyl nijak problematický, dokonce v~editoru je~možnost rychlého exportu assetů do~jiného projektu. Rozhodně tomu pomohlo, že~se~C++~kód nepřenášel, ale~byl napsán znovu. UE~citelně rozšířil seznam dostupných tříd, přitom~některé jsou~již deprecated nebo~odstráněny úplně. Tak~mimo~jiné byly~odstraněny třídy Matinee (bývalý formát a editor animací objektů) pro~podporu novejší třídy Sequencer nebo~starý PhysX\footnote{PhysX je open-source fyzický engine s hardwarovou akcelerací pro grafiky s CUDA architekturou (GPU společnosti NVIDIA).} rozhraní, které~je nahrazeno systémem Chaos. Přesto se~něco pokazilo při~exportu objektů s~dynamickou fyzikou (závěsy, které~reagují na~simulaci větru, se~musely předělat).

Přenos byl~odůvodněn převážně malou velikostí starého projektu a~taky lákavou nabídkou nových technologií, zejména Nanite a~Lumen. Navíc pátá verze Unrealu -- přesněji verze~5.5 -- přinesla značná vylepšení jako:
\begin{itemize}
\item Nový systém zpracování vstupu Enhanced Input\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/enhanced-input-in-unreal-engine}. Místy má~příliš mnoho objektové abstrakce, ale~rozhodně velký krok vpřed. Umožňuje snadné dynamické přepínání různých sad ovládání (multiplayer hry, gameplay/menu), dynamické modifikátory a~spouštěče vstupu (změna senzitivity, víceklik, podržení tlačítka určitou dobu), podpora vstupu více než~jedné periferie naráz a~podpora přeřazení vstupu (např.~změna tlačítka odpovídající za~skok herní postavy). Předtím tohle a~spoustu dalšího se~muselo naprogramovat ručně.
\item Podporu vektorové grafiky v~UI. Veškeré staré UI~elementy byly~tvořeny pomocí základních vektorových obdélníkových tvarů právě proto, aby~se~vyhnulo použití rastrové grafiky, která~je~velmi závislá na~rozlišení. Aktuálně všechny UI~elementy jsou tvořeny ještě starou metodou, pro~udržení konzistentního vzhledu. V~budoucnu bychom určitě využili této~možnosti.
\item Přepracované vykreslování textů -- rychlejší vykreslování a~efektivnější využití paměti.
\item MetaSound\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/metasounds-the-next-generation-sound-sources-in-unreal-engine} pro~přehrávaní nebo procedurální generování zvuků, který~nahrazuje starou třídu~Cue. De-facto se~jedná o~Digital Signal Processing (DSP) grafový engine a~editor. Bohůžel jsem nestihl tento nástroj využit v~práci.
\item World partition systém\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/world-partition-in-unreal-engine}, který~dokáže automaticky rozdělit jeden velký svět na~streamovací kousky a~propojit sdílení dat mezi nimi i~při multiplayer hře přes internet. Taky není využit v~této práci.
\end{itemize}
Samozřejmě je~toho daleko víc, ale~většina ostatních vylepšení jako~rovněž nový systémy animací postav Motion Matching\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/motion-matching-in-unreal-engine} nebo~nový fyzikální engine Chaos\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/destruction-overview} neměly vliv na~rozhodnutí.

Podrobné informace jak~každá implementace funguje a~jak s~ní~pracovat, jak~kompilovat a~exportovat projekt  je~popsáno v~přiložené programátorské dokumentaci.

\section{Herní logika, systémy, mechaniky}
\label{sec:systemsAndMechanics}
\subsection{Architektura}
Protože Unreal Engine byl~na~začátku vyvíjen primárně pro~online multiplayer hru Unreal Tournament a~dnes~je stejně~tak vyvíjen spolu s~extrémně velkou online multiplayer hrou Fortnite, je~backend enginu velmi abstraktní. 

Například každý svět musí obsahovat vlastní game mode (třída AGameMode), který~funguje jako~správce daného světa -- přestože svět se~může spravovat sám. Veškerá funkcionalita používaná v~singleplayer hrách mohla být přímo v~kódu levelu nebo~v~globální instanci celé hry. Důvodem této abstrakce je~právě nativní podpora multiplayer her, která~potom vývoj takových her zjednodušuje.

Protože tento projekt je~zaměřen pro~hru jednoho hráče, práce je~často programována navzdory ustáleným UE~C++ zásadám (guidelines) pro~pohodlí a~rychlost vývoje. Proto~často třídy manažerů systémů, game~modů, instance hráče a~další jsou na~architektuře singletonu. Přináší~to nejen zmíněné pohodlí, ale~navíc šetří od~tří do~deseti volání getterů, reflexí (castů), vyhledávání v~hash tabulkách a~iteraci polí v~každém místě použití. Přesto nemá žádný vliv na~stabilitu programu a~dokonce šetří výkonem zařízení.

Jen pro představu, co~obnáší klasické získání reference na~instanci vlastní třídy hráče na~pozadí. GetGameMode()\textrightarrow GetPlayerController(index)\textrightarrow GetPlayerPawn()\textrightarrow Cast<Class>(). A~blueprinty disponují zkrácenou verzí GetPlayerPawn(index)\textrightarrow Cast<Class>(). V~případě~C++ je~potřeba navíc ověřovat zda~nějaké z~volání nevrátilo nullptr.

\subsection{Scény a ukládání hry}
Scény, resp. levely (třídy UWorld a ALevelScriptActor)\footnote{UWorld instance je~přímo celý svět, který~funguje jako~balík metadat a~kontejner pro~veškeré instancované objekty v~něm. ALevelScriptActor je~objekt instancovaný v~UWorld automaticky a~obsahuje uživatelskou logiku světa.}, lze~taktéž získat v~podobě singletonu. Základní implementace byla~rozšířená pro~high level mechanismus volání událostí ve~scéně. Ten~je~zapotřebí například, když~hráč aktivuje spínací plošinu ve~hře a~ta~následně otevře dveře.
\newpage
Na rozdíl od~jiných enginů, v~UE objekty ve~světě nemůžou referencovat jiné~nezávislé objekty. Jednoduše referenci nelze přiřadit z~důvodu abstrakce popsané v~předchozí podsekci, protože~každý objekt může~mít vlastní herní svět (a~nejen~to). Proto~pokud~plošina z~našeho příkladu chce otevřít dveře, musí~zkusit poslat požadavek správci herního světa, ten~požadavek se~nějak zpracuje a~teprvé~poté správce buď~provede akci otevírání dveří samostatně nebo~zavolá odpovídající funkci v~instanci objektu. Pokud~by~bylo potřeba opustit singleton architekturu pro~podporu paralelní existenci světů, stačí předělat členskou (member) funkci instance světa na~statický multicast delegate\footnote{Delegate jsou obaly na~C++ funkce, lambdy, funkce s~reflexi a~funkce z~Blueprintu. Delegate může~být typu single, pro~uložení reference na~jednou funkci, nebo~multicast pro~uložení dynamického seznamu funkcí. Podrobněji jsou~popsané v~programátorské dokumentaci.}, ke~kterému se~každý svět při~konstrukci bude vázat.

Navíc hra byla rozšířena o~implementaci obnovení hry z~úložených dat. Při~návrhu byla~snaha udělat postup co~nejjednodušší. Hra se ukládá pomoci globální herní instance (třída GameInstance)\footnote{GameInstance je~první objekt vytvořený enginem hned po~úvodním načtení základu enginu a~taky poslední objekt na~destrukci při~vypínání hry.} při~vypínání hry a~načítá taktéž při~spuštění. Byl~využit existující systém serializace v~UE, který~ukládá inventář postavy, jméno levelu a~checkpoint na~něm spolu s~posledním stavem levelu.

\subsection{Interakce}
Interakce jsou~často řešeny pomocí architektury interface tříd\footnote{Interface třídy jsou~konkurenčním přístupem komponentní architektuře. Interface je~běžná praktika v~OOP (Objektově Orientovaném Jazyce), která~funguje jako~domluva, že~objekt bude obsahovat určité member funkce. Komponenty jsou~samostatné určité podinstance objektu. Komponentní přístup se~osvědčuje jako~intuitivnější a~více flexibilní zatímco Interface přístup při~vývoji her je~spíše nepříjemné vynucení ze~světu~OOP.} především kvůli populárním návodům vyzdvihující tuto metodu jako~nejlepší ještě~z~doby, kdy~Unreal Engine~4 pouze vznikal. Nevýhodou je~potřeba v~obsáhlém a~repetitivním nastavení každého objektu, který~chceme zapojit do~mechaniky interakce.

Byl navržen komplexní systém pro~správu každého interakčního objektu a~komponent (viz\Cref{fig:InteractableSystemDiagram}). Objekt dědící třídu AInteractable při~instancování samostatně nastaví a~následně přepíná potřebné kolize. Zároveň spravuje interakční komponenty a~reaguje na~požadavky, které~jsou na~ně směřovány. Komponenty se~dělí na~aktivátory a~modifikátory.

\begin{figure}
\centering
\includegraphics[width=1\linewidth]{img/InteractableSystemDiagram.pdf}
\caption{Diagram zpracování systému interakčních objektů.}
\label{fig:InteractableSystemDiagram}
\end{figure}

\newpage
\paragraph{AInteractableActivator} Aktivátory jsou~komponenty s~určitými mechanismy detekce objektů. Instance hráče automaticky vytváří pro~sebe jednu podinstanci každého aktivátoru registrovaného v~enginu. Libovolný objekt může rovněž obsahovat libovolný aktivator. Práce obsahuje klasický způsob detekce objektů pomoci ray~tracingu a~následného dereferencování objektu v~případě nárazu paprsku.

Navíc je~k~dispozici detekce objektů v~zorném poli hráče. Ta~funguje na~zpomaleném snímání určité stencil vrstvy\footnote{Stencil Buffer sousedí s~Z-Bufferem a~má~pouze jeden osmi~bitový celočíselný kanál. Slouží především jako~pomocník při~tvorbě specifických renderovacích technik a~efektů. Nejběžnější použití je~renderování obrysů objektů, označení objektů pro~následné zpracování v~nějaké render pipeline a~tvorba portálů.} s~vynecháním většiny render pipeline a~v~malém rozlišení. Zachycený snímek obsahuje pouze viditelné hráčem interakční objekty v~podobě masky. Následně je~maska v~grafickém vlákně zpracovaná pomocí algoritmu vyhledávání komponent z~počítačového vidění, kterou~poskytuje knihovna OpenCV. Nakonec do~středu nalezených komponent se~promítne paprsek a~zachytí objekty (viz~\Cref{fig:InteractableScreenCapture}).

Původně bylo předpokládáno využití HLSL compute shaderu\footnote{High-Level Shader Language je~proprietární shader jazyk používaný v~DirectX.} pro~vyhledání komponent v~textuře, ale~z~časových důvodů jsem nedodělal přenos dat mezi CPU a~GPU, jelikož dohledat dokumentaci o~použití shaderu je~poměrně náročné. Proto~aktuální vyhledávání komponent je~spouštěno na~procesoru a~v~renderovacím vlákně na~moderních zařízeních trvá pět až~deset milisekund. V~praxi se~tento problém často řeší náhodným promítáním velkého množství paprsků nebo~velkého hitboxu napodobujícího tvar pohledového frustrumu kamery. Tato řešení jsou sice~rychlá na~implementaci, avšak~při~větších vzdálenostech vykazují výrazné snížení přesností a~větší spotřebu výpočetních prostředků. Navíc zahrnují časté počítání nárazů na~velké množství objektů, čímž~výkonnostně nejsou o~nic~lepší metody implementované v~této práci.

\begin{figure}
\centering
\includegraphics[width=1\linewidth]{img/InteractableScreenCapture.pdf}
\caption{Debug náhled aktivace interakčních objektů v zorném poli hráče.}
\label{fig:InteractableScreenCapture}
\end{figure}

\paragraph{AInteractableModificator} Modifikátory jsou~komponenty s~určitou logikou libovolné modifikace objektu, ve~kterém jsou~instancovány. Tyto~komponenty mohou obsahovat pouze objekty označené jako~interakční (dědí třídu interakčního objektu). Aktuální implementace nabízí modifikátory pro~aktivaci nějaké události pomoci dosahu~,,ruky'' nebo zahlédnutím~,,očima'' hráče, pohyb a~rotace předmětu v~prostoru, ukládání předmětu do~inventáře hráče.

Z~časových důvodů byla zamítnuta implementace modifikace geometrie objektu, která~by~využívala nového rozhraní Chaos.

Největší přínos nového systému zpracování vstupu v~Unreal Engine~5 se~projevil právě u~modifikátorů. Ty~využívají možnost dynamického přidávání nebo~odstraňování vstupních kontextů za~běhu.

\subsection{Cutscény a Quick Time Events}
Unreal Engine je~známý~tím, jak~dobře umožňuje animovát scény. Rozhraní a~editor systému Sequencer jsou~přívětivé a~nabízejí široké možnosti. Bohužel~však většina těchto výhod končí mimo samotný editor, jelikož~chybí pohodlné prostředky pro~režii různých souborů animací (totéž platí i~pro~UI animace). Proto byl~dodán systém UCutsceneManager implementující frontu animací spolu s~uživatelským rozhraním pro~jejich přeskakování.

Pro~přiblížení problému, vyjmenuji časté potřeby, které~vznikají při~běžném použití animací.
\begin{itemize}
\item Zároveň spuštěné animace bojují o~vlastnictví objektů,
\item animace nelze přetáčet,
\item u~animace nelze zjistit zpětně zda~byla přehrána až~do~konce, pouze přivázat volání funkce po~ukončení,
\item systém dokáže určit, zda~se~animace někde přehrává, ale~není schopen ukázat, kde~přesně.
\end{itemize} 

Převážně pro~použití v~animacích je~implementována fronta rychlých interaktivních událostí (QTE - Quick Time Events), což~jsou~interaktivní UI~elementy na~obrazovce hráče. V~herním průmyslu jsou~využívány zejména v~cutscénách, pro~,,hlubší ponoření'' hráče do~děje. Klasickými příklady jsou~animace šplhání herní postavy po~nějaké překážce nebo~kinematografický souboj mezi postavami. Při~takových událostech lze~přiblížit hráče k~dynamické a~napínavé situaci pomocí klikání na~stejně dynamické UI~elementy na~obrazovce v~souladu s~pohybem herní postavy. V~praxi se~objevují i~pokročilejší varianty napodobení děje pohybem myší a~joystickem nebo~gyroskopem ovládače. V~implementaci jsou~k~dispozici eventy jednotného a~vícenásobného klikání a~držení tlačítka v~časovém intervalu.

\subsection{Dialogy}
V~enginu je~zavádějící implementace pokročilého dialogového systému. Dialogy jsou~neintuitivní pro~tvorbu a~použití, vyžadují časté repetitivní kopírování stejných parametrů mezi~soubory dialogů a~k~tomu celý systém má~nedostatečnou dokumentaci. Navíc~,,dialogy'' v~tomto systému jsou~pouze samostatné věty, které~musí přehrávat nějaký zvuk a~mohou se~vybírat v~závislosti na~omezeném kontextu typu ,,kdo~na~koho mluví''. O~nepoužitelností takového rozhraní svědčí návody na~tvorbu vlastních dialogů nebo~vývojářský obchod plný pluginů implementujících tento systém lépe.

\newpage
Protože kvalitní řešení jsou~placená a~ty~zdarma jsou~často nevyhovující kvality, byla~navržená vlastní implementace. Jedná~se o~frontu, která~umí přehrávat celé tabulky dialogových vět. Dialog, resp.~množinu vět společného kontextu, lze~pohodlně zapsat do~tabulkového formátu přímo v~editoru. Jednotlivá věta obsahuje id, text, dobu přehrání nebo~zvukovou stopu. Ve~výsledku lze~do~fronty zařadit několik tabulek, které~se~mohou přehrávat sekvenčně od~n-té věty po~poslední, jednu náhodnou větu nebo~přesně jednu větu podle id.

\subsection{Minihry}
Herní průchod druhého levlu je~celý složen z~miniher. V~době vydání práce obsahuje pouze pět~hlavních miniher v~podobě ,,proof of~concept''. Z~časových důvodů nebyly vedlejší minihry implementovány. Každá z~miniher je~parodie na~již existující známou hru.

Minihry jsou samostatné objekty, které~může správce scény restartovat nebo~vypnout. Po~spuštění si~minihra sama přepne kontext ovládání na~sebe a~řídí svůj vlastní stav. Jestli~minihra nebyla ukončena dočasně, ale~dohraná, vráti ovládání zpět hráči spolu s~výsledkem a~skóre.

Dostupné zkušební implementace:
\begin{itemize}
\item Parodie flash hry Age of~War. V~pozadí scény s~úklidem učebnic dějepisu jsou~umístěny základny hráče a~soupeře (umělé inteligence). Hráč ovládá minihru pomicí~UI, kde~nakupuje jednotky typu: pěšák, střelec a~tank. Peníze získává za~zničení nepřátelských jednotek. Vyhrává ten, kdo~dokáže proniknout přes obranu nepřítele až~k~jeho základně a~zničit~ji. V~aktuální implementaci chybí vylepšení jednotek, zvuky, grafické efekty, modely a~animace jednotek. Přesto~lze vyzkoušet nákup a~,,souboj'' jednotek.
\item Parodie na~mobilní hru Subway Surfers. Aktuálně má~minihra nevhodné pozadí, neobsahuje audio a~grafické prvky. Podle návrhu hráč nahání veverku v~lese, která~mu ukradla část důležitého pro~příběh předmětu. Pomocí pohybů nahoru, dolů, vlevo a~vpravo se~hráč vyhýbá objevujícím se~překážkam v~lese. Překážková dráha má~šířku tří~běžeckých pruhů a~překážky mohou vyžadovat přeskočení, sklouznutí nebo~úhyb do~strany.
\item Podoba počítačové rytmické hry Osu!. Hráč má~za~úkol klikat na~objevující~se na~obloze hvězdičky v~souladu s~rytmem hudby (v~pořadí ve~kterém se~objevily). Aktuálně ,,hvězdičky'' jsou~v~podobě čtverečků, ale~hudba je~zcela hotova. Již~teď lze vyzkoušet klikání během prvních 10~sekund hudby.
\item Podoba mobilní hry Crossy Road. Hráč pomocí pohybu dopředu, dozadu, doleva a~dolů potřebuje posouvat se~vpřed po~překážkové dráze. Dráha je~složená z~pěti~pruhů kolmých ke~kameře, a~každý pruh je~složen z~dvanácti políček, na~které~může stoupnout hráč. Náhodně na~krajích pruhu se~objevují divoká zvířata, laviny a~silný vítr (v~originální hře to~jsou auta na~silnici), které~se~posouvají k~opačnému kraji přes všechna políčka a~mohou ukončit běh hráče. Podle návrhu se~minihra odehrává v~ledovém prostředí, kde~hráč prochází sněžnou krajinou. Audiovizuální prvky opět nejsou k~dispozici, ale~již~teď lze vyzkoušet posun dopředu a~úhyb překážkám.
\item Jednoduchá minihra rybolovu (více podob napříč různými hry). Hráč má~na~obrazovce svislý obdélníkový indikátor znázorňující vodní hlubinu. Podél indikátoru se~náhodně pohybuje obrázek rybičky, kterou~hráč musí udržovat v~malé pohyblivé zóně. Zóna se~pohybuje automaticky dolů nebo~nahoru držením tlačítka myší (rychlost pohybu není lineární, ale~kvadratická). V~implementaci chybí zvukové assety a~vyváženost složitosti, ale~je k~dispozici kompletní~UI a~mechanika lovu.
\end{itemize}

\subsection{Nehratelné postavy}
Pro~tvorbu NPC (Non-Playable Characters) byly použité základní prostředky enginu. Podle návrhu hry, k~dispozici měly~by~být tři~druhy logiky pro~NPC, ale~z~časových důvodů jsou~implementovány pouze~dvě. Jedno~z~chování je~pouhá chůze k~dynamickým bodům. Toto~základní chování se~potom rozděluje na~střežení oblasti nebo~boj s~hráčem.

Postavy, které~střeží oblast využívají v~UE5 nový systém vjemů nehratelných postav. Postavy umí reagovat na~zvuky, dotyky nebo~zahlédnutí jiných objektů. Toto~je~využito pro~postavy, které~hlídají vězení v~levelu 4. Ty~patrolují předem navržené trasy a~spouští určité akce až~zahlédnou hráče.

V~implementaci chybí kompletní logika boje s~hráčem. Aktuálně postavy pouze běží k~hráči pokud ho~zahlédnou. Zbytek nedodělané logiky je~spíš vizuálního charakteru a~spočíval~by v~jednoduchých animacích použití střelné nebo~ruční zbraně ve~hře.

Každé chování využívá Navmesh pro~orientaci na~úrovni.

\subsection{Nastavení}
Hra využívá existující v~enginu de/serializaci v~textovém formátu~,,.ini''. Při~exportu hry v~podobě samostatného buildu lze~využívat i~binární formát konfiguračních souborů. Tento~přístup značně zjednodušuje tvorbu konfiguračních proměnných. Díky~tomu stačí pro~tvorbu vlastních parametrů pouze~deklarovat potřebné proměnné v~C++~třídě.

Triviálně se~pracuje s~preferencemi hráče, které~určují hlasitost různých kategorií zvuků nebo~preferencemi ovládání. U~těchto preferencí stačí pouze~přečíst resp.~zapsat hodnotu. Jednoduché to~přestává~být v~momentě nastavení kvality grafiky a~parametrů zobrazení okna aplikace. Zejména změny zaměřené na~okno aplikace mohou způsobit pád~aplikace nebo~ještě hůř zablokovat vstup celého počítače a~donutit uživatele ke~kompletnímu restartování zařízení. Takové~situace mohou nastat celkem běžně, a~nemusí znamenat problém v~aplikaci. Například předčasný zásah~OS k~neodpovídajícímu procesu (hra se~delší dobu načítá po~aplikování nového nastavení) nebo~nevhodná reprezentace rozlišení, které~monitor nebo~GPU uživatele nepodporuje.

V~libovolném případě hra musí~být~schopna obstát nečekané závady, a~proto byl~navržen mechanismus obnovení předchozích funkčních nastavení. Po~zvolení nových parametrů a~jejich aplikování, hra nejprv~uloží stávající nastavení a~až~poté aplikuje ty~nová. Po~aplikování a~až se~proces okna vrátí zpět do~renderujícího stavu, v~menu se~objeví okénko po~dobu pěti~sekund očekávající schválení od~uživatele. Pokud~uživatel stihne potvrdit úspěšnou změnu parametrů, jsou~uložené jako~funkční. Pokud~uživatel z~libovolného důvodu změnu neschválí, potom jsou~obnoveny předchozí parametry.

\newpage
Právě nastavení zobrazení okna (a~výběr zhlazovácí metody) byly implementovány navíc, jelikož~nejsou volně k~dispozici v~high-level implementaci enginu. Jedná~se~o~možnost výběru rozlišení a~jeho třídění podle poměru stran, změna režimu vykreslování okna (bezokenní, okenní bez~rámce, okenní s~rámcem) aЁzměná obnovovací frekvence. Při~výběru a~nastavení rozlišení se~pracuje přímo s~DirectX\footnote{DirectX je~množina API pro~práci s~grafikou a~převážně pro~počítačové hry.} rozhraním a~zhlazovací metoda se~nastavuje přes~příkazové rozhraní enginu.

\section{Návrh tvorby generativního obsahu a jeho načítání za běhu}
\label{sec:contentGenerationAndIntegration}

\subsection{Možností generativních modelů v tomto projektu}
Herní úrovně jsou navrženy~tak, aby~pokrývaly rozsáhlé herní žánry a~situace, které~dosud~nebyly nebo~nejsou~často využívané s~generovanou tvorbou.
\begin{enumerate}
\item Level je~zaměřen na~tvorbu hororového obsahu. Je~to~skvělá příležitost vývoje a~použití modelu, který~využívá naše~fyzické, chemické a~psychické znalosti o~lidském organismu, aby~dokázal generovat strašidelný obsah a~následně ho~vhodně začlenit.
\item Level slouží k~testování modelu schopného tvorby libovolných miniher. Nabízí~se~tady~taktéž online tabulka skóre pro~základní a~vygenerované minihry.
\item Level existuje pro~generování nových logických úseků a~úkolů a~modifikaci stávajících logických překážek. Například nová logika zapojení kabelů v~elektrotechnické místnosti nebo~přestavba bludiště.
\item Level umožňuje vyzkoušet generování sekvencí chodeb. Chodby by~musely obsahovat patroly a~kryty~tak, aby~hráč dokázal nenápadně prolézt skrz patroly.
\item Poslední Level bude testovat schopnost navržení herních nepřátel, jejich logiku a~rozmístění na~úrovni. 
\end{enumerate}

\subsection{Návrh architektury}
Architektura generování obsahu je~založená na~použití zřetězení různých modelů a~kontrolních mechanismů. Kompletní řetězce modelů jsou~nasazeny na~soukromých serverech, které~v~různých intervalech nezávisle produkují nové assety. Po~generování jsou hotové soubory přemístěny na~veřejné úložiště, odkud~hra při~zapínání stahuje několik~,,náhodných'' assetů (přesnou definici výběru obsahuje \cref{par:contentSharing}).

\paragraph{Fine-tuning} V~podobě open-source je~k~dispozici většina potřebných druhů modelů. Po~analýze vyplývá, že~bude~potřeba vytvořit pouze jeden~model, který~bude~schopen pracovat s~kódem v~Unreal Engine. Je~to~potřeba pro~programování assetu nebo~aspoň~jeho~umístění ve~světě hry. Nejjednodušší a~zároveň efektivní cesta je~založená na~fine-tuningu resp.~dotrénování modelu, který~se~již~využívá pro~programování.

\newpage
Dotrénování může~mít více~podob. Nejspíš by~se~jednalo o~fine-tuning programovacího modelu v~C++ s~dodatečnou syntaxí Unreal Enginu nebo~fine-tuning tvorby diagramů v~Blueprintech. Výsledné blueprinty potom~lze konvertovat do~Python příkazů, které~vytvoří vygenerovaný diagram v~editoru. Nelze jednoznačně říct, který~přístup je~vhodnější. Pro~C++~model je~k~dispozici více dat a~toto prostředí umožňuje větší tvůrčí svobodu, přestože~může zhavarovat aplikaci. Blueprinty jsou~zdaleka bezpečnější, ale~na~oplátku bude~těžší sbírat trénovací data.

\paragraph{Postup generování}
Vše~by~začínalo v~textovém modelu, který~vytvoří typ a~popis generovaného objektu. Pomocí třídícího mechanismu se~vybere příslušná množina dalších modelů, kontrolních mechanismů a~konverzních nástrojů. Asset bude~postupně procházet takovým řetězcem až~nabyde finální podoby. Na~konci bude~vždy kontrolní mechanismus, který~zvaliduje soubor a~ověří funkčnost assetu pomocí unit-testů ve~hře. Pokud~asset neprojde validací, celý postup, soubor a~vstupní popis se~zaznamenají pro~budoucí ruční doladění modelu.

Příklad tvorby interakčního objektu:
\begin{enumerate}
\item LLM vytváří popis assetu, v~tomto případě interakční objekt, který~přehrává specifický zvuk a~je~umístěn na~konkrétním místě v~levelu~3.
\item Kontrolní mechanismus vybírá následující potřebné modely a~nástroje.
\item Popis prochází modelem generující obrázky.
\item Obrázky prochází modelem generující 3D~model (nejdřív se~generuje 360°~video potřebného objektu, ze~kterého se~následně generuje mesh).
\item Další část popisu je~použita modelem generující zvukové stopy.
\item Poslední část popisu se~vloží do~našeho dotrénovaného programovacího modelu. Tento~model se~zároveň stará o~umístění assetu v~herních světech, protože~jako~jediný je~natrénovaný na~kontext této~hry.
\item Výsledné kousky linkovací mechanismus spojí do~jedné~třídy resp.~vloží do~jednoho Blueprintu. Předtím převede jednotlivé části na~assety v~enginu a~případně aktualizuje cesty referencí.
\item Konečný asset se~zkouší na~kompilaci a~prochází unit-testy. Pokud~tento~krok bude úspěšný, asset je~exportovan v~podobě~DLC nebo~patch~obsahu. Jinak~popis, vygenerováné částí a~výsledek se~logují pro~budoucí investigaci.
\end{enumerate}

\subsection{Poskytování obsahu}
\paragraph{Nasazování generátoru} Nezávislé řetězce modelů zjednodušují řízení sítě workerů. Pomocí Docker kontejneru\footnote{Docker je~software umožňující lokální virtualizaci prostředí nazývané kontejnery. Kontejnery jsou~předvytvořené samostatné prostředí s~potřebnými nástroji.} nebo~nasazovacího skriptu by~se~snadno vytvořil další worker (naše~generující jednotka), který~může ihned~začít s~generováním. Vygenerovaný obsah je~poté přemístěn na~veřejné úložiště, tedy~worker nepotřebuje nijak~velké vlastní úložiště.
\newpage
Protože~workery nemusí~odpovídat na~požadavky uživatele v~reálném čase a~plánovaná doba jedné hry je~15-30~minut, generátory nemusí~být~rychlé a~tedy~ani~náročné na~výpočetní prostředky. Nezáleží~nám ani~na~dlouhodobé životnosti workerů, jelikož~modely se~často sekvenčně přepínají (běží vždy pouze jeden model najednou). Takový~přístup přináší flexibilitu v~řízení prostředků a~umožňuje ukládat mezistavy generátorů. Dokonce nepotřebujeme nijak~velkou propustnost sítě, protože~jednoduché assety nemohou přesahovat velikost jednotek megabajtů a~jistě~máme větší časové intervaly mezi~vznikem souborů.

\paragraph{Stahování obsahu}\label{par:contentSharing} Hra automaticky stahuje a~aktivuje obsah před začátkem nové hry. Z~podrobné analýzy jsem~rozhodnul, že~nejsou~zapotřebí žádné autentifikační nebo~šifrovací vrstvy. Vždy~by~byla~možnost zpětnou analýzou (reverse-engineeringem)\footnote{Reverse-engineering je~metoda analýzy hotového produktu (v~nášem~případě binárního souboru), pro~získání neveřejných informací popisujících funkčnost produktu.} získat klíč z~binárních souborů hry a~napadnout celý systém. Když~se~nad~tím zamyslíme, volný přístup k~generovaným assetům nemá žádné zápory. Je~jednoduchý na~implementaci a~údržbu. Očekává~se ale připojení pomocí HTTPS\footnote{Hypertext Transfer Protocol Secure je~protokol pro~šifrovaný přenos dat využívaný pro~poskytování webových serverů.} a~ověření certifikátu\footnote{Certifikáty v~digitální podobě jsou~řetězcem veřejných asymetrických klíčů různých vydavatelů. Každý~předchozí vydavatel ručí za~důvěryhodnost dalšího vydavatele.} s~kopií uloženou v~aplikaci. Mohlo~by~totiž dojít k~man-in-the-middle útoku\footnote{Man-in-the-middle (MITM) je~druh kyberútoku, ve~kterém útočník tajně sleduje nebo~upravuje komunikaci mezi~dvěma uzly.} a~hráč by~mohl spustit ve~hře nebezpečný obsah.

Hra zahájí stahování pomocí API, který~vybere nějaké soubory. V~základu assety jsou~vybírány náhodně, ale~zároveň se~používá hodnocení získané od~hráčů, které~váhově lehce~mění hustotu pravděpodobnosti normálního rozdělení.

\paragraph{Hodnocení obsahu} Poté, co~si~hráč zahraje s~určitým assetem, máme~možnost získat zpětnou vazbu od~hráče. Hodnocení využíjeme k~váhové manipulaci náhodného výběru a~zároveň jako~data pro~doladění generátorů. Návrh~systému hodnocení staženého obsahu je~již náročnější problém. Úkolem je~umožnit pouze unikátní hodnocení a~pouze od~hráčů, kteří~si~s~tímto obsahem opravdu zahráli. Protože~nemáme žádnou autentifikaci, volné~hodnocení nemusí fungovat. Kdokoliv může~spamováním falešných hodnocení přemístit špatně hodnocený obsah do~kategorie lepších a~naopak. Autentifikace tomu~také nezabrání, pouze~oddálí takovou situaci.

Některé hry v~praxi používají sofistikováné metody využívající detekci nelegální kopie hry, nebo~využití API herních obchodů (achievementy, odznaky, ID~účtu~atd.). Takové metody se~zdají~být účinné, ale~už~dávno se~lehce obchází pomocí triviální simulace odpovědí API.

Táto práce nabízí sledování ID~účtu hráče, který~hru zahrál a~jeho seznam stažených souborů, pokud~hra bude šířená na~platformě Steam. UUID (Unique User Identifier) účtu ví~pouze vlastník účtu, čili~je~to citlivá informace. Proto~před odesláním takových dat je~budeme vždy šifrovat asymetrickým klíčem (veřejným certifikátem webu ze~kterého~zároveň obsah stahujeme). Až~bude hráč chtít ohodnotit ve~hře obsah se~kterým~zahrál, API~zkontroluje zda~UUID~hráče na~Steamu opravdu vlastní hru, že~toto~UUID stahovalo tento~obsah z~našeho serveru a~že~toto~UUID ještě tento~obsah nehodnotilo.

Pokud~by~hra byla~šířená zdarma, bude~potřeba zavést omezení na~N~hodnocení denně pro~jedno~UUID, protože~bude~možné bezproblémově vytvářet falešné účty. Jinak, z~ekonomických důvodů, nám~nebude vadit, že~někdo bude~nakupovat hru víckrát, aby~víckrát nevhodně ohodnotil obsah.

Pořád bude možné reverse-engineerovat~API a~zapsat stažení libovolného obsahu pro~nějaký účet. Taková situace je~zcela zanedbatelná, jelikož~jedno~hodnocení má~malý vliv na~průměr ve~větších číslech.

\subsection{Problémové typy obsahu}
Již teď je možné předpovědět co~nebude kompletně fungovat nebo~nebude fungovat v~dostatečné kvalitě.
\begin{itemize}
\item Herní obsah tvořený ručně nástroji v~editoru vyžadují samostatné modely. Například animace objektů na~levelu tvořené v~Sequencer, tvorba~UI~v editorovém designeru, práce~se~zvuky v~Cue, statická tvorba úrovní a~tedy i~Landscape nebo~foliáž a~tvorba fyzických objektů (simulace tkáně, destrukce, pružnosti a~dalších~jevů). Pravděpodobně i~jiné, ale~víc technologií v~této práci využito nebylo.
\item Materiály též vyžadují vlastní model, ale~jsou tvořeny pomocí grafových prvků podobné blueprintům a~máme k~dispozici velké~množství dat pro~trénování takového modelu. V~základu můžeme vystačit si~bez~generování materiálů a~pouze vytvářet variace barev.
\item Grafické provedení generovaných objektů může~mít velký dopad na~výkon hry. Optimalizaci může provést další model, který~bude provádět retopologii\footnote{Retopologie je proces zjednodušení složité topologie 3D~objektu bez~značně viditelných změn.} a~pro~tvorbu kolizí lze~použít k-DOP\footnote{k-DOP (k-Discrete Oriented Polytope) je~jeden z~postupů obalování složitých 3D~objektu do~jednodušších tvarů.} algoritmus dostupný~v~UE.
\end{itemize}

\section{Grafika}
\label{sec:graphics}
\subsection{Statické objekty}
Engine disponuje modely základních tvarů (krychle, koule, válec) a~navíc lze zdarma vzít libovolné assety z~balíčku Starter Content\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/starter-content-in-unreal-engine} nebo~assety použité v~demo projektech společnosti Epic~Games. Přestože assety mají souvislý styl, většinou jsou~zaměřeny na~konkrétní prostředí, a~proto~v~další~hře nemusí najít využití. Zřejmě lze nahrát vlastní modely, které~lze~ručně vytvořit nebo~obstarat na~libovolné online platformě.

V~Unreal Engine verze~5 navíc přidali funkčně bohatý editor 3D~modelů. Tvůrci propagují editor tak, že~v~něm lze vytvářet vlastní modely, protože~množina funkcí dovoluje tvořit hardsurface a~sculpting modely, ale~aktuální provedení není~dostačující ve~srovnání s~dedikovaným softwarem.
\newpage
Drobné editovací funkce na~druhou stranu jsou~užitečné a~šetří čas. Ty~umožňují například editování UV~map, normálových vektorů plošek nebo~změnu středového bodu modelu. ,,Best practice'' je~využití tohoto editoru pouze v~případě nouze (například časová výhoda nebo~neexistence původního souboru), jinak~je~v~dlouhodobém měřítku prospěšné editovat původní verzovaný soubor.

\paragraph{Použití cizích assetů} Rychlejší a~občas jednodušší je~získání assetů třetí strany. K~tomu~existují různé volně dostupné webové platformy. Jednou z~takových platform je~FAB\footnote{https://www.fab.com/}, která~navíc má přímou integraci s~UE~5. Objektivně FAB nemá dostatečně velký výběr assetů, jelikož nemá ani~dostatečnou popularitu vývojářů a~tvůrců. Příčinou jsou~hlavně větší platformní marže z~prodeje a~sice jednoduchý, ale~přesto nevýhodné licencování produktů pro~kupující stranu. Tyto a~další problémy popisují i~jiní uživatelé na~fórech\cite{fabRealityCheck}.

Z~finančních důvodů, v~této praci byly využity pouze produkty dostupné zdarma. Neznamená~to, že~vše~končí pouhým stahováním souborů a~vložením do~editoru. Často (v~této práci všech~100\%) assety nevykazují známky optimalizace nebo~profesionální tvorby. Modely tak~mají některé normaly plošek invertované\footnote{Invertované normály plošek jsou při~tvorbě objektů běžné a~triviálně řešitelný problém, který~často způsobuje, že~ploška ve~scéně není vidět, jelikož~se~vykresluje pouze ve~viditelném směru normálového vektoru a~tedy vytváří ,,díry'' v~objektu.}, středové body jsou~nesmyslně mimo, textury a~UV~mapy je~potřeba kompletně předělat. Nejhorší jsou primitivní objekty, které~mají bezdůvodně velké množství vrcholů. V~praxi se~nachází i~náhodné vrcholy bezúčelně existující v~prostoru modelu.

\paragraph{Vlastní tvorba} Vlastnoručně jsou tvořeny modely ze~staré verze hry a~během vývoje této práce se~pouze upravovaly nebo tvořily textury. Standardem v~oboru jsou~obecně Maya\footnote{https://www.autodesk.com/products/maya/overview} nebo~3ds~Max\footnote{https://www.autodesk.com/products/3ds-max/overview} pro~víceúčelové zpracování a~úpravy, ZBrush\footnote{https://www.maxon.net/en/zbrush} pro~sculpting a~Substance~Painter\footnote{https://www.adobe.com/products/substance3d/apps/painter.html} pro~texturování objektu. V~tomto projektu byl použit výhradně Blender\footnote{https://www.blender.org/} a~software pro~editaci obrázkových formátů, které~jsou k~dispozici na~internetu zdarma. Výsledný model lze často bez~problémů rovnou využít v~enginu.

\paragraph{Modeling a Sculpting} Nejprve se~vytváří tvar modelu. Toho se~docílí pomocí modelování polygonů nebo~sculptingu. Obě~metody jsou velmi odlišné a~stejně~tak mají odlišný výstup. 

Sculpting se~provádí především přes~grafický tablet, kde~pomocí různých 3D~štětců se~natahují nebo~smršťují vrcholy a~celý proces napodobuje tvorbu sochy z~plastického materiálu. Především takový přístup se~používá pro~tvorbu organických modelů nebo~modelů s~měkkým povrchem jako~například živé bytosti, rostliny nebo~oblečení.

\newpage
Modeling na~druhou stranu je obecnější zpracování vrcholů, hran a~ploch. Tady se~manuálně přidávají resp.~odebírají a~posouvají vrcholy. Navíc toto~prostředí obsahuje funkce umožňující různé druhy efektivního instancování, množinových operací mezi objekty a~zjednodušených simulací vrcholů. V~takovém prostředí se~tvoří především komplexní resp.~hybridní nebo~tvrdé povrchy jako~například nábytek, architektura nebo~scény se~sculpting modely.

Specifickou sculpting instancí v~enginu je Landscape\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/landscape-overview}, de-facto síť vrcholů předem určené hustoty, kterou~můžeme v~editoru sculptovat a~napodobovat křivý resp.~různě vysoký terén. Manuální sculpting je pomalý a~přináší slabé až~nevyhovující výsledky. Proto místo sculptingu se~používá výšková neboli height~mapa, což~je textura odstínů šedi, kde~každý pixel kóduje výšku v~3D prostoru. Potom stačí naskenovat nějaký povrch v~reálném světě a~získat skvělé výsledky. Stejné height~mapy lze používat i~jako~štětce v~běžném sculptingu, pro~specifické detalizace povrchů, a~samotné height mapy lze získat na~některých online platformách dokonce zdarma. Ukázka landscapu je k~dispozici ve~druhé úrovni, kde~povrch terénu jsem vytvořil pomocí textury výšek a~hory jsem tvořil ručně základními štětci. 

\paragraph{Animace} Animace se~tvoří v~dalším kroku modelingu. Pokud jsme předtím vytvořili model pomocí sculptingu, potřebujeme ho importovat do~modeling prostředí. Začíná~se tvorbou umělé kostry z~tzv.~kostí a~kloubů.

Klouby slouží pouze ke~specifikaci hierarchie mezi kostmi tak, že~kost propaguje vlastní modifikaci na~všechny následující. Navíc specifikují střed rotačního bodu.

Kosti jsou samostatné absraktní označení pro~nosič prostorových transformací, pro~který~můžeme přiřadit množinu vrcholů. Potom v~logice animace stačí pouze posouvat určité kosti a~předrenderovácí engine bude souvislé modifikovat přiřazené vrcholy. Navíc kostí často modifikují vrcholy podle předem určené váhy pro~každý vrchol, čímž~lze škálovat a~skládat posuny různých kostí na~určitých vrcholech. Jen~je~potřeba brát v~úvahu, že~skeleton animace neboli modifikace provedené předrenderovacím enginem jsou spuštěné na~CPU, jelikož jsou řízeny logikou herního světa. Naštěstí moderní procesory s~instrukčními sadami AVX a~více jádry v~takových úlohách dokážou předvádět poměrně skvělé až~nadbytečné výkony.

V~Unreal~Engine~5 přidaly rozhraní pro~tvorbu skeleton animací přímo v~editoru. Předtím bylo možné pouze hotové animace naimportovat. Uvnitř editoru je příliš mnoho způsobů jak~režírovat animace (myšleno přehrávání, slepení přechodů, modifikace, skládání atd.) a~lze se~v~tom jednoduše ztratit. V~základu je předpokládaná tvorba state-machine, který~bude přehrávat a~cyklit jednotlivé animace v~závislosti na~větvení grafu a~podmínkách hran.

Táto práce obsahuje pouze jednoduché animace postav, které~byly přeneseny ze~staré verze. Animace hráče navíc disponuje imersivním\footnote{Imersivita je označení pro~větší stupeň uživatelské odezvy nebo~pocit přítomností a~ponoření do~děje hráčem.} otáčením trupu a~animace nohou jsou přitahovány k~podlaze pomocí inverzní kinematické metody\footnote{Inverzní kinematická metoda umožňuje procedurální modifikaci skeleton animace.}.

\newpage
Tráva viditelná v~první a~druhé úrovní je animovaná pomocí offsetů vrcholů. V~reálném čase pod~hráčem se~generují částice s~barevným gradientem kódující offset v~prostoru. Takové~částice jsou viditelné pouze pro~speciální render target menší velikosti -- snímá~se pouze blízké okolí hráče. Materiál trávy následný render target interpretuje jako~texturu, kterou~interpoluje spolu s~texturou jednoduchého procedurálního shaderu větru dostupného v~enginu. Výsledkem je~výkonná procedurální animace reakce na~vítr a~chůzi hráče v~okolí objektu obsahující velké množství instancí resp.~vrcholů.

\paragraph{Texturování} Za~účelem texturování nejdřív potřebujeme objektu určit jedinečnou UV~mapu, která~bude mapovat plošky 3D~modelu na normalizovaný prostor 2D~obrázku. Často tvůrci mají na~začátku problém pochopit o~co~se~vlastně jedná a~jak~model rozložit. K~tomu může napomoci myšlenka s~rozlepováním resp.~slepováním hran papírové figurky. Celý koncept UV~mappingu je totožný se~zpětným procesem tvorby například papírové krychle, kde~rozbalenou krychli skládáme z~jednoho uceleného kousku materiálu.

Když máme hotové mapování, můžeme volně přiřazovat textury, které~mohou určovat barvu vrcholů, modifikovat jejich normálový vektor, lesk, matnost, průhlednost a~případně další. Přibližně do~roku~2014, kdy~vznikl Substance Painter a~dnes i~jeho alternativy, jediný způsob texturování objektu bylo manuální kreslení navrch vytvořené mapy. Dnes existují uživatelsky příjemné programy, kde~stačí kreslit rovnou komplexní materiály na~povrch 3D~modelu a~aplikace sama obstará data všech textur.

V~tomto projektu většina objektů nepoužívá difuzní textury ale~jednoduché vybarvení určitých skupin plošek. Přesto jsou často využívané normal mapy nebo~masky průhlednosti. Bohužel se~musely zahodit mapy pro~tesselaci\footnote{Teselace je technika podrozdělení a~modifikace plošek za~účelem zvětšení detalizace objektu.} povrchů používané v~staré verzi projektu, jelikož s~příchodem UE~5 tvůrci odebrali celou podporu tesselace kvůli technologii Nanite. 

\paragraph{Exportování a Importování}
Workflow nebo~pipeline exportu jsou standardizované v~profesionálních softwarech jako~3ds~Max. Blender má pouze základní možnosti exportu, které~je potřeba nejdřív přizpusobit specifickému hernímu enginu. Potřebné minimum je zajištění správné interpretace dopředního a~vrchního vektorů celého modelu. Taky se~vyplatí:
\begin{itemize}
\item nastavit šablonu pro~všechny budoucí projekty, tak~aby~modelovací program a~herní editor sdíleli měřítko jednotek,
\item vyzkoušet, jak~se~chová exportovaná hierarchie modelů v~jednom souboru,
\item před exportem ověřit, že~všechny plošky modelu mají správně natočený normálový vektor (očekává~se směr mířící ven z~objektu).
\end{itemize}

Unreal Engine je standardem herního oboru a~proto verze~5 implementuje systém importovacích pipelines. Jedná~se o~mocný nástroj, který~citelně zrychluje a~sjednocuje postupy importování různých assetů nebo~dokonce stejných assetů podle specifických filtrů (adresář assetu, typ, obsah, podřetězce názvu atd.). Subjektivně největší výhodou je předání zodpovědnosti specifického importu pouze osobám v~týmu s~odpovídajícími znalostmi.
\newpage
V~praxi týmový senior založí pipelines pro~často využívané importy~tak, aby~odpovídali vnitřním firemním politikám a~proto celý tým nemá žádné starosti při importu assetů.

\paragraph{Optimalizace} I~když objekty jsou statické, stále vyžadují optimalizace. Takové lze najít i~v~tomto projektu:
\begin{itemize}
\item Instancování se~využívá k~tvorbě prostorů hustých na~specifické modely. V~UE se~jedná o~editovací prostředek sousedící vedle Landscape. Umožňuje pokročilé nastavení různých množin instancí a~jejich parametry náhodného umístění.
\item Optimální topologie objektu pro~minimalizaci vrcholů potřebných k~vykreslování. Převážná většina modelů -- patří sem i~získané od~třetích stran -- mají mnou ručně přepracované topologie. Jedná~se nejen~o~jednoduchou redukci nepotřebných vrcholů, ale~taky použití létající neboli floating geometrie. Tato~metoda spočívá v~protínání plošek, místo skutečného propojení vrcholů někde uprostřed, jelikož takové propojení by~vyžadovalo podrozdělení plošek, což~by~vedlo ke~zbytečnému zvětšení počtu vrcholů (viz \Cref{fig:FloatingGeometry}). Taktéž objekty mají redukovanou k-DOP kolizní topologii, pro~urychlení výpočtů fyzických simulací.
\item Modely náročné na~vykreslování nebo~použité v~instancování používají LOD~technologii (viz \Cref{fig:LodShowcase}). Nanite v~práci nebyl využít.
\end{itemize}

\begin{figure}
\centering
\includegraphics[width=1\linewidth]{img/FloatingGeometry.pdf}
\caption{Floating geometrie využitá v~modelu okna. Vlevo je výsledný vzhled, uprostřed floating geometrie (48~vrcholů a~52~trojúhelníků) a~napravo běžná naivní topologie (64~vrcholů a~152~trojúhelníků).}
\label{fig:FloatingGeometry}
\end{figure}

\begin{figure}
\centering
\includegraphics[width=1\linewidth]{img/LodShowcase.pdf}
\caption{Ukázka LOD instancí kytky.}
\label{fig:LodShowcase}
\end{figure}

Optimalizace textur je zajištěná pouze hlídáním rozumných rozlišení. Jinak některé textury je určitě možné seskupit do~jedné a~výběr instance řídit pomocí UV~mapy, což~zrychlí přístup k~datům.

Jiná grafická optimalizace není řešená. Modely použité v~instancování občas mohou vyvolat snížení výkonu, což~by~bylo potřeba už~řešit nahrazením plnohodnotných modelů za~kolekce průhledných textur (billboard metoda popsaná v~další podsekci).

\subsection{Dynamické a procedurální objekty}
\paragraph{Sequencer} Běžná dynamická animace se~vytváří přímo v~editoru objektu Sequencer\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-sequencer-movie-tool-overview}. Taková animace dokáže modifikovat parametry objektů na~úrovní a~volat funkce v~určité okamžiky. Objekty mohou~být určené předem nebo~Sequencer umí dynamicky vyhledat jejich reference před~spuštěním. Právě v~tomto prostředí se~tvoří cutscény nebo~cyklické animace objektů na~úrovni.

\paragraph{Procedurální generování} V~předchozí verzi hry model trávy byl vytvořen pomocí billboard metody, kde~místo vykreslování 3D~geometrie vegetace, se~vykresluje průnik ploch s~texturou vegetace a~průhledným pozadím. Tato~technika je~standardem ve~videohrách, přesto nestačila ke~splnění dizajnových účelů projektu. Buď~vegetace musela být řídká, nebo~vyžadovala nesmyslně mnoho hardwarových prostředků a~občas vzniklo i~drobné zmrazení aplikace.

\newpage
Pro~tento účel jsem implementoval nástroj pro~editor, který~podle určitých parametrů je~schopen vygenerovat náhodnou a~hustou trávu z~trojúhelníků. Výsledný objekt má několikanásobně více geometrických dat než~billboard metoda, přesto~má skvělý výkon a~navíc vegetace působí mnohem hustěji, má kvalitnější vzhled a~lépe reaguje na~offset vrcholů v~shaderech (viz \Cref{fig:GrassShowcase}). Trik~je v~přenesení velké texturové zátěže s~převýpočty průhledností na~vykreslování jednotné a~jednoduché 3D~geometrie. K~tomu, generativní přístup umožňuje kvalitnější pokrytí ploch, jako~například v~tomto projektu, kde~tráva se~generuje pouze v~oblastech určité velikosti a~jestli jsou pokryté určitým materiálem, tedy~tráva se~negeneruje na~cestičkách a~mezi povolenou a~zakázanou plochou je pozvolný přechod ve~velikosti jednotlivých stebel. Takový přístup byl inspirován hrou Ghosts~of~Tsushima od~studia Sucker~Punch~Productions, kde~autoři si~vytvořili podobný proprietární nástroj, jelikož chtěli dosáhnout husté kinematografické a~stylistické vegetace na~konzolích.

\begin{figure}
\centering
\includegraphics[width=1\linewidth]{img/GrassShowcase.pdf}
\caption{Ukázka procedurální~(vlevo) a~billboard~(vpravo) metod pro~vykreslování vegetace. Procedurální metoda má přibližně 6-krát menší render time a~paměťové požadavky.}
\label{fig:GrassShowcase}
\end{figure}

\subsection{Osvětlení}
Téměř každý objekt osvětlení sdílí podobné parametry, které~mohou definovat~to, jak~světlo vypadá nebo~ovlivňuje prostředí. Vedle běžných dizajnových parametrů nechybí ani~široká škála technických triků a~úskalí.

\paragraph{Forward shading} Jelikož celá hra je v~režimu forward shading, -- podle tvůrců enginu obsolete funkcionalita čekající na~plný rework, -- některé technologie jsou značně omezené nebo~nefungují a~zhoršuje~se~to s~každou novou verzi. Například časem přestal fungovat Rect Light, který~ale~můžeme napodobit~tak, že~Point Light zdroji přiřadíme IES~texturu, která~nám specifikuje způsob šíření světla neboli~tvar světla v~herním světě. Stejně~tak lze~vytvořit vlastní Light Function, což~je~materiál definující co~a~jak světelný zdroj vyzařuje.

\newpage
Navíc je potřeba pamatovat na~reálná technická omezení forward shadingu, jako~nejvýše tři~zdroje světla na~jeden objekt a~nedostatek SSAO nebo~SSR. S~čímž~stále si~můžeme poradit. Pokud~je potřeba víc zdrojů světel ve~scéně, máme k~dispozici tři~kanály, které~můžeme specifikovat pro~konkrétní objekt a~zdroj světla. A~pokud~nutně potřebujeme ambientní okluzi můžeme použít Lightmass Volume\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/cpu-lightmass-global-illumination-in-unreal-engine} pro~jeho simulaci a~stejně tak~můžeme použít Planar~Reflections\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/planar-reflections-in-unreal-engine} pro simulaci odrazů.

\paragraph{Základy osvětlení} Kromě bodových světel na~úrovní téměř vždy chceme přidat globální osvětlení, který~sestává z~Directional~Light a~Sky~Light.

Directional zdroj funguje jako~jeden velký bodový zdroj pro~celou scénu, který~napodobuje funkci slunce a~slouží primárně k~vykreslování stínů. Zdroj typu Sky~Light také~může ovlivňovat stíny, ale~primárně zobrazuje Skybox texturu a~modifikuje ambient složku celého osvětlení.

Navíc pokud chceme zobrazit venkovní prostory, je dobré použít nějakou formu mlhy, jako~je Ambient~Fog. Mlha přidá pocit velkého a~neomezeného prostoru i~když ve~skutečnosti je malý a~uzavřený. Navíc mlha výborně skryje a~tedy~umožní horší detailizaci objektů v~dálce, čímž~efektivně zkrátíme dobu vykreslování snímku.

Nakonec se~lze odchýlit k~použití mnoha různých Volume objektů, které~z~důvodů rozsahu práce nebudou podrobně probrány. Pomocí těchto prostorů lze~specifikovat oblastí s~určitými parametry, které~budou napovídat enginu potřebné optimalizace, nebo~zapínat výkonnostně náročné vykreslovací technologie. Pro~představu Lightmass~Importance~Volume\footnote{https://dev.epicgames.com/documentation/en-us/unreal-engine/lightmass-basics-in-unreal-engine} specifikuje oblast, kde~je potřeba propočítat větší počet odrazů paprsků světla.

\subsection{Post-Processing}
Post-Processing lze~definovat přímo v~kameře nebo~v~již zmíněných Volume objektech. Každá~definice je de-facto materíál, který~lze vrstvit mezi sebou. PP~vyžaduje hlubší grafické znalosti, aby~bylo možné vytvořit něco užitečnějšího než~barevnou korekci. Zároveň kvůli tématice práce pouze nastíním jak~jsem naimplementoval PP~materiály (viz~\Cref{fig:PPShowcase}), které~mají gamedizajnový důvod, ale~se~nestihli použít.

\begin{figure}
\centering
\includegraphics[width=1\linewidth]{img/PPShowcase.pdf}
\caption{Ukázka post-process materiálů ve~hře. Efekt deště jsem nedokázal rozumně zachytit.}
\label{fig:PPShowcase}
\end{figure}

\begin{itemize}
\item Plovoucí obrazovka - UV~prostor obrazu se~lehce zakřiví pomocí animované šumové textury.
\item Námraza - obraz interpolujeme s~animavanou texturou. Nejlépe použít nějaký gradient uprostřed jako~masku průhlednosti, aby~hráč měl čistší vidění.
\item Stylová dálková kamera - obraz rozložíme na~trochu sesunuté proužky dle~rozlišení výstupu a~zároveň tyto~proužky střídavě obarvíme. Nakonec proužky animujeme posunem nahoru nebo~dolu.
\newpage
\item Déšť - obraz rozložíme na~jemnou mřížku a~v~blocích vygenerujeme různé kapky pomocí složení dvou turbulencí, každá~z~kterých bude mít animovanou lehce odlišnou rychlost posunu, aby~kapky nebyly stále stejné. Paralelně k~tomu znovu rozložíme obraz, ale~teď na~hrubou mřížku, kde~animujeme svislé pády bloků s~gradientním ocasem. Oba~výstupy složíme~tak, že~hruba mřížka představuje animovanou masku průhlednosti, která~nám bude v~různý okamžik otevírat pouze některé kapky. Nakonec přidáme trochu distortion a~výsledek použijeme jako modifikátor UV~výstupního obrazu.
\item Pixelizace - obraz rozložíme na~potřebnou mřížku dle~rozlišení a~modifikujeme UV~prostor výstupního obrazu.
\item Tavení pixelů - vytvoříme netriviální vertikální gradient s~více přechody. Výsledek znečistíme zaokrouhlováním a~násobením dat, zpixelizujeme rozdělením na~mřížku a~výsledek použijeme k~modifikaci UV~prostoru výstupního obrazu a~barevné korekci.
\item Slepota - výstupní obraz nahradíme vlastním, ve~kterém zobrazujeme pouze ohraničení objektů s~efektem emise. Ohraničení lze dosáhnout různými způsoby a~v~tomto projektu je~implementováno pomocí drobného posunu hloubkové textury ve~všech směrech. Mezi posuny se~provede rozdíl s~originální hloubkou a~sloučením rozdílů získáme obrysy objektů.
\item Tužka a~papír - výstupní obraz nahradíme texturou ambient occlusion.
\end{itemize}

\subsection{Materiály a shadery}
Přestože materiály jsou omezené shadery, stále lze pomocí nich definovat mnoho různých a~komplexních grafických funkcí. Základem jsou jednoduché barevné výstupy s~triviálními parametry lesku, matnosti a~emise. Může záležet na druhu objektu, pro~který~materiály tvoříme, tedy~potřebujeme správně nastavit i~druh materiálu, čímž~následně dostaneme další, předtím uzavřené, výstupy a~vstupy. Například za~účelem optimalizace, můžeme přepnout materiál ze~základního režimu osvětlení neboli~Default~Lit do~neosvětleného režimu Unlit, čímž~budeme moci definovat barvu objektu pouze emisní složkou, ale~zmenšíme vykreslovací čas potřebný pro~materiál.

V~UE materiály resp.~shadery mají mnoho globálních proměnných, z~kterých můžeme získat cenné údaje o~enginu, scéně, vykreslovaném objektu, render buffrech atd. Dokonce můžeme definovat vlastní globální nebo~lokální parametry a~měnit jejich hodnoty v~logice světa. Použití takových proměnných lze často vidět v~již~zmíněných post-procesech, které~přebírají a~modifikují hodnoty výstupního zobrazení nebo~jsou animované pomocí sinusové funkce s~globálním parametrem herního času jako~vstup.

Stojí~za~to zmínit, že~některé materiály se~hodí pouze na~určitý druh objektů podle velikostí a~umístění ve~světě. Jedním z~příkladu v~této hře je materiál skla. Původně navržený shader, který~simuluje zalamování a~vnitřní objem, skvěle funguje na~drobných objektech jako lahve nebo~skleněné střepy. Při~použití na~velkých skleněných plochách jako~jsou~okna, takové simulace vytváří nežádané artefakty. Pro takové situace byl přidán duplicitní shader skla, který~primárně vykresluje poloprůhlednou barvu na~povrchu objektu.

\paragraph{Funkce} V~materiálech se~lze zbavit duplicitního kódu, čímž~se~zároveň zrychlí kompilace a~běh shader variací. Implementoval~jsem funkce:
\begin{itemize}
\item Škálování vstupné hodnoty podle vzdálenosti objektu od~kamery.
\item Uniformní škálování a~tiling textury nezávislé na~velikosti objektu.
\item Získání obrysů objektů v~podobě masky.
\item Rotace objektu ve~směru kamery.
\end{itemize}

\subsection{UI}
Před~Unreal~Engine~5 téměř každé~UI byl rastrový a~v~minulosti to~ani~nebyl problém. Stačilo vytvořit mip-mapy pro~menší množinu nejrozšířenějších rozlišení (HD, WSXGA a~Full~HD) a~k~tomu škálovat mip~texturu menšího rozlišení na~potřebný lehce větší výstup. Předtím hry nevypadaly zaostřeně takže nemuselo ani~UI a~dokonce to~rozostření rastrového obrazu nebylo tak~viditelné na~displejích menší velikosti v~té~době. Dnes rastrové~UI vytváří příliš komplikací při~tvorbě a~vykreslování. Je potřeba mnoho mip-map ve~velkých rozlišeních pro~ostrý obraz na~každém displeji, což~vyžadují velké množství paměti a~hlavně velkou propustnost při~čtení dat, což~se~nejvíc projevuje u~rastrových animací.

Jelikož původní projekt vznikal ve~čtvrté verzi enginu, ale~v~době již~velkých rozlišení, nebylo realistické pro~dva vývojáře vypracovat přijatelné rastrové~UI. Proto jsem tehdy a~teď vytvořil všechny prvky pomocí černobílých poloprůhledných vektorových čtverců s~transformacemi. Rastrové textury se~používají pouze v~podobě masek nebo gradientů, při~použití~kterých nejsou zřejmé škalovací artefakty.

Všechny kořenové UI~prvky (overlay, kontejner questů, kontejner nápověd ovládání, menu~atd.) spravuje mnou implementována třída Widget~Manager. Tato~třída slouží nejen jako~high-level~API pro~všechny kořenové prvky resp.~kontejnery, ale~primárně přehledně udržuje reference na~takové prvky. Bez~manuálního udržování reference, po~instancování libovolného UI~prvku ho~již~nelze získat a~tedy nemůžeme prvek ani~odstranit z~obrazovky.

Každý prvek se~instancuje na~začátku a~udržuje~se v~paměti po~celou dobu. Důvodem stálého udržování prvků v~paměti je jejich naplňování daty, které~občas může trvat déle a~tak při~dynamickém instancování vyvolávat zaseknutí aplikace.

\paragraph{Texty a překlady} V~enginu je více druhů řetězců:
\begin{itemize}
\item FString - běžný řetězec pro~reprezentaci UTF-16 se~stejnou množinou funkcí jako~u~std::string. Je optimalizovaný pro~konkatenace.
\item FName - pouhý ukazatel na~tabulku triviálních unikátních bajtových řetězců. Používá~se pro~pojmenování konstant v~kódu nebo~tagování objektů a~je~to doporučený textový formát pro~přenos přes internet.
\item FText - komplexní řetězec schopný překládat obsah podle tabulky nebo~formátovat čísla podle pravidel jazyka.
\end{itemize}
Engine při~instancování určitého FText nebo~FString se~snaží najít již~existující instanci v~paměti, čímž~se~výrazně redukuje duplicita dat zejména v~blueprintech.

Při~tvorbě projektu jsem~si~dal záležet, aby~veškerý text viditelný hráčem byl překladatelný. Zároveň jsem dbal na~zachování unikátností řetězců, aby~se~v~tabulce překladů nevyskytovaly duplicitní záznamy.

\paragraph{Načítací obrazovka} Načítací obrazovka je povinná z~důvodů licenčních podmínek některých knihoven a~programů. Zejména Unreal~Engine a~FMOD vyžadují, aby~produkt obsahoval načítací obrazovku s~logem jejich softwaru. Tato~zdánlivě triviální problematika ve~skutečnosti zahrnuje netriviální množství časové investice a~rozboru startovací sekvence enginu, což~vyúsťuje v~nekompetentní řešení začínajících i~pokročilých vývojářů. Přesně se~jedná~o:
\begin{itemize}
\item úplné vynechání celé funkcionality a~tedy porušování licenčních podmínek, 
\item nebo~simulaci načítaní~tak, že~po již plném načtení enginu se~otevře speciální scéna obsahující pouze UI s~animaci načítání s~předem definovanou délkou zobrazování.
\end{itemize}
Ve~své práci pro~mě bylo zásadní vytvářet věci technicky správně a~tedy vyhýbat~se programátorským workaroundům nebo~technickému ,,lhaní'' hráči. Proto~jsem~si~dal záležet i~na~správném provedení načítací obrazovky.

Postup tvorby načítací obrazovky vývojáři enginu nedokumentují a~běžně dostupné návody třetích stran jsou již zmíněné nekvalitní simulace. Dokázal jsem najít pár funkčních ukázek u~kolegů z~Číny, které~mi~umožnily se~zorientovat v~základech a~následně provést reverse engineering celé problematiky. K~mému překvapení jedná~se o~důkladně propracovaný systém, který~je podrobně přizpůsoben specifikům různých platforem.

Engine při~načítaní nepodporuje UI vytvořený v~blueprintech, jelikož blueprinty jsou assety s~hlubokou reflexí, kterou~engine již~načítá (po~načtení již~lze zobrazit blueprint načítací obrazovky mezi úrovněmi). Proto~jsem~musel vytvořit navíc UI~v~nízkoúrovňovém Slate.

\section{Audio}
\label{sec:audio}
V~tomto projektu jsem~se~zaměřil primárně na~zprovoznění všech technologií potřebných k~dokončení uceleného produktu a~proto~je ve~hře značný nedostatek audia. Přesto je připravené široké technické zázemí, které~obsahuje drobné ukázky:
\begin{itemize}
\item nastavení a~ukládání hlasitostí různých kategorií audia,
\item prostorové přehrávání,
\item dynamický hudební doprovod
\item a~možnost dabování dialogů spolu s~hotovým procesem generování hlasů.
\end{itemize}

\newpage
Optimalizace audia nebyla mezi cíle této práce, avšak~základní systematická pravidla byla určena.
\begin{itemize}
\item Použít streaming a~kompresi dat kdekoliv to~bude možné,
\item hudební doprovod je~ve~formátu~MP3,
\item hlasy a~jiné zvuky jsou~ve~formátu~WAV.
\end{itemize}
V~budoucnu by~také pomohlo zabalit všechny hlasy a~jiné audio do~samostatných datových balíčků neboli~chunků. Aktuálně všechny herní assety jsou automaticky zabalené do~pár ucelených balíčků, což~může vyvolat sice drobné zpomalení načtení assetů, ale~stále kriticky ovlivnit audio zážitek.

\subsection{Dynamický hudební doprovod}
Když~mluvíme o~dynamickém doprovodu ve~hrách, často myslíme právě~dynamické přepínání částí skladby v~závislosti na~proměnných světa. Pří~vývoji jsem se~uchýlil k~použití zvukového enginu~FMOD (viz~\Cref{prg:fmod}) a~hudbu jsem skládal sám bez~použití samplů, tedy~pomocí~VST (Virtual~Studio~Technology) hudebních nástrojů. Častí hotových kompozic za~účelem dynamiky by~měly~být nerušivě zacyklené, na~což~jsem kladl největší důraz. Bohužel kvůli~omezenému času jsem~nemohl věnovat dostatečnou pozornost rozmanitosti a~komplexitě hudebních kompozic. Prototypy dynamického doprovodu lze již~zaslechnout v~průběhu třetí úrovně.

\subsection{Dabing dialogů}
Jelikož hra by~měla poskytnout prostor pro~AI generovaný obsah, dialogy jsou již~nadabované pomocí~AI. Původně jsem začínal s~python knihovnou Coque~TTS\footnote{https://github.com/coqui-ai/TTS}, ale~dosáhnout v~ní aspoň dobrých výsledků bylo náročné. Proto~jsem~přešel na~knihovnu a~model Zonos\footnote{https://github.com/Zyphra/Zonos}, který~již v~základu poskytuje vynikající výsledky a~navíc má~prostředky pro~udržování kontextu nebo~parametry zabarvení hlasu.

V~modulu VoiceGenerator v~repozitáři hry je~k~dispozici skript pro~jednoduchou instalaci prostředí. Z~časových důvodů jsem~nestihl vytvořit skript, který~by jednoduše generoval množiny resp.~sekvence dialogů přímo z~jednoho textového souboru. Aktuálně je~potřeba ručně generovat každou větu jednotlivě přes~webové rozhraní, které~je~součástí knihovny.

Ukázkové dialogy lze již~zaslechnout v~průběhu třetí úrovně. Původně jsem~taky~plánoval vytvořit robotický hlas ve~třetí úrovni pomocí modifikace základního hlasu v~novém pro~UE5 zvukovém systému MetaSound. Ten~dokáže komplexně modifikovat zvukový signál za~běhu, ale~na~začlenění takové technologie do~hry nezbýval čas. 

\newpage
\section{Co se~nestihlo nebo~změnilo}
Přestože do~práce jsem~vložil mnoho času a~úsilí, nepodařilo se~mi splnit všechny mnou stanovené cíle. Místo herního dema, práce představuje spíš demo technické, neboli~jsem~úspěšně vytvořil technické zázemí, ale~nestihl naplnít hru obsahem. Třetí úroveň nějakým obsahem disponuje a~dohromady lze tuto úroveň považovat za~hru. Jinak~všechny úrovně resp.~celá hra trpí nedostatkem nebo~neobsahuje vůbec:
\begin{itemize}
\item Grafické prvky jako~animace postav, efekty, 3D modely.
\item Zvukové prvky jako~hudební doprovod, zvuky~interakce se~světem a~UI.
\item Příběhové dialogy, cutscény a~dokončený level design.
\item Balancování herních mechanik a~doladění ovládání.
\end{itemize}
Nepodařilo~se~mi vytvořit poslední pátou úroveň z~časových důvodů. Zároveň jsem~se~rozhodl změnit žánr této úrovně z~first-person shooter na~top-down shooter. Důvodem změny posloužila analýza náročnosti tvorby obsahu pro~takový žánr. Přestože~first-person shooter se~může zdát jako~jednoduchý koncept, ve~skutečnosti pro~hezký herní zážitek je~potřeba vložit mnoho úsilí a~času. Pro~tento~žánr je~nutné pečlivě odladit všechny prvky hry a~hlavně animace, které~jsou má slabá stránka. Na~druhou stranu top-down shooter neklade tak~vysoké nároky a~dokonce umožňuje skrytí od~hráče nedostačující animace.
\subsection{Obsah mimo hru}
Projekt není~tvořen pouze technickým demem hry, ale~také zahrnuje nasazení a~údržbu sítě s~veřejnou ip~adresou, webového a~git serveru. Postupy nasazení a~údržby z~důvodu zaměření práce nejsou zveřejněny.
