Aktuality  |  Články  |  Recenze
Doporučení  |  Diskuze
Grafické karty a hry  |  Procesory
Storage a RAM
Monitory  |  Ostatní
Akumulátory, EV
Robotika, AI
Průzkum vesmíru
Digimanie  |  TV Freak  |  Svět mobilně

Grafické enginy her a reálný svět

23.2.2012, Pavel Kovač, článek
Grafické enginy her a reálný svět
V tomto článku se podíváme na enginy moderních her, porovnáme si je s reálným světem a se softwarovými rendery. Doba pokročila a dnešní hry již vypadají velice reálně. Čím se tedy liší od reálného světa a moderních rendering systémů? Doplněno o 4 kapitoly.

Ambient Occlusion


Tento efekt se v dnešních hrách zatím prakticky nepoužívá, jsou zde sice výjimky, ale je jich jak šafránu. Takovým tahounem Ambient Occlusion (dále jen AO) je CryEngine 2, který jej prezentuje jako Realtime Ambient Maps. Tento efekt se dříve počítal jako statický jev pomocí globálního osvětlení (dílčí efekt globálního osvětlení). V podstatě šlo o předpočítaný efekt namapovaný jako další textura na objektech. V době dynamické simulace, ragdoll apod. se však už s touto statickou interpretací nespokojíme a je třeba přejít k něčemu více sofistikovanému. A co tento efekt tedy vytváří? Jde o ovlivňování jednotlivých objektů navzájem.

Jednoduchý příklad: Vemte si bílý papír a k němu přibližte nějakou tmavou krabičku. Nevšímejte si stínů vrhaných žárovkou, sluncem apod. Soustřeďte se pouze na hodně rozmazaný "stín" (tmavší místo) pod krabičkou. A právě to je onen efekt ve hrách a 3D programech zvaný jako Ambient Occlusion.




Princip Ambient Occlusion (AO)


Na předchozím obrázku vidíte základní princip AO zjednodušený do 2D. Na objektu se určí několik bodů (v herních enginech jich není moc, ale u SW renderu je to prakticky každý viditelný bod) a z těchto bodů se vyšlou paprsky do okolí. Počet paprsků je samozřejmě konečný a obvykle dost malý (u SW renderů např 64, u herních enginů 1, 2, max kolem 8). Tyto paprsky mají omezenou životnost (na obrázku označeno jako "Hranice Ambient Occlusion"). Pokud paprsek narazí do nějakého objektu, zjistí jeho barvu a zpětně ovlivní sledovaný bod.

V závislosti na počtu paprsků, které narazí na nějaký objekt, je sledovaný bod tmavší nebo světlejší (tmavší s větším počtem objektů). Takto se zjistí několik bodů na objektu a pomocí některé z filtrací se vyhladí konečný výsledek. Bohužel tato metoda je velmi výpočetně náročná, a proto se z větší části dodnes používala předpočítaná scéna. Výkonné grafické karty však již AO relativně zvládají, a tak se můžeme kochat velmi realistickým nasvícením scény i při pohybujících se objektech, či animaci jednoho objektu (postava).




Scéna bez Ambient Occlusion




Ta samá scéna s Ambient Occlusion


Všimněte si, co takový na pohled nicneříkající efekt AO udělá se scénou. První obrázek nemá prakticky žádnou hloubku a jen těžko se orientujete v prostoru. Schválně jsem nechal vypnuté stíny, aby se efekt AO více zvýraznil. Všimněte si, co udělal kvádr s logem Svět hardware na levé stěně. Je zde tmavší místo. Také rohy výklenku jsou lehce tmavší, a tím vytváří lepší prostorový dojem. V 3D programech se softwarovým renderingem se AO používá jako dílčí efekt globálního osvětlení, a dotváří tak pouze scénu. V těchto programech se AO používá pouze na velmi jemné doladění scény a k dosvětlení malých detailů s rozměry řádově v mm. Pro dosvětlení stěn se používá Global Illumination (emise fotonů), u menších objektů Final Gather. Vysvětlení těchto pojmů je ovšem nad rámec tohoto článku (jsou to softwarové metody a dnes se zabýváme HW renderingem ve hrách).

A jak je na tom reálný svět? Stále ještě hodně jinak. V reálu je každé světlo zdrojem ohromného počtu fotonů, které si letí světem, odrážejí se, získávají různou barvu z objektů, na které narazily, a v podstatě mají nekonečnou životnost a stále se odrážejí. Tím vznikají ony tmavší rohy, jemné stíny apod. Ve hrách se vysílá jen pár "fotonů" (rozuměj paprsků), které se neodrážejí a mají opravdu malou životnost. Softwarové rendery sice ve své podstatě využívají stejný princip jako reálný svět (zdroj světla je současně i zdrojem fotonů), ale počet fotonů na jedno světlo je hodně omezen (např. pouze 2 000 000) a jejich počet odrazů opět omezen tak do 10. Tato metoda se nazývá Global Illumination a je podpořena již zmiňovaným FinalGather a AO. Stále je tedy oproti reálu hodně co dohánět.

Následuje ukázka, jaké jsou rozdíly v jednotlivých renderech.




Scéna bez globálního osvětlení a AO




Scéna vypočítaná s FinalGather




Scéna spočítaná s FinalGather + AO


Zaměřte se na jednotlivé rohy u objektů a na místa, kde se objekty sebe dotýkají. Při použití klasického renderu bez globálního osvětlení, které se používalo dodnes ve hrách, vypadá dost prapodivně. Aby nevypadala scéna takto hrůzostrašně, tak se textury preventivně "kreslily" s lehce ztmavenými rohy, aby se vytvářel dojem tmavých rohů ve scénách. Problém však nastal, pokud se měly objekty pohybovat. Druhý obrázek znázorňuje situaci, kdy je scéna vypočítána pomocí FinalGather (jedna z částí Global Illumination). Na první pohled zde není nic špatně, ale obrázek stále nepůsobí dobrým dojmem. Až AO dodá tu správnou hloubku a realističnost výslednému obrazu. Nejvíce je to vidět na kleci v místě dotyku s podlahou. A proč zde uvádím softwarový render, když se bavíme o herních enginech? Je to jednoduché, naprosto stejně totiž pracuje i dnešní herní engine, pouze si zavádí určitá zjednodušení (u AO menší počet paprsků apod.).

O Global Illumination by se dalo povídat ještě hodně dlouho, ale už bychom zabrousili někam, co je i pro dnešní hry zcela tabu, a tak toho raději necháme. Každopádně si pojem Global Illumination resp. Ambient Occlusion velice dobře zapamatujte, protože v budoucnu se s ním budeme u her setkávat čím dál tím častěji.


Stíny


Trochu si oddychneme od nových technologií a podíváme se na jednoduchou část o stínech, která je na první pohled jednoduchá. Stíny v reálném světe vznikají tak, že foton emitovaný ze slunce/žárovky narazí na objekt a od něj se odrazí, zkrátka neprojde za onen objekt. A proč není za objektem zcela tma, i když na něj svítíme např pouze jednou žárovkou (temná komora)? Opět se musím vrátit k problematice globálního osvětlení. Ony fotony se totiž odrážejí a odrážejí až si najdou cestu i za daný objekt, sice s nižší intenzitou a dostane se jich tam méně, ale zkrátka dostanou se. Proto je za objektem, který vrhá stín, stále trochu světla.

Jistě jste si všimli, že stín má ještě jednu zásadní vlastnost - nikdy není ostrý a vždy vytváří v menší či větší míře rozostřený okraj. Pokud osvětlíme objekt slunečním svitem, tak jej osvicujeme v podstatě rovnoběžnými paprsky (zjednodušeně). Přesto se však vytváří rozostřený stín, čím je to způsobeno? Ten, kdo někdy něco slyšel o vlnové povaze světla, jistě slyšel i o difrakci světla, která tento jev způsobuje. Vysvětlování principu difrakce si odpustíme a spokojíme se s tím, že stín není plynule rozostřen, ale závisí na vlnové délce a při ideálních podmínkách bychom sledovali na okraji stínu jisté proužkování vypadající nějak takto:





Takto samozřejmě ve hrách a ani při softwarovém renderingu stíny vytvářet nelze. Nechat počítat světlo jako elektromagnetické vlnění by stále pro počítač bylo příliš náročné a asi se toho jen tak v brzké době nedočkáme. Proto se zavedlo na první pohled výrazné zjednodušení, ale ve skutečnosti to vlastně docela dobře simuluje tyto jevy. Opět trochu odbočím k přírodě, kde vznikají měkké stíny ještě jiným způsobem.

Mějme kruhový zdroj světla s nějakým poloměrem. Toto světlo svítí na nějaký objekt, ten vrhá stín. Na hranu objektu dopadá světlo z více míst (z celé plochy onoho kruhu). Rozdělme si pro jednoduchost kruh na konečný počet malých částí. Každou tuto část berme jako bodový zdroj světla. No a teď si uvědomme, že každé toto světlo vrhá stín, každý stín je však vytvářen v jiném místě (světlo je vůči druhému v jiné poloze). Takto se nám vytvoří opět konečný počet stínů. Pokud si stíny dáme hodně průhledné (1= zcela neprůhledný stín, tak intenzita je 1/počet_světel), tak nám vytvoří onen krásně rozostřený stín.




Stín vržený 100 bodovými světly


Všimněte si, jak se stín s různou vzdáleností od objektu různě rozmazává. Stín nejblíže objektu je téměř dokonale ostrý, naproti tomu stín vzdálený od objektu více již má znatelně rozmazaný okraj. Rozmazaný okraj je díky počtu bodových světel (100) celkem hezký, avšak můžete při podrobném zkoumání nalézt jakési proužkování. Takto lze simulovat měkké stíny v renderech (dnešní rendery samozřejmě toto umějí i samy tím, že zadáte velikost světla a počet vzorků a o ostatní se již render postará, tedy nemusíte světla ručně vytvářet), u her však nelze použít 100 vzorků na jedno světlo, aniž by nespadl framerate do pekel. Proto se používají různé triky, jak toto obejít. Buď se stíny rozmažou nějak neutrálně po celé ploše (toto používá Half-Life 2 Episode 2), nebo se vrhnou např. čtyři stíny a mezi nimi se interpoluje. Druhá metoda je samozřejmě daleko náročnější na výpočetní výkon, a tak lze obvykle tuto volbu vypnout a ponechat pouze ostré stíny ala Doom 3.

Vznik stínů je kapitola sama o sobě. Existují dvě základní metody, jak vytvořit stín. První se nazývá ShadowMap, kdy je předvytvořen stín tím, že se vyrenderuje scéna z pohledu světla (jsou využity různá zjednodušení apod.) a všechny objekty, které vrhají stín, vyrenderují stín do textury, která se posléze namapuje na objekt, který stín přijímá. Je to velice jednoduchá metoda, kdy nepotřebujeme nějaké speciální úpravy scény. Nepřidáváme polygony do scény a vše se zvládne ve dvou průchodech. Tento způsob stínů využívá řada her (např. Half-Life 2), protože je výpočetně nenáročný. Má jednu velkou výhodu v tom, že na texturu stínu lze aplikovat kdejaké filtry a okraje stínů tak pěkně rozmazat.

Za pomocí ShadowMap se obvykle nevytváří reálně rozmazaný stín vzhledem k velikosti světla z jednoho prostého důvodu. Pokud by se renderoval stín vícekrát, tak by neúměrně zaplňoval paměť grafické karty a zkrátka by nezbylo tolik místa pro textury jako takové. Některé softwarové rendery využívají stejný způsob vrhání stínů, avšak dnes se daleko více využívá metoda sledování paprsku.




Stín při použití metody ShadowMap


Všimněte si nedokonalosti okraje stínu. Je zde použita shadowmap o velikosti 128x128 px a tím se výrazně snižuje přesnost vrhaného stínu. Okraje jsou roztřepené a nepřesné. Na následujícím obrázku je ještě vidět problém s "patou" stínu, tedy místo, kde se stín dotýká objektu, který ho vrhá.




Problém vzniklý u paty stínu při použití ShadowMap


Druhý způsob vytváření stínů je tzv. StencilShadow, který jistě velice dobře znáte ze hry Doom 3. Ta využívala tuto metodu na plné čáře a spoléhala se na ni. Jak vznikají stíny u Stencil metody? Od světla jsou vytvořeny polygony, které leží na hranách objektu, jenž vrhá stíny. Tento polygon vlastně simuluje paprsek světla, který je na hraně objektu a protože je hrana vždy lomená čára (objekt složen z polygonů), tak lze nahradit paprsek polygonem. Zkrátka a jednoduše, taková lehce zjednodušená a celkem fikaně promyšlená metoda sledování paprsku. Tyto vržené polygony uzavírají hranici, která má přesný tvar stínu daného objektu. Pak již stačí vyplnit tuto oblast a získáme pěkný ostrý stín. Protože ve scéně vytváříme další polygony, tak znatelně zatěžujeme VerteShader, a tak si je třeba dávat velký pozor na to, kolik objektů zrovna vrhá stín a z kolika světel. Každé světlo totiž musí vrhnout svůj vlastní stín pro každý objekt zvlášť a to už je nějakých polygonů navíc oproti tomu, co ve skutečnosti vidíme.




Stencil Shadow


U těchto stínů není problém renderovat reálné rozmazání pomocí drobného posunutí světla a vytvoření např. šesti překrývajících se stínů. Samozřejmě opět je to velice náročné na výpočet, protože se musejí stíny spočítat několikrát, ale už to nezabírá tolik paměti jako u ShadowMap.

Doteď jsme se bavili o dynamických stínech, které se sice v dnešní době používají v největší míře, ale jsou zde i statické stíny předrenderované a namapované přes textury (toto stále využívá v určité míře i Half-Life 2). Jde v podstatě o klasické ShadowMap stíny, pouze jsou spočítány předem (jsou dodány jako textura ve hře), a tak nikterak nezatěžují grafickou kartu. Aby se však udržela hra s velikostí na rozumné míře, jsou stíny vždy dost zubaté a dohání se to výrazným rozmazáním okrajů. Proto se používají tyto stíny pouze pro velké objekty jako jsou budovy a terén. Brzy však budou vytlačeny tyto stíny kompletně a už se s nimi v moderních hrách jen těžko setkáte.