Vykreslování terénu dun ve WebGL

Vydali jsme novou živou tapetu pro Android a současně zveřejnili živou ukázkovou stránku, která ukazuje všechny funkce aplikace. Webovou stránku můžete zkontrolovat zde.

Historicky bylo jako první vytvořeno webové demo — bylo použito jako prototypové hřiště pro skládání scény a dolaďování shaderů. Také to opravdu pomáhá při sdílení práce mezi týmem dvou lidí, aniž byste se museli učit Android Studio pro oba. A když bylo vše vyleštěné a vypadalo dostatečně dobře, byla na základě webového demo kódu poměrně rychle vytvořena aplikace pro Android. Přenesení kódu na Android je poměrně přímočarý a snadný proces, protože náš rámec WebGL má stejné podpisy metod jako rámec používaný v aplikacích pro Android.

Kompozice scény

Scéna je poměrně jednoduchá a obsahuje pouze šest objektů – terén, oblohu, prachové částice, slunce, ptáky a palmy.

Chcete-li zjistit, jak jsou objekty vykreslovány, můžete se podívat na drawScene() metoda v DunesRenderer.ts — nejprve vykreslíme mapu hloubky na texturu (to je potřeba pro měkké částice), poté vykreslíme objekty na obrazovce v pořadí zepředu dozadu (nejprve nejbližší a největší objekty, pak vzdálené), abychom efektivně využili z- utracení z pufru.
Terén ve scéně je reprezentován jako jedna čtvercová dlaždice. Základem do terénu je tento model zakoupený na CGTrader. Jeho polycount je snížen na 31 000 ploch, aby nedošlo k rozdělení geometrie a nakreslení pomocí jediného volání kreslení. Tento polycount produkuje přiměřeně dobrou kvalitu. Jeho plocha však není tak velká, aby vytvořila dojem nekonečné písečné pouště – když je kamera umístěna mírně nad terénními hranicemi čtvercového terénu, jsou její limity jasně viditelné:

Zjevně to snižuje rozsah pohybu kamery a vytváří nežádoucí pocit, že se terén „vznáší“ v prostoru. Abychom tento efekt eliminovali a zlepšili atraktivitu scény, používáme techniku ​​zvanou „terénní sukně“. Dozvěděli jsme se o tom z této skvělé přednášky GDC o terénu v Halo Wars. Určitě byste si měli prohlédnout celé video, protože vysvětluje spoustu dalších zajímavých a jedinečných technik, které by se vám mohly hodit. Myšlenkou této terénní sukně je vykreslit stejnou dlaždici na okrajích dlaždice, ale zrcadlově od středu scény. Tím se výrazně rozšiřuje plocha terénu. Tento snímek obrazovky ukazuje všech 8 dalších vykreslených dlaždic (s dalšími mezerami na samostatné dlaždice):

Můžete vidět zrcadlení dlaždic na okrajích, kde se duplicitní dlaždice spojují s hlavní, ale ve finální aplikaci to není patrné, protože kamera je umístěna pouze v hlavní dlaždici, aby se zabránilo přímému pohledu na tyto okraje. Další dlaždice vykreslíme 1,5krát větší než původní, čímž efektivně zvětšíme vnímané rozměry terénu 4krát. Tento krátký klip ukazuje, jak vypadá finální rozšířený terén se sukní a bez ní:

Jak můžete vidět, tento jednoduchý trik vytváří obrovský, zdánlivě nekonečný terén táhnoucí se až k horizontu s velmi malým úsilím a znovu využívá existující geometrie.

Prachové částice

Pro prachový efekt se používají měkké částice. Více o této technice si můžete přečíst v našem předchozím článku — https://dev.to/keaukraine/implementing-soft-particles-in-webgl-and-opengl-es-3l6e.
Jediný objekt vykreslený s hloubkovou texturou pro měkké částice je hlavní dlaždice terénu, protože to je jediná geometrická částice, se kterou se protínají. Aby bylo toto vykreslování rychlejší, používá se k vykreslení tohoto objektu nejjednodušší fragment shader namísto složitého, který se používá k vykreslení terénu na obrazovce.

Shader Dunes

Pro simulaci efektu větru vytvářejícího písečné vlny na povrchu dun jsme vyvinuli poměrně složitý shader. Pojďme se podívat dovnitř. Vezměte prosím na vědomí, že zatímco vysvětlíme GLSL kód shaderu, generické techniky a přístupy v něm používané mohou být také použity k opětovnému vytvoření podobného materiálu v Unity/Unreal engine.
Kód shaderu lze nalézt na DunesShader.ts. Pojďme to analyzovat.

Rozptýlené barvy a světelné mapy

Terén používá poměrně velkou texturu — 2048x2048 pro webovou ukázku a až 4096x4096 v aplikaci pro Android. Je zřejmé, že to vyžaduje docela dost paměti, takže pro efektivní využití byly použity některé triky. Hlavní difúzní barva pro duny je ve skutečnosti uložena jako jednokanálová hodnota ve stupních šedi v červeném kanálu textury terénu. Skutečná barva písku je určena uColor uniformní, která je vynásobena difuzní hodnotou ve stupních šedi. Další 2 kanály obsahují světelné mapy pro vysoké slunce (den a noc) a nízké slunce (východ a západ slunce). Protože pro přístup k texturovým datům není možné používat uniformy, jsou pro dvě světelné mapy zkompilovány dvě verze shaderu. Finální difúzní barva je znásobena barvou stínů.

Efekt pohyblivého písku

Dále se podívejme na to, jak vzniká efekt pohybujícího se větru. Můžete si všimnout, že u návětrných a závětrných svahů dun je tomu jinak. Abychom určili, který efekt použít na který sklon, vypočítáme koeficienty prolnutí z normály povrchu. Tyto koeficienty se počítají na vrchol a jsou předány do shaderu fragmentů pomocí vSlopeCoeff a vSlopeCoeff2 měnící se. Odpovídající čáry můžete odkomentovat ve fragment shaderu a vizualizovat návětrné a závětrné části různými barvami:

Oba svahy používají stejnou texturu, která je na nich aplikována, ale návětrný je více natažený. Souřadnice textur pro oba svahy jsou také vypočítány ve vertex shaderu, aby se zabránilo závislému čtení textury. Pohyb větru se provádí přidáním offsetu k souřadnicím textury od uTime uniforma.

Mlha

Další důležitou věcí pro získání realistického výsledku je použití atmosférické mlhy. Z výkonnostních důvodů používáme jednoduchou lineární mlhu, která se počítá ve vertex shaderu. Rozsah mlhy je řízen dvěma uniformami — fogStartDistance a fogDistance a hodnota, která má být použita ve fragment shaderu, je vypočítána a uložena v vFogAmount měnící se. Shader fragmentů použije barvu mlhy z uFogColor jednotné na základě hodnoty tohoto proměnlivého.
Barva mlhy je upravena pro vzdálené okraje terénu, aby splynula s texturou oblohy. A textura oblohy je také upravena tak, aby měla vzdálený opar stejné barvy mlhy v místech, kde by měla splynout s terénem.

Detail textury

I když je celková textura terénu poměrně velká, pokrývá velkou plochu, a proto stále není dostatečně detailní pro detailní záběry. Aby byly duny méně rozmazané a realističtější při pozorování ze země, aplikujeme na ně detailní texturu. Jedná se o malou texturu 256x256, která má 2 různé vzory vlnění písku ve 2 kanálech pro různé svahy. Detailní textura může difúzní barvu buď ztmavit, nebo zesvětlit. Abychom toho dosáhli, nejprve odečteme 0,5 od barvy detailu, aby mohla mít zápornou hodnotu, a poté se tato hodnota přičte ke konečné barvě. Tímto způsobem 50 % šedé barvy v detailu textury neovlivní rozptýlenou barvu, tmavší hodnoty ji ztmaví a jasnější hodnoty barvu zesvětlí. Detailní textura se aplikuje podobným způsobem jako mlha – má dvě uniformy pro úpravu ořezové vzdálenosti tam, kde detailní textura není potřeba. Můžete odkomentovat čáru ve fragment shaderu a vizualizovat detailní rozsah textury v červeném kanálu:

Výsledek

Živou ukázkovou stránku můžete vidět zde. Je interaktivní – kliknutím můžete změnit denní dobu. A na ploše, abyste mohli prozkoumat scénu z libovolné pozice, můžete přejít do režimu volného letu stisknutím klávesy Enter. V tomto režimu pro otáčení kamery podržte pravé tlačítko myši a pro pohyb použijte klávesy WASD, mezerník nahoru a C dolů. Pro zrychlení podržte Shift při pohybu.
Úplný zdrojový kód je k dispozici na GitHubu, pokud máte zájem o opětovné vytvoření podobných efektů, můžete jej naklonovat a použít pro své potřeby — je licencován pod licencí MIT.