Deferred Clustered Shading
Martin Douda
Popis projektu
Mým úkolem bylo naimplementovat techniku Clustered Deferred Shading, což je odložené stínování optimalizované rozdělením viditelné části scény uvnitř pohledového tělesa na 3D bloky (clustery), pro které je nalezena skupina světelných zdrojů, které mohou ovlivňovat jejich objem.
Tuto techniku jsem měl za úkol porovnat s klasickým zobrazováním, nebo s Tile-based Deferred Shading na vhodně navržené scéně, ve které měla být možnost měnit počet světelných zdrojů. Mělo být podporováno minimálně 1024 světel, množství objektů a jejich hloubkový rozsah.
Měl jsem se zaměřit na analýzu jednotlivých fází algoritmu, a to s ohledem na časovou i paměťovou náročnost a pokusit se o optimalizaci těchto jednotlivých fází.

Ukázka z aplikace
Popis implementace
Celou implementaci jsem prováděl na vlastním frameworku, který jsem vytvářel v průběhu semestru a vždy do něj doplňoval aktuálně probíranou látku. Moje implementace využívá Vertex a Fragment shadery pro vykreslování scény do textur a finální vykreslování na obrazovku za použití těchto textur a příslušných světel. Výpočty týkající se implementované techniky jsou prováděny pomocí Compute shaderů.
Implementace obsahuje tři již zmíněné techniky pro stínování, mezi kterými lze za běhu aplikace přepínat. Jedná se o klasické odložené stínování (v aplikaci jako “Deferred“), kde pro výpočet nasvícení každého pixelu jsou zahrnuty všechny světelné zdroje. Dále Tile-based odložené stínování založené na rasterizaci (v aplikaci jako “Deferred Tiled“), ve které jsou kresleny koule, umístěné do středů bodových světel, do malého framebufferu, přičemž je do shader storage bufferu zaznamenáváno, do jakého pixelu se jaká koule vykreslila. Poté je osvětlení počítáno pouze pro světla, která danou oblast mohou ovlivňovat. V poslední řadě Clustered odložené stínování (v aplikaci jako “Deferred Clustered“), které rozšiřuje Tile-based do tří dimenzí. V této implementaci ale není užito rasterizace k přidělování světel do clusterů, ale na místo toho je užito testu průsečíku koule s AABB (Axis Aligned Bounding Box) daného clusteru. Implementaci této techniky je detailněji rozeberána v následující sekci.
Detailní popis Clustered Deferred Shading
V mojí semestrální práci jsem se věnoval převážně implementaci a optimalizaci techniky Clustered Deferred Shading. Technika je rozdělena na 3 hlavní části: inicializaci clusterů, označení aktivních clusterů a hledání světel co zasahují do těchto aktivních clusterů.
Inicializace clusterů probíhá tak, že rozdělíme pohledový jehlan podle vzdálenosti od kamery v ose z na malé plátky a tyto jednotlivé plátky dále rozřežeme v osách x a y na clustery, jak je znázorněno na obrázcích níže. Poté vezmeme rohy vzniklých clusterů a nalezneme maxima a minima ve všech osách, a to nám vytvoří AABB daného clusteru. Celý tento výpočet lze jednoduše provést na GPU pomocí Compute shaderu.


Zdroj obrázků: How to Implement Clustered Shading
Pro druhý krok, kterým je označení aktivních clusterů, je za potřebí hloubková textura scény, v případě odloženého stínování je tedy vhodné předem provést vykreslení scény do GBufferu a využít jeho hloubkový buffer. Tento hloubkový buffer předáme Compute shaderu a pro každý pixel spočítám do jakého clusteru náleží. Tento cluster potom označíme za aktivní a v dalším kroku pro něj budeme hledat světla, která do něho zasahují.
Posledním krokem je pak samotné hledání světel, které do clusterů zasahují a zapisování indexů těchto světel do bufferu. Pro tento krok je vhodné v Compute shaderu nejdříve načíst AABB světel do sdílené paměti, a poté testovat průsečík těchto těles s AABB clusterů. Pro každé světlo, které do AABB pasuje si uložíme jeho index do lokálního pole a na závěr si atomickou operací zarezervujeme místo v poli všech indexů a nakopírujeme do něj indexy z lokálního pole.
Ve všech těchto krocích je spousta míst pro různé optimalizace, o které jsem se pokusil, např. kopírování co nejmenšího množství dat s co nejdále dotaženými výpočty do sdíleného pole, užití subgroup pro zrychlení atomické operace při rezervování indexu, využí uniformních bufferů a shader storage bufferů na místo mnoha uniform volání a spousta dalších optimalizací pro zrychlení celého běhu aplikace.


Porovnání deferred tiled a deferred clustered na stejném pohledu na scénu
Ovládání
Pro pohyb ve scéně je nutné držet stisknuté pravé tlačítko myši a poté použít klávesy WASD a QE pro pohyb vertikálně dolu a nahoru. Dále je možné pohyb zrychlit držením klávesy CTRL anebo zpomalit pomocí LSHIFT. Zbytek ovládání jako je změna počtu bodových světel, počtu objektů ve scéně a jiná nastavení se provádějí pomocí uživatelského rozhraní.