Rectilinear Texture Warping for Fast Adaptive Shadow Mapping
Tereza Hlavová
Zadání
Práce implementuje základní techniku stínových map a rozšiřuje jí o vykreslování stínů za pomocí adaptivního mapování stínových map s přímočarou deformací textur - Rectilinear Texture Warping(RTW).
Myšlenka spočívá ve zhodnocení scény z hlediska důležitosti vůči kameře a snaze o deformaci stínové textury tak, aby její fixní rozlišení bylo využito efektivněji, tedy důležitějším částem scény připadá větší část textury než méně důležitým.
Dopředná varianta algoritmu začíná vykreslením hloubkové textury z pohledu světla, jejíž texely jsou následně zhodnoceny z hlediska důležitosti (projekce texelů dopředu do pohledu kamery), zatímco zpětná varianta začíná plným vykreslením z pohledu kamery a texely promítá zpět do pohledu světla.
Důležitost se v této implementaci počítá ze vzdálenosti od kamery.
Obě varianty takto utvoří mapu důležitosti (Importance map), podle které se následně vrcholy objektů ve scéně posouvají při vykreslování deformované stínové mapy. S deformací se samozřejmě musí počítat i při aplikaci vygenerované stínové mapy
a to ve formě posunu texturovacích souřadnic.
Implementace
Implementace vychází z kostry příkladu stínového mapování ze zdrojů na cvičení předmětu.
FrameBuffery, textury, shadery
Aplikace dohromady utvoří dva pomocné frame buffery: FullRenderFB s RGB i Z-buffery pro vykreslovaní v rozlišení pohledu z kamery a ShadowFB se Z-bufferem a barevným bufferem s pouze červenou složkou (pro čtení v compute shaderech) pro vykreslení ve zvoleném rozlišení pro stínovou mapu.
Dále pak pomocné textury Importance v rozlišení stínové mapy ve formátu red channel unsigned integer, čtyři 1D textury stejného formátu a 2 1D textury red channel float.
Protože výpočet deformací je z velké části prováděn v compute shaderech za pomocí atomických operací, je potřeba pracovat právě v unsigned integer formátu, na který jsou hodnoty Z-bufferu převáděny a naopak.
Základní stínové mapy
Základní varianta používá navíc pouze ShadowFB frame buffer a obejde se bez compute shaderů či dalších pomocných textur. V prvním průchodu generuje stínovou mapu, kterou při následném plném renderu ihned aplikuje.
Dopředná RTW
Dopředná varianta začíná průchodem vykreslujícím hloubkovou mapu z pohledu zdroje světla do ShadowFB frame bufferu a rovnou do napojené Importance textury zapisuje hodnoty důležitosti po transformování fragmentů do pohledu kamery.
Následují tři průchody v compute shaderech - nejprve se do dvou 1D map pro osu x a y uloží maximální hodnoty důležitosti (nutnost atomických operací), poté se na hodnoty aplikuje gaussian blur a nakonec se předpočítají hodnoty posunu pro deformaci podle vzorce:
kde k značí zpracovávaný texel, n celkový počet texelů v 1D textuře a I jsou hodnoty důležitosti.
V dalším průchodu se znovu použije ShadowFB frame buffer, tentokrát ale ve vertex shaderu dojde k posunu renderovaných vrcholů ve scéně podle hodnot z vytvořených map v předchozím kroku. Do fragment shaderu už tedy jdou fragmenty deformované a stači pouze uložit jejich hloubku do nyní deformované stínové mapy.
Poslední průchod vykresluje scénu plně z pohledu kamery a podle hodnot čtených z 1D map posouvá uv souřadnice, pod kterýma následně čte hodnoty z deformované stínové mapy a stíny pomocí těchto hodnot dopočítá.
Zpětná RTW
Zpětná varianta začíná průchodem provádějícím plný render z pohledu kamery do FullRenderFB frame bufferu. Poté do Importance textury zapisuje hodnoty důležitosti po transformování fragmentů zpět do pohledu světla, atomickými operacemi. Následují tři průchody v compute shaderech - úplně stejně jako v dopředné variantě. Varianty se liší až v posledním kroku a to faktem, že v této variantě už plný render proběhl v prvním kroku a není proto potřeba ho opakovat, pouze se dopočítají stíny a na výsledek se přidají.
Zhodnocení
Základní technika pro stínové mapy o rozlišení 1024x1024 dosahovala rychlosti vykreslení snímku do 1ms, přičemž větší část výpočtu, tedy druhý průchod, plný render, zabíral okolo 60 procent času. Dané rozlišení po přiblížení k jednotlivým objektům ve scéně rozhodně není dostatečné.
Dopředná i zpětná technika se stejným rozlišením dosahují mnohem lepších vizualních výsledků, a to dokonce i s rozlišením nižším - 512x512.
Ovšem pro 1024x1024 trvá výpočet jednoho snímku mnohem déle, pro dopřednou variantu okolo 3.2ms a pro zpětnou 3.5ms.
Pro rozlišení 512x512 se časy pro dopřednou variantu pohybují okolo 2.1ms a pro zpětnou 2.8ms.
Zpětná variantu k mému překvapení na Importance průchodu netráví ve skutečnosti v poměru k ostatním průchodům zas tolik času - 10% výpočtu. Pro nižší rozlišení stínové mapy, než je
rozlišení renderovaného okna nejvíce času zabere první průchod, tedy plné vykreslení scény (krom stínů). Pro vyšší rozlišení (při testovaní 512x512/1024x1024 a výš) však nejdéle trvá
třetí krok warpingu, kde prostor ke zrychlení nejspíš je - provádí se tu v každém texelu sumy hodnot, které by implementací prefixového součtu mohly dosáhnout lepšího výkonu.
Dopředná varianta je na tom ohledně třetí fáze warpingu podobně, ale pro nižší rozlišení nejdéle trvá poslední finální render.
Co se týče paměti potřebné na dodatečné textury, RTW techniky oproti klasické, např. 1024x1024, dosahují podobné kvality při použití rozlišení 512x512, kterou potřebují pro výpočty jako stínovou mapu,
mapu důležitosti a poté 3x 1D warping mapy (zde by pravděpodobně stačily dvě, lze je prohazovat pro čtení/zápis mezi průchody compute shaderu).
To je tedy 1,048,576 texelů klasické stínové mapy oproti 525,824 texelům RTW.
Ovládání
[z/Z] ... pohyb po Z souřadnici
[s] ... ukázat/schovat generované textury
[t] ... ukázat a počítat/schovat statistiky pro průchody algoritmu
[a/A] ... výběr algoritmu
[f/F] ... float hodnota pro lepší vizualizaci hodnot v texturách
[y/Y] ... z offset pro stínové mapy (omezení surface akné)
[d/D] ... změna rozlišení stínových map
[c] ... překompilovat shadery
[mouse] ... rotace scény
[šipky] ... pohyb se scéně