Rasterizace
Rasterizer (RA)
Jak už jsme si řekli, rasterizace je proces, ve kterém jsou primitiva převáděna z třírozměrného světa do plošného rastru, který reprezentuje plochý displej našeho monitoru. Proces rasterizace funguje tak, že je náš trojúhelník pomocí interpolace „promítnut“ do ploché rastrové mřížky.
Po této projekci budeme tedy vědět, které body (pixely) rastrové mřížky náš trojúhelník obsadil, ale my potřebujeme ještě trochu víc. Při rasterizaci, tedy převodu 3D na 2D, dochází k tomu, že vlastně ztrácíme jeden rozměr, který nám udává vzdálenost objektu od kamery. Při rasterizaci je tedy také nutné určit nejen, které pixely na rastrové mřížce náš trojúhelník obsadil, ale také jejich „hloubku“, která představuje jejich vzdálenost od kamery v původním 3D světě (Z-rozměr).
Poznámka:
Při procesu rasterizace dochází k jednomu nepříjemnému jevu na hranách primitiv - Jagged Edges, tedy jakýchsi zubatých hran.
Velikost "jaggies" je přímo úměrná hustotě rastrové mřížky, která představuje rozlišení, do kterého je 3D objekt rasterizován. O tyto zubaté hrany se tedy budeme muset později nějak postarat za pomoci procesu nazvaného antialiasing (ale o tom až někdy jindy). Druhým způsobem, jak se s "jaggies" vypořádat je pak rendering do rastrové mřížky s vyšším rozlišením, což však představuje vyšší nároky na Pixel Shader a Output Merger (viz. dále).
Výstupem rasterizéru jsou tedy jakési bezbarvé pixely (fragmenty), které popisují přesné umístění každého bodu (x,y), který na rastrové mřížce trojúhelník obsadil a současně také jeho hloubku (z). Poslední věcí, kterou tedy zbývá určit, je barva každého takového fragmentu. Toto finální určení barvy každého pixelu má na starosti následující zastávka grafické pipeline - Pixel Shader.
Pixel Shader (PS)
Pixel Shader je programovatelnou a prakticky nejvytíženější jednotkou pipeline a jak už víme, primárním úkolem PS je vypočítat barvu každého pixelu, který mu zaslal rasterizér. Pokud by byla situace ideální, pak všechny barvy pro každý jednotlivý pixel jsou umístěny na příslušné textuře, kterou je objekt „potažen“. Stačilo by tedy přečíst pouze barvu na patřičném texelu (pixel na textuře) a bylo by hotovo. Bohužel věci tak jednoduché nejsou, objekt může být pokryt vícero texturami, na objekt mohou dopadat různá světla, nebo naopak se musí počítat odlesky materiálu atd. Finální barva pixelu se tedy musí pracně vypočítat z několika zdrojů tak, aby byla v daném prostředí co nejrealističtější. Pokud je barva pixelu vypočítána, práce Pixel Shaderu je ukončena a můžeme jít dále.
Output Merger (OM)
Dříve, nežli si povíme, jak Output Merger pracuje, je třeba si vysvětlit ještě jeden pojem s názvem Z-buffer (Depth buffer). Pokud rasterizujeme objekt po jednotlivých primitivech (trianglech), nikdy nevíme, zda vytvořené pixely tohoto trojúhelníku (nebo jeho část) ve finálním snímku budou či nebudou překrývat pixely trojúhelníku nějakého jiného, již dříve rasterizovaného. Z tohoto důvodu se informace o hloubce pixelu (vzdálenosti pixelu od kamery) ukládají do speciálního úložiště s názvem Z-buffer. Z-buffer je tedy jakýsi pomocný rastr totožné velikosti (x,y), jako má samotná rastrová mřížka, nicméně do jeho hodnot se nevkládá barva pixelu, nýbrž jeho hloubka (z).
Na obrázku jsou hodnoty Z-bufferu reprezentovány stupněm šedi, kdy ke kameře bližší pixely mají barvu světlejší a vzdálenější barvu tmavší. Pokud jsme seznámeni s pojmem Z-buffer, můžeme pokračovat dále.
Barva pixelu byla díky Pixel Shaderu vypočítána a odeslána do Output Merger společně s jeho pozicí (x, y) a vypočtenou hloubkou (z). Ale bude tato barva opravdu reprezentovat daný pixel na obrazovce? Možná ano a možná také ne, to závisí právě na hodnotě hloubky.
Output Merger bere v úvahu také informace o „hloubce“ pixelů v Z-bufferu a postupuje tak, že porovná hloubku právě zpracovávaného pixelu s hloubkou uloženou na stejné pozici v rastru Z-bufferu. Pokud zjistí, že hodnota hloubky pixelu je nižší než ta v Z-bufferu (aktuální pixel je blíže ke kameře), zapíše barvu aktuálního pixelu a jeho hloubku přepíše v Z-bufferu. V opačném případě je pixel zahozen jako neviditelný. Takto je zajištěno, že pixely blíže k pozorovateli (kameře) vždy přepíšou pixely vzdálenější.
Barvy pixelů jsou zapisovány do výstupního zásobníku (Render Target) v paměti GPU (VRAM). V tomto zásobníku se pixely (jejich barvy) postupně shromažďují a postupně je tam i vytvářen také finální snímek (Frame) scény naší hry.
V každém případě Output Merger byl poslední zastávkou grafické pipeline a zbývá již jen dodat, že jako Render Target je nejčastě používán tzv. Back Buffer, který je součástí takového podivného uskupení zásobníků s názvem Swap Chain. Tato kolekce bufferů je umístěna v paměti grafické karty a jejím úkolem je prezentovat hotové snímky na monitor počítače. O tom však bude až další díl této minisérie.
Naprosto zjednodušeně by se dalo říci, že pipeline na grafické kartě funguje tak, že se pracuje postupně s jednotlivými primitivy, které nejdříve pomocí vertexů Input Assembler v prostoru sestaví, Vertex Shader s nimi může nějak pohnout, Tessellation a Gemometry Shader může nějaká primitiva přidat nebo odstranit. Jakmile je tato geometrická část hotova, Rasterizér převádí primitiva z 3D do pixelů plochého rastru, Pixel Shader pak těmto pixelům vypočítá barvu a konečně Output Merger pomocí testu hloubky pixelu proti Z-bufferu buďto pixel zapíše do Render Target, nebo také ne. Hotový finální snímek je umístěn v Render Target (nejčastěji Back buffer) a připraven k prezentaci na monitoru počítače.
Dříve, nežli se vrhneme na grafické karty samotné, pro jistotu znovu zopakuji, že vše, co zde bylo popsáno, je cíleně velmi zjednodušeno a skutečnost je mnohem složitější. Neřekli jsme si zde například o některých technikách (Clipping, Culling, Early Z …), které již dopředu umí odhalit a z pipeline odstranit primitiva nebo pixely, které by ve finálním snímku nebyly nikdy viditelné, zbytečně by pak zahlcovaly pipeline a plýtvaly prostředky grafické karty. Nebyla zde řeč ani o Blendingu (míchání barev) nebo Stencil bufferu, který pracuje na obdobném principu jako Z-buffer (Depth buffer), ale můžou v něm být uchovávány další volitelné hodnoty přidružené k pixelům potřebné pro různé efekty (stínování, reliéf apod.). Nebyla zde řeč ani o mnoha dalších důležitých věcech, ale předpokládám, že ten kdo bude mít eminentní zájem, jistě si vše potřebné dohledá sám.