reklama
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.

Reflection a Refraction (odrazy a průsvity)


Nejprve se podíváme na to jednodušší a tím je samozřejmě efekt odrazu. Z praktického hlediska lze čistý odraz vypočítat metodou sledování paprsku velmi jednoduše. Stačí od pozorovatele poslat paprsek, který náleží jednomu pixelu ve výsledném obrazu a nechat jej na lesklém povrchu odrazit s využitím zákona odrazu, který známe z fyziky základní školy, kdy úhel dopadu se rovná úhlu odrazu. To v dnešní době není až tak náročný výpočet, avšak pro dnešní grafické karty to je stále příliš náročné, aniž by spadl framerate do pekel. Proto se výpočet provádí obvykle velmi jednoduchým trikem.

Použije se hybridní raytracing, kdy se v případě rovinné plochy vyšle pouze jeden paprsek a zjistí se, jakým směrem se má odraz "koukat". Do tohoto směru se upraví kamera a vyrenderuje se scéna. Tato mapa se následně aplikuje jako odrazivá mapa na celý objekt. Tím je odraz hotový. Samozřejmě existují objekty, které odráží pod určitým úhlem jinak než pod jiným úhlem. Zkrátka pokud se koukáte například kolmo, objekt není odrazivý vůbec (např. taková voda) a při téměř tečném pohledu se odráží 100 %. Na takovéto objekty se může aplikovat pixelshader kód, který pouze zjišťuje, pod jakým úhlem dopadá sledovaný paprsek a podle toho se upraví intenzita odrazivé mapy.

Pokud se ještě aplikuje na objekt, co má mít odrazy například Parallax Occlusion Mapping, tak se situace dost zesložiťuje, protože je třeba počítat i s odrazy objektu sama na sebe (anglický název to vystihuje daleko lépe: "self reflection"). V tomto případě se např. taková vodní hladina tesselluje (zjemní se síť) a spočítá se několik odrazivých map pro různé úhly odrazu. To samozřejmě prodlužuje dobu renderingu, a tak se tomu chtějí vývojáři her za každou cenu vyhnout. V některých hrách si můžete všimnout, že voda sem tam na svém povrchu vytvoří černé místo. To je způsobeno právě tím, že se nezapočítávají self reflection a vlastně pixel shader při použití Parrallax Occlusion Mappingu neví, co má zobrazit, a tak přiřadí neutrální černou (to je samozřejmě schválně naprogramováno). Obvykle to výrazně urychlí rendering a na výsledku to není až tak moc znát. Existuje více způsobů, jak vytvořit odraz, ale tento je jedním z nejjednodušších a často se používá v nejedné hře.




Odrazy od vody ve hře Half-Life 2


Nyní se dostáváme k tomu složitějšímu. Tím je průsvit (refraction). Samotný princip průsvitu resp. průhledu skrz průhledný objekt je stejný jako při odrazu. Vyšle se paprsek z kamery, který se po dopadu zlomí podle indexu lomu a to samé se stane při opuštění objektu. Nic víc nic míň. Zní to jednoduše, ale počítat v rozumném rozlišení a FPS raytracing zkrátka nelze. Proto se přistupuje například ke snižování rozlišení pro průhledné materiály (např. na 1/4) a poté je obraz interpolován. Pak zde existují různé další optimalizace, které například počítají průchod paprsků jen pro každý polygon a mezi těmito lomy se interpoluje. Je to velmi účinná metoda, jak vytvořit rychle a bezbolestně kvalitní lom světla například ve skleničce. Ve hrách se však často používá ještě razantnější zjednodušení, které je dané pixelshaderem.

Například taková lupa není matematicky nic složitého a v podstatě jde pouze o jednu rovnici. Inu vše záleží na programátorech, jak si s daným problémem poradí. V budoucnu se nejspíš začne prosazovat klasický reytracing aplikovaný pouze na objekty, které to vyžadují. Nedávno šéf NVIDIE prohlásil, že raytracing není správnou cestou pro hry. Osobně si však myslím, že se tomu nevyhneme, protože zkrátka klasický rendering u dnešních her neumožňuje leckteré efekty, co jsou běžně používány u softwarových renderingů. NVIDIA nejspíše tuší, že by šlo o zcela odlišný přístup ke grafickým kartám a musela by se změnit od základu architektura. No uvidíme, věštec nejsem, křišťálovou kouli taky nemám a síla marketingu je nevyzpytatelná.

Každopádně osobně dávám raytracingu ve hrách velkou budoucnost. Dnešní softwarové rendery již raytracing zvládají velice dobře a začínají se objevovat i fyzikální rendery, které počítají světlo jako elektromagnetické vlnění. Zkrátka softwarový render se postupně povyšuje o jednu úroveň výše, tak proč by nemohl HW rendering ve hrách také o jeden stupínek výše?


Rendering vody


Rendering vody je kapitola sama o sobě. Samotná voda se zdá z fyzikálního hlediska velmi jednoduchá. Průhledná z nějakých 85 % (čirá voda), odrazivá podle indexu lomu (BRDF odraz - tedy ten typ odrazu, co přesně známe ze základní školy, kdy úhel odrazu se rovná úhlu dopadu). Index lomu vody je 1,33 a tím v podstatě popis vody z fyzikálního hlediska končí. Samozřejmě voda má nějakou barvu, ale to je celkem vedlejší. Pro počítač je však velmi velký problém toto všechno věrně nasimulovat. Voda totiž ve většině případů není rovná plocha, ale jsou na ní vlnky apod. Jen tyto vlnky jsou obrovským problémem, protože vytváří spoustu efektů, které jsou pro grafickou kartu v reálném čase zkrátka nespočitatelné.

Vezměme si jen takové přesné odrazy, které by se musely počítat pro každý pixel zvlášť, což v dnešní době sice již lehce v úvahu připadá, ale stále se aplikují různá zjednodušení, aby zbyl nějaký výkon pro ostatní scénu a FPS nekleslo do pekel. Vzpomeňme například na "optimalizaci" beta driverů ForceWare od NVIDIE, které vykreslovaly odraz vody každý čtvrtý snímek. Tím výrazně ulehčily grafické kartě ve výpočtu a FPS dost znatelným způsobem vzrostlo nahoru. Výsledný dojem byl skoro stejný a jen "něco" na pohled vadilo. Nevěděli jste, co je tam špatně, ale něco špatně tam bylo. A právě tyto nedokonalosti jsou velmi zásadní pro výsledný dojem z vody.

To jsou však pouze efekty odrazů. Samotný odraz není až tak výpočetně náročný, ale takový prostup světla je jiný oříšek. Samotný lom paprsku pohledu není až takový problém, ve své podstatě jde o stejný princip jako při odrazu. Zkrátka se paprsek zlomí pod určitým úhlem daným indexem lomu a efekt je na světě. Opět se zde aplikují různá zjednodušení (vzpomeňte například na Half-Life 2, kde lupa sice zvětšovala, ale obraz byl renderován s cca 1/4 rozlišením, které se interpolovalo) a tím ulehčuje grafické kartě.

Pokud bychom nechali vyrenderovat vodu s těmito parametry, tak stále nedosáhneme věrného výsledku. Ptáte se proč? Odpověď je jednoduchá, stále tu jsou efekty, které je třeba spočítat. Prvním a velmi důležitým je efekt "hlubiny". I když se zdá voda prakticky čirá, tak se zvětšující se hloubkou resp. masou vody se zabarvuje obvykle do hodně tmavě modré barvy. Proto je třeba tento efekt zohlednit. Pokud si zjednodušíme vodu na rovnou plochu (hojně užívanou při renderingu oceánů atd.), musí pixel shader počítat, jak je vzdálený "ponořený" objekt a s ohledem na tuto vzdálenost zabarvit i výsledný pixel. Stupeň zabarvení není obvykle lineární, ale spíše logaritmický. Logaritmický útlum má tu výhodu, že se zbavíme ostrých přechodů a hlavně hladina bude vypadat na povrchu opravdu zcela průhledná a až s velkou hloubkou se výrazně zabarví. Vše ale záleží na programátorech, jak si s tímto jevem poradí. Chce to jistou dávku zkušeností (3D grafici mě dají jistě za pravdu, že vodu v 3ds Max na poprvé málokdy vytvoříte reálnou).


Kaustika


Ani tím však rendering vody nekončí. Velmi důležitou součástí vody je efekt kaustiky (caustic), který vytváří na dně mihotavé shluky světelných paprsků. Efekt kaustiky se pokusím vysvětlit na jednom jednoduchém případě. Pokud jste si někdy hráli s lupou a např. pálili mravence, tak jste sice gauneři, ale aspoň nyní víte, co taková kaustika dokáže. Pokud si případ zjednodušíme do 2D prostoru, tak je pochopení velmi jednoduché.

Paprsek světla (foton) dopadne na čočku lupy a podle indexu lomu se zlomí. Poté putuje sklem, aniž by se ohýbal apod. až do chvíle, kdy vystupuje ze skla. Opět se zlomí a pokračuje pod nějakým úhlem dál světem. Záleží pak pouze na tom, pod jakým úhlem vyletí ven. Pokud směřuje paprsek k ose lupy, tak se vytvoří v nějaké vzdálenosti ohnisko. V tomto ohnisku se setkají všechny paprsky od slunce, které byly při vstupu na povrch lupy rovnoběžné a vytvoří velmi intenzivní světelný bod, resp. malé kruhové místo. Více je vidět na následujícím obrázku.




Princip kaustiky


U vody to funguje v podstatě stejně. Pouze se paprsek zlomí pouze jednou a díky tvaru vlnek se na dně vytvoří ony mihotavé světelné efekty. Konvenční softwarový render efekt kaustiky počítá tak, že každý zdroj světla vyemituje řádově několik jednotek až desítek miliónů fotonů, které mají velikost řádově do milimetru, reálný foton je samozřejmě daleko menší, ale taky jich každý zdroj světla emituje daleko více. Musí zde platit jakási nepřímá úměra mezi velikostí a počtem fotonů. Výpočetně je však tento efekt velmi náročný a pro hry naprosto nepoužitelný. Zkrátka pokud jeden statický obrázek, kde je např. bazén, počítá dvoujádrový procesor řádově několik desítek minut jen pro kaustiku, tak těžko dokáže grafická karta spočítat animaci vodní hladiny oceánu s FPS 30 a více.

Naštěstí kaustika je již velmi složitý efekt a lidský mozek jen tak nedokáže odhadnout, jak bude ve výsledku vypadat. Jednoduché objekty jako je koule, kvádr či prstýnek zkrátka již v oku leckdo má, ale složitá vodní hladina je nevyzpytatelná. To nahrává do karet optimalizacím a v tomto případě velmi razantním. Kaustika jako taková totiž není vůbec počítána a použije se pouze jednobarevná animovaná textura, která se aplikuje jako další vrstva na dno. Je to zkrátka takové neutrální mihotání, které si vytvoří grafici. Ve výsledku je tedy efekt kaustiky u vodní hladiny tím nejjednodušším pro výpočet. A jakou parádu to udělá, že?




Ukázka softwarově renderované kaustiky




Kaustika v DX10 verzi Crysis (simulace)


Pobřeží


Posledním a neméně důležitým efektem se stávají vlnky a pěna u pobřeží. Samotný styk vodní hladiny a pobřeží je velmi ošemetná záležitost. V reálném světě se voda tříští o skály, rozvíří písek a různě pění. Nasimulovat tento jev například pomocí částicových systémů by jistě šlo, ale nedokážu si představit ten výpočetní výkon, který by byl zapotřebí pro spočítání několika miliónů částic a pro jejich vzájemnou dynamiku. Zkrátka nepřípustná situace.

Ve hrách je navíc obvykle voda reprezentována jako rovinná deska, na které jsou aplikované pixel shader kódy, aby se vytvořil dojem vlnek. Při styku s pobřežím však obvykle narazíme na problém, že je voda velmi ostře ohraničena a narážíme na často jednoduchý polygonální model pobřeží. Tyto nedostatky je třeba velmi obratně skrýt, nebo to dopadne jako v Half-Life 2, kde voda měla nějaké neutrální vlnky a u pobřeží si nikdo s nějakou pěnou hlavu nelámal. Výsledek nebyl zrovna moc ideální.




Ostré hrany vody v Half Life 2


Naopak hra Crysis resp. FarCry tento nepříjemný jev zamaskovala pod velmi pěknou pěnu u pobřeží. V enginu se detekuje styk vodní hladiny s dalšími objekty a v místě styku se aplikuje na vodní hladinu další textura a jiné pixel shader kódy. Nic víc nic míň. Jde opět pouze o další animovanou texturu na vodu a částečně i na pobřeží, dále pak jde o velmi kraťoučký pixel shader kód. Ve výsledku voda vypadá daleko přirozeněji a jsou skryty nepříjemné hrany. Samozřejmě všechny tyto efekty zatěžují jak jádro, tak paměť grafické karty. Přibyde dost velký počet textur a navíc jsou animované. Proto je obvykle ona pěna taková neutrální po celém pobřeží, aby se mohla aplikovat menší opakující se textura.




Zpěněný okraj vody v Crysis (eliminace ostrých okrajů)


Disperze světla


Posledním efektem, co se ve hrách zatím prakticky moc nevyskytuje, je disperze světla. Jde o výpočetně velmi náročnou operaci, kdy dochází k rozkladu jednotlivých složek světla. Čistě bílé světlo se skládá ze všech barev, které jsou smíchány dohromady. Pokud však dopadne takovýto paprsek pod úhlem na např. jehlan, tak vlivem rozdílné vlnové délky se každá barevná složka zlomí podle indexu lomu lehce jinak. Poté z tohoto jehlanu vystoupí opět pod jiným úhlem a ve výsledku vytvoří světelnou duhu. Asi nejlépe to vysvětluje následující obrázek.




Render disperze přes fyzikální render Maxwell


Výpočet takovéhoto obrázku však i dnes na dvou/čtyřjádrových počítačích trvá řádově několik dní (do rozumného rozlišení), a tak se nelze divit, že se disperze ve hrách jen tak neobjevuje. Pokud by se ve hře tento jev objevil, tak vězte, že jde čistě o simulaci pomocí nějaké neutrální textury duhy. Dokonce většina konvenčních softwarových renderů, co nabízí disperzi, ji počítá pouze velmi zjednodušeně a pouze fyzikální rendery, jako je Maxwell, FryRender a jemu podobní, si disperzi počítají opravdu přesně, čas renderu tomu také odpovídá. Disperzi zde nebudu dále popisovat, protože se ve hrách nevyskytuje, a tak jsme již překročili rámec tohoto článku. Chtěl jsem jen upozornit na tento efekt, který se může v některé hře objevit a fakt, že jde o velmi hrubou simulaci.

Přesto se ve hře Crysis disperze v mírné míře objevuje při pohledu pod vodou nad hladinu. Tento efekt je sice vidět pouze u DX 10 verze a málokdo si ho uvědomí, ale je tam. Samozřejmě, že Cry Engine 2 nepočítá reálnou disperzi světla, ale pouze se na hranách objektů objeví jakási duha. Více je vidět na následujícím obrázku. První je z DX 10 verze, kde je efekt disperze vidět a druhý z DX 9 verze bez disperze. Obrázky jsou 3x zvětšeny, aby byl efekt více znatelný.




Crysis DX 10 s disperzí




Crysis DX 9 bez disperze
reklama