Poglavlje 29: UE5 Rendering Arhitektura

Poglavlje 29: UE5 Rendering Arhitektura

Deo V: UE5 Specifično


"Da biste napravili nešto lepo, morate prvo razumeti mašinu koja to pravi."


Dobrodošli u peti deo knjige — i u svet specifičan za Unreal Engine 5. Do sada ste izgradili solidno razumevanje grafičkog pipeline-a uopšteno, od vertex transformacija do post-processinga. Sada ćemo zaroniti u to kako tačno UE5 organizuje sve te korake da bi isporučio kadar na vaš ekran.

Ovo poglavlje je jedno od najvažnijih u čitavoj knjizi. Rendering arhitektura je srce svakog game engine-a — sve ostalo, od materijala do osvetljenja, od senki do post-processinga, oslanja se na odluke donete u ovom sloju. Kada razumete kako UE5 organizuje svoje render pass-ove, zašto koristi deferred shading, i šta se tačno nalazi u G-Buffer-u, imaćete mnogo jasniju sliku zašto su neke stvari brze, neke skupe, a neke jednostavno nemoguće bez workaround-a.

Hajde da počnemo.


29.1 Dva pristupa renderovanju: Forward vs Deferred

Pre nego što uđemo u UE5-specifične detalje, moramo da razumemo fundamentalnu arhitektonsku odluku koju svaki moderni engine mora da donese: kako organizovati osvetljenje scene?

Postoje dva osnovna pristupa, i svaki ima duboke posledice na performanse, mogućnosti, i ograničenja engine-a.

29.1.1 Forward Rendering — Klasičan pristup

Forward rendering je stariji i konceptualno jednostavniji pristup. Princip je sledeći:

Za svaki objekat u sceni, za svaki piksel tog objekta, izračunaj kompletno osvetljenje odmah — u istom draw call-u koji crta geometriju.

Zamislite to ovako: engine prolazi kroz listu objekata za renderovanje. Za svaki objekat poziva vertex shader (da transformiše geometriju), pa fragment/pixel shader (da izračuna boju piksela). U tom pixel shader-u, odmah se računa uticaj svakog svetla na taj piksel. Rezultat ide direktno u framebuffer.

Za svaki objekat:
    Za svaki piksel objekta:
        Evaluiraj materijal
        Za svako svetlo koje utiče na ovaj piksel:
            Izračunaj osvetljenje
        Zapiši konačnu boju u framebuffer

Prednosti Forward renderinga

  1. Jednostavnost: Konceptualno je lako pratiti šta se dešava. Jedan objekat, jedan draw call, kompletna boja piksela.

  2. Hardverski MSAA (Multisample Anti-Aliasing): Ovo je velika prednost. Budući da se geometrija renderuje direktno u framebuffer, GPU hardver može da primeni MSAA — tehniku anti-aliasing-a koja uzorkuje ivice geometrije na više lokacija unutar piksela i prosečuje rezultate. MSAA je izuzetno kvalitetan za ivice objekata i ne zahteva nikakav post-processing. U poglavlju 07 smo pomenuli ovu tehniku — ovde vidimo zašto je forward rendering jedini put koji je u potpunosti podržava.

  3. Transparentni objekti: Forward rendering prirodno radi sa transparentnim objektima jer svaki objekat ima kompletnu informaciju o osvetljenju u trenutku renderovanja.

  4. Manji memorijski footprint: Nema potrebe za dodatnim baferima koji čuvaju međurezultate — sve ide direktno u framebuffer.

Ograničenja Forward renderinga

  1. Ograničen broj svetala: Ovo je fundamentalni problem. Budući da se za svaki piksel svakog objekta moraju evaluirati sva svetla, kompleksnost raste kao O(objekata × piksela × svetala). Scena sa 50 dinamičkih svetala može da dovede forward renderer do kolapsa. Čak i sa optimizacijama (light culling po objektu), forward rendering teško podnosi scene bogate svetlima.

  2. Redundantan rad (overdraw): Ako dva objekta preklapaju isti piksel na ekranu, forward renderer će izračunati kompletno osvetljenje za oba piksela, iako će samo bliži biti vidljiv. Depth prepass (koji smo obradili u poglavlju 09) može da ublaži ovaj problem, ali ne eliminiše ga potpuno — geometrija se i dalje mora obraditi dva puta.

  3. Komplikovan shader kod: Svaki materijal shader mora da sadrži kompletnu logiku osvetljenja. To znači da su shaderi veliki, kompleksni, i teški za održavanje. Dodavanje novog tipa svetla zahteva izmenu svakog materijal shader-a.

  4. Složenost varijanti: Kada imate N tipova materijala i M tipova svetala, potencijalno vam treba N × M shader varijanti. Ovo je kombinatorna eksplozija koja komplikuje shader kompilaciju i cache.

29.1.2 Deferred Rendering — Moderan pristup

Deferred rendering (odloženo renderovanje) rešava problem forward renderinga tako što razdvaja geometriju od osvetljenja u dva potpuno odvojena koraka.

Korak 1 — Base pass (geometrija): Renderuj sve objekte, ali nemoj računati osvetljenje. Umesto toga, zapiši informacije potrebne za osvetljenje (normale, boju, metalnost, hrapavost...) u skup tekstura koji se zove G-Buffer (Geometry Buffer).

Korak 2 — Lighting pass (osvetljenje): Za svaki piksel na ekranu, pročitaj podatke iz G-Buffer-a i izračunaj osvetljenje. Ovo se radi u screen-space-u — nema više veze sa originalnom geometrijom.

KORAK 1 - Base Pass:
Za svaki objekat:
    Za svaki piksel objekta:
        Evaluiraj materijal
        Zapiši normale, boju, metalnost, hrapavost... u G-Buffer

KORAK 2 - Lighting Pass:
Za svaki piksel na ekranu:
    Pročitaj podatke iz G-Buffer-a
    Za svako svetlo koje utiče na ovaj piksel:
        Izračunaj osvetljenje
    Zapiši konačnu boju u framebuffer

Prednosti Deferred renderinga

  1. Efikasno rukovanje velikim brojem svetala: Kompleksnost osvetljenja je sada O(piksela × svetala) — potpuno nezavisna od broja objekata u sceni. Možete imati stotine dinamičkih svetala bez značajnog pada performansi, jer se svako svetlo obrađuje samo jednom po pikselu.

  2. Eliminacija overdraw problema za osvetljenje: Čak i ako se 10 objekata renderuje na isti piksel, osvetljenje se računa samo jednom — za piksel koji je zaista vidljiv (najbliži kameri). Sav "bačeni" rad se dešava samo u base pass-u (koji je relativno jeftin jer ne računa osvetljenje), ne u skupom lighting pass-u.

  3. Jednostavniji shaderi: Materijal shaderi su jednostavniji jer samo zapisuju atribute u G-Buffer. Lighting shader je odvojen i univerzalan. Dodavanje novog tipa svetla ne zahteva izmenu materijal shader-a.

  4. Fleksibilnost: Budući da su svi podaci o površini dostupni u G-Buffer-u, lako je dodavati nove efekte koji rade u screen-space-u (SSAO, screen-space reflections, itd.).

Ograničenja Deferred renderinga

  1. Nema hardverskog MSAA: Budući da se geometrija ne renderuje direktno u framebuffer, već u G-Buffer teksture, hardverski MSAA ne može da se primeni na uobičajen način. G-Buffer bi morao da bude multi-sampled, što bi dramatično povećalo memorijsku potrošnju (svaki sample bi zahtevao kompletnu kopiju svih G-Buffer tekstura). Zato deferred rendereri koriste TAA (Temporal Anti-Aliasing) ili TSR (Temporal Super Resolution) — softverske tehnike anti-aliasing-a koje rade u post-processingu. Ovo ćemo detaljnije obraditi u nastavku poglavlja.

  2. Velika memorijska potrošnja za G-Buffer: G-Buffer može da zauzme značajnu količinu video memorije — pogotovo na visokim rezolucijama. Na 4K rezoluciji, samo osnovna tri G-Buffer-a mogu zauzeti više od 100 MB. O tačnim brojevima ćemo govoriti u sekciji 29.4.

  3. Memorijski bandwidth: Zapisivanje u G-Buffer (base pass) i čitanje iz G-Buffer-a (lighting pass) zahteva ogromnu količinu memorijskog bandwidth-a. Ovo može postati usko grlo, posebno na mobilnim GPU-ovima.

  4. Ograničeni shading modeli: Sve informacije o površini moraju da stanu u fiksne G-Buffer teksture. Ako želite novi shading model koji zahteva neku egzotičnu informaciju (npr. debljinu potkožnog tkiva za subsurface scattering), morate da nađete gde da je smestite u postojeće kanale. Ovo ograničava fleksibilnost shading modela.

  5. Transparentni objekti: Providni objekti ne mogu da se renderuju kroz deferred pipeline jer ne mogu da zapišu svoje atribute u G-Buffer na smislen način (G-Buffer čuva samo jedan set atributa po pikselu — najbliži). Zato se transparentni objekti uvek renderuju forward pristupom, čak i u engine-u koji inače koristi deferred rendering.

29.1.3 Šta koristi UE5?

Unreal Engine 5 koristi deferred rendering kao podrazumevani rendering put.

Ovo je svesna arhitektonska odluka koja odražava prioritete modernog game engine-a: podržati složene scene sa velikim brojem dinamičkih svetala, naprednim GI sistemom (Lumen), i kompleksnim materijalima. Deferred rendering omogućava UE5 da efikasno obradi scene koje bi bile nepraktične sa forward renderingom.

Međutim, UE5 takođe nudi forward rendering put za specifične slučajeve:

U nastavku ovog poglavlja, fokusiraćemo se pretežno na deferred rendering pipeline jer je to podrazumevani i najčešće korišćeni put u UE5 projektima za desktop i konzole.


29.2 Render Pass-ovi u UE5 — Redosled operacija po kadru

Svaki kadar koji UE5 isporuči na vaš ekran prolazi kroz pažljivo organizovan niz koraka — render pass-ova. Svaki pass ima specifičnu ulogu, i redosled u kom se izvršavaju nije proizvoljan — on je rezultat decenija istraživanja i optimizacije u real-time renderingu.

Hajde da prođemo kroz kompletnu sekvencu, od prvog do poslednjeg koraka.

29.2.1 Pregled sekvence

Evo kompletne sekvence render pass-ova u tipičnom UE5 kadru sa deferred renderingom:

1. Visibility & Occlusion Culling
2. Depth Prepass (Early-Z)
3. Base Pass (geometrija → G-Buffer)
4. Shadow Depth Passes
5. Lighting Pass (deferred shading)
6. Lumen GI & Reflections
7. Translucency Pass (forward)
8. Post-Processing Chain
9. Final Output (framebuffer / backbuffer)

Svaki od ovih koraka ćemo sada detaljno objasniti.

29.2.2 Visibility i Occlusion Culling

Pre nego što se ijedan piksel nacrta, UE5 mora da odluči šta je uopšte vidljivo. Nema smisla slati GPU-u geometriju koja je iza kamere, van frustuma, ili zaklonjena drugim objektima.

Frustum culling: Objekti koji su van frustuma kamere (vidnog polja) se odbacuju. Ovo se radi na CPU-u koristeći bounding box-ove objekata. Brz i jednostavan test koji eliminiše veliki deo scene.

Occlusion culling: Objekti koji su potpuno zaklonjeni drugim objektima (npr. zgrada iza zgrade) se takođe odbacuju. UE5 koristi kombinaciju softverskog i hardverskog occlusion culling-a:

Rezultat ovog koraka je lista objekata (i njihovih mesh-eva) koji zaista treba da se renderuju — visible set.

29.2.3 Depth Prepass (Early-Z)

Ovo je koncept koji smo detaljno obradili u poglavlju 09, ali hajde da ga stavimo u kontekst UE5 deferred pipeline-a.

Šta se dešava: Pre base pass-a, UE5 renderuje svu neprozirnu geometriju koristeći samo vertex shader — bez ikakvog pixel shader-a (ili sa minimalnim pixel shader-om za alpha-tested materijale). Cilj je da se popuni depth buffer (Z-buffer) sa dubinskim vrednostima svih vidljivih piksela.

Zašto: Kada se base pass izvršava nakon depth prepass-a, GPU može da koristi Early-Z rejection — hardversku optimizaciju koja preskače pixel shader za piksele koji ne bi prošli depth test. Ovo znači da se za piksele koji su zaklonjeni bližom geometrijom uopšte ne izvršava materijal shader. S obzirom na to da materijal shaderi u base pass-u mogu biti veoma skupi (kompleksni materijali sa mnogo tekstura i računanja), ovo je ogromna ušteda.

Bez depth prepass-a:
    Objekat A crta piksel na (500, 300) — kompletan materijal shader se izvršava
    Objekat B crta piksel na (500, 300) — kompletan materijal shader se izvršava
    Samo bliži piksel preživljava depth test → shader za dalji piksel je bio uzaludan

Sa depth prepass-om:
    Prepass: oba objekta pišu samo dubinu — brzo
    Base pass: piksel (500, 300) — Early-Z proverava dubinu PRVO
    Ako ovaj objekat nije najbliži → preskoči materijal shader kompletno!

UE5 specifično: U UE5, depth prepass je posebno važan jer base pass piše u G-Buffer — multiple render targets. Pisanje u više tekstura istovremeno je memorijski skupo, pa je eliminacija nepotrebnog pisanja (kroz Early-Z) kritična za performanse.

Depth prepass takođe generiše depth buffer koji će se koristiti u kasnijim pass-ovima: shadow depth, screen-space efekti (SSAO, SSR), i post-processing.

29.2.4 Base Pass — Geometrija u G-Buffer

Ovo je centralni render pass deferred pipeline-a i zaslužuje posebnu sekciju (29.3). Ovde ćemo dati pregled:

Šta se dešava: Sva neprozirna geometrija se renderuje sa kompletnom materijal evaluacijom. Za svaki vidljivi piksel, materijal shader izračunava surface atribute (boja, normale, metalnost, hrapavost, specular...) i zapisuje ih u G-Buffer — skup tekstura pune rezolucije ekrana.

Ključna stvar: U ovom koraku se ne računa osvetljenje. Shaderi evaluiraju samo materijal — boju teksture, normal map-u, PBR parametre. Rezultat je "sirova" informacija o površini, bez ikakvog svetla.

Za Nanite mesh-eve, base pass je organizovan drugačije — Nanite ima svoj vlastiti rasterizer koji direktno piše u G-Buffer, zaobilazeći tradicionalni hardverski rasterization pipeline. Ali konceptualno, rezultat je isti: G-Buffer popunjen atributima površina.

29.2.5 Shadow Depth Passes

Šta se dešava: Za svako svetlo koje baca senku, scena se renderuje iz perspektive tog svetla da bi se generisao shadow map — depth tekstura koja opisuje šta svetlo "vidi".

Ovo znači da se geometrija scene renderuje ponovo — ali samo sa depth zapisivanjem (slično depth prepass-u), bez materijal evaluacije. Za svako svetlo sa senkama, potreban je barem jedan dodatni render pass.

Tipovi shadow map-ova u UE5:

Zašto ovaj korak dolazi posle base pass-a? Zato što se informacije iz base pass-a (posebno depth buffer) koriste za optimizaciju shadow renderinga — engine zna koji pikseli su vidljivi i na kojim rastojanjima, pa može da optimizuje shadow map rezolucije i culling.

29.2.6 Lighting Pass — Deferred Shading

Šta se dešava: Sada dolazi korak koji daje deferred renderingu ime. Za svaki piksel na ekranu, engine:

  1. Čita podatke iz G-Buffer-a (normala, boja, metalnost, hrapavost, itd.)
  2. Čita shadow map-ove za relevantna svetla
  3. Za svako svetlo koje utiče na ovaj piksel, izračunava doprinos osvetljenja
  4. Sabira sve doprinose u konačnu osvetljenu boju

Ovaj pass radi isključivo u screen-space — nema geometrije, samo full-screen ili per-light volume renderovanje. Light culling (o kome ćemo govoriti u sekciji 29.5) osigurava da se za svaki piksel evaluiraju samo svetla koja zaista utiču na njega.

Rezultat lighting pass-a je scene color buffer — tekstura pune rezolucije sa kompletno osvetljenom, ali još uvek ne post-procesiranom slikom.

29.2.7 Lumen GI i Reflections

Šta se dešava: Nakon standardnog lighting pass-a, UE5 primenjuje Lumen — svoj global illumination i reflection sistem. Lumen kombinuje:

Lumen koristi podatke iz G-Buffer-a (posebno normale i roughness) da bi znao gde i kako da primeni GI i refleksije. Rezultat se dodaje na scene color buffer kao dodatni doprinos osvetljenju.

29.2.8 Translucency Pass

Šta se dešava: Sada se renderuju providni (translucent) objekti — staklo, voda, efekti čestica, volumetrička magla, itd.

Kritična razlika: Transparentni objekti se renderuju forward pristupom, čak i u deferred pipeline-u. Razlog je fundamentalan: G-Buffer čuva samo jedan set atributa po pikselu. Transparentni objekti zahtevaju blending — kombinovanje boje transparentnog objekta sa bojom pozadine. Ovo je nemoguće u čistom deferred pristupu jer bismo morali da čuvamo atribute i prednjeg i zadnjeg objekta.

Providni objekti se sortiraju od najdaljeg ka najbližem (back-to-front) i renderuju se forward pristupom:

  1. Za svaki transparentni objekat
  2. Evaluiraj materijal
  3. Izračunaj osvetljenje (forward — u istom shader-u)
  4. Blend sa scene color buffer-om

Ovo znači da transparentni objekti imaju ograničenja u broju svetala koja mogu da ih osvetle (jer koriste forward rendering), i mogu da budu skuplji od neprozirnih objekata.

29.2.9 Post-Processing Chain

Šta se dešava: Scene color buffer, koji sada sadrži potpuno osvetljenu scenu (uključujući GI, refleksije, i transparentne objekte), prolazi kroz lanac post-processing efekata. Ovo je tema koju smo detaljno obradili u poglavlju 15, ali evo kratkog pregleda u kontekstu render sekvence:

  1. Temporal Anti-Aliasing (TAA) ili Temporal Super Resolution (TSR): Budući da deferred rendering ne podržava hardverski MSAA, TAA/TSR je primarni metod anti-aliasing-a. Koristi podatke iz prethodnih kadrova (motion vectors iz velocity buffer-a) da ublaži aliasing.

  2. Tone Mapping: Konverzija iz HDR (High Dynamic Range) u LDR (Low Dynamic Range) koji monitor može da prikaže.

  3. Bloom: Simulacija bljeska svetlih izvora svetlosti.

  4. Depth of Field: Simulacija fokusa objektiva kamere.

  5. Motion Blur: Zamućenje pokreta zasnovano na velocity buffer-u.

  6. Auto Exposure / Eye Adaptation: Automatsko prilagođavanje ekspozicije.

  7. Color Grading / LUT: Korekcija boja i kreativno obojenje.

  8. Vignette, Film Grain, Chromatic Aberration: Filmski efekti.

29.2.10 Zašto je ovaj redosled bitan?

Redosled render pass-ova nije proizvoljan — svaki korak zavisi od rezultata prethodnih koraka:

Pass Zavisi od
Depth Prepass Visibility rezultata
Base Pass Depth buffer-a iz prepass-a (za Early-Z)
Shadow Depth Depth buffer-a (za optimizaciju), visibility podataka
Lighting Pass G-Buffer-a (iz base pass-a), Shadow map-ova
Lumen GI G-Buffer-a, Lighting rezultata, Scene depth-a
Translucency Scene color-a (za blending pozadine), Depth buffer-a
Post-Processing Svega prethodnog — scene color, depth, velocity, itd.

Ako biste pokušali da računate osvetljenje pre nego što imate G-Buffer, nemate podatke o površinama. Ako biste pokušali da renderujete transparentne objekte pre neprozirnih, nemate pozadinu za blending. Ako biste pokušali post-processing pre osvetljenja, obrađivali biste neosvetljenu sliku.

Svaki pass proizvodi podatke koje sledeći pass konzumira. Ovo je pipeline u najčistijem smislu te reči.


29.3 Base Pass — Srce Deferred Renderinga

Base pass je korak u kome se sva neprozirna geometrija scene renderuje i njeni materijal atributi zapisuju u G-Buffer. Ovo je najskuplji korak po pitanju geometrije i materijal evaluacije, pa hajde da ga razumemo detaljno.

29.3.1 Šta se tačno dešava u Base Pass-u

Kada UE5 izvršava base pass, dešava se sledeće za svaki vidljivi objekat:

1. Vertex Processing

Vertex shader transformiše vertekse mesh-a iz object-space u clip-space (koristeći World, View, i Projection matrice). Za skinned mesh-eve (karakteri sa skeletalnom animacijom), vertex shader takođe primenjuje bone transformacije. Za mesh-eve sa World Position Offset u materijalu, ta deformacija se takođe primenjuje ovde.

2. Rasterizacija

GPU rasterizator konvertuje transformisane trouglove u fragmente (kandidate za piksele). Za svaki fragment se generiše barycentrička interpolacija vertex atributa (UV koordinate, normale, tangent vektori, itd.).

3. Early-Z Test

Pre pokretanja pixel shader-a, GPU proverava depth buffer (koji je popunjen u depth prepass-u). Ako fragment ne prolazi depth test (tj. iza je nečeg bližeg), pixel shader se uopšte ne pokreće. Ovo je ogromna ušteda, jer je pixel shader najskuplji deo base pass-a.

4. Pixel Shader — Materijal Evaluacija

Za svaki fragment koji prođe Early-Z test, pixel shader evaluira kompletnu materijal logiku:

5. G-Buffer Write

Konačni surface atributi se zapisuju u G-Buffer teksture putem Multiple Render Targets (MRT) — mogućnosti modernih GPU-ova da pišu u više tekstura istovremeno iz jednog pixel shader-a. UE5 tipično piše u 3-4 G-Buffer teksture plus depth/stencil u jednom pass-u.

29.3.2 Materijal evaluacija — Šta se zapravo računa

Hajde da budemo konkretni o tome šta pixel shader radi u base pass-u. Za standardni PBR materijal u UE5, shader evaluira:

// Konceptualni pseudokod UE5 base pass pixel shader-a

// 1. Uzorkuj teksture
float3 BaseColor = SampleTexture(BaseColorMap, UV);
float3 NormalTS = SampleTexture(NormalMap, UV);        // Tangent-space normala
float  Metallic = SampleTexture(MetallicMap, UV).r;
float  Roughness = SampleTexture(RoughnessMap, UV).r;
float  Specular = SampleTexture(SpecularMap, UV).r;
float  AO = SampleTexture(AOMap, UV).r;

// 2. Transformiši normalu iz tangent-space u world-space
float3 NormalWS = TangentToWorld(NormalTS, VertexNormal, VertexTangent);

// 3. Primeni materijal modifikacije (npr. detail textures, vertex color blending)
BaseColor *= VertexColor.rgb;
Roughness = lerp(Roughness, 1.0, WetnessAmount);

// 4. Zapiši u G-Buffer — BEZ RAČUNANJA OSVETLJENJA!
GBufferA = float4(EncodeNormal(NormalWS), PerObjectData);
GBufferB = float4(Metallic, Specular, Roughness, ShadingModelID);
GBufferC = float4(BaseColor, AO);
// Velocity buffer za TAA/motion blur
VelocityBuffer = ComputeVelocity(CurrentPos, PreviousPos);

Primetite da nigde nema CalculateLighting() ili EvaluateLight() poziva. Osvetljenje se ne računa u base pass-u. Ovo je suština deferred renderinga.

29.3.3 Nanite i Base Pass

Sa Nanite-om, situacija je malo drugačija. Nanite mesh-evi ne prolaze kroz tradicionalni hardverski rasterization pipeline. Umesto toga:

  1. Nanite softverski rasterizer na GPU-u crta micro-cluster-e (grupe od ~128 trouglova) direktno u visibility buffer
  2. Visibility buffer sadrži informaciju o tome koji trougao, kog cluster-a, kog mesh-a je vidljiv na svakom pikselu
  3. Materijal evaluation pass čita visibility buffer, rekonstruiše surface atribute (interpolacijom vertex podataka), i piše u G-Buffer

Konačni rezultat je isti — popunjen G-Buffer sa svim surface atributima — ali put do njega je fundamentalno drugačiji i mnogo efikasaniji za mesh-eve sa velikim brojem trouglova.

29.3.4 Performansne implikacije Base Pass-a

Base pass je često jedan od najskupljih render pass-ova. Evo šta utiče na njegovu cenu:

  1. Broj vidljivih trouglova: Više geometrije = više vertex processing-a i rasterizacije. Nanite ovo dramatično optimizuje za statičnu geometriju.

  2. Kompleksnost materijala: Materijali sa mnogo tekstura, složenim grafovima, i mnogo instrukcija u pixel shader-u su skuplji. Svaki vidljivi piksel mora da evaluira kompletnu materijal logiku.

  3. Overdraw: Pikseli koji se nacrtaju više puta (jer se objekti preklapaju) troše resurse uzalud. Depth prepass ublaži ovo, ali ne potpuno — svaki fragment i dalje prolazi kroz vertex shader i rasterizaciju pre nego što Early-Z može da ga odbaci.

  4. Texture bandwidth: Uzorkovanje tekstura je memorijski intenzivna operacija. Materijali sa mnogo tekstura (posebno velikih rezolucija) mogu da zagušite memorijski bandwidth GPU-a.

  5. MRT write bandwidth: Pisanje u 3-4 G-Buffer teksture istovremeno zahteva značajan write bandwidth. Na rezoluciji 4K, ovo postaje ozbiljno opterećenje.


29.4 G-Buffer — Anatomija geometrijske memorije

G-Buffer je srce deferred renderinga. To je skup tekstura pune rezolucije ekrana koje čuvaju sve informacije o vidljivim površinama — dovoljno podataka da se osvetljenje može izračunati bez ikakve reference na originalnu geometriju.

Hajde da detaljno razmotrimo šta se tačno čuva u svakom kanalu G-Buffer-a u UE5.

29.4.1 Struktura G-Buffer-a u UE5

UE5 koristi nekoliko G-Buffer tekstura, svaka sa specifičnom namenom. Evo detaljnog pregleda:

G-Buffer A — Normale i Per-Object podaci

Kanal Sadržaj Format
R World Normal X 10 bit
G World Normal Y 10 bit
B World Normal Z 10 bit
A Per-Object Data 2 bit

World Normal (RGB): Normala površine u world-space-u, izražena kao trodimenzionalni vektor. Ovo je kritičan podatak za osvetljenje — normala određuje pod kojim uglom svetlost pogađa površinu, što direktno utiče na difuzno i spekularno osvetljenje.

UE5 koristi octahedron encoding za pakovanje 3D normale u 2 kanala (što oslobađa prostor), ili standardno 3-kanalno kodiranje zavisno od konfiguracije. Preciznost kodiranja je važna — gubitak preciznosti u normalama dovodi do vidljivih artefakata u osvetljenju, posebno na glatkim površinama.

Per-Object Data (A): Dva bita za podatke specifične za objekat. Ovo može da uključuje selektivne flag-ove koje lighting pass koristi za posebno ponašanje.

Format: Tipično RGBA8 ili RGB10A2 (10 bita po kanalu za RGB, 2 bita za A). RGB10A2 daje bolju preciznost za normale, što smanjuje artefakte.

G-Buffer B — PBR Parametri i Shading Model

Kanal Sadržaj Format
R Metallic 8 bit
G Specular 8 bit
B Roughness 8 bit
A Shading Model ID + Selective Output Mask 8 bit

Metallic (R): Stepen metalnosti površine, od 0.0 (dielektrik — drvo, plastika, kamen) do 1.0 (metal — zlato, srebro, aluminijum). Ovaj parametar fundamentalno menja kako se površina ponaša pod svetlom: metali reflektuju svetlost bojom svojeg base color-a, dok dielektrici reflektuju belu svetlost.

Specular (G): Kontroliše jačinu Fresnel refleksije za dielektrične površine. Podrazumevana vrednost je 0.5 (što odgovara IOR od ~1.5, tipičnom za većinu dielektrika). Retko se menja od podrazumevane vrednosti u praksi.

Roughness (B): Hrapavost površine, od 0.0 (savršeno glatka — ogledalo) do 1.0 (potpuno hrapava — mat). Ovaj parametar kontroliše koliko je specular highlight raspršen — glatke površine imaju oštre, fokusirane refleksije, dok hrapave imaju široke, difuzne.

Shading Model ID (A, gornji bitovi): Identifikator koji govori lighting pass-u koji shading model da koristi za ovaj piksel. Ovo je ključni mehanizam koji omogućava UE5 da podrži više shading modela u deferred pipeline-u:

ID Shading Model
0 Unlit (neosvetljen)
1 Default Lit (standardni PBR)
2 Subsurface
3 Preintegrated Skin
4 Clear Coat
5 Subsurface Profile
6 Two Sided Foliage
7 Hair
8 Cloth
9 Eye
10 SingleLayerWater
11 Thin Translucent
12 Strata

Lighting pass čita ovaj ID i bira odgovarajuću granu lighting koda. Ovo je elegantan način da se podrži raznolikost shading modela unutar ograničenja deferred renderinga, ali dolazi sa cenom — lighting shader mora da sadrži sve lighting modele i da dinamički bira koji da koristi, što povećava kompleksnost shader-a.

G-Buffer C — Base Color i Ambient Occlusion

Kanal Sadržaj Format
R Base Color R 8 bit
G Base Color G 8 bit
B Base Color B 8 bit
A AO / GI podaci 8 bit

Base Color (RGB): Osnovna boja površine — boja teksture bez ikakvog osvetljenja. Za metale, ovo je boja refleksije. Za dielektrike, ovo je difuzna boja (albedo).

AO / GI Data (A): Ambient Occlusion vrednost za materijal (ne treba ga mešati sa SSAO koji se računa u post-processingu). Ovo je "baked" AO iz teksture materijala koji daje dodatne detalje senčenja u šupljinama i naborima površine. U nekim konfiguracijama, ovaj kanal se koristi i za skladištenje podataka za Lumen GI.

Format: RGBA8 (8 bita po kanalu, 32 bita ukupno).

Velocity Buffer — Vektori pokreta

Kanal Sadržaj Format
R Velocity X 16 bit float
G Velocity Y 16 bit float

Motion Vectors (RG): Za svaki piksel, velocity buffer čuva koliko se taj piksel pomerio od prethodnog do trenutnog kadra, izraženo u screen-space koordinatama. Ovo se koristi za:

Format: RG16F (dva kanala po 16-bit float).

Velocity se izračunava u base pass-u poređenjem trenutne pozicije piksela (nakon transformacije sa trenutnim World-View-Projection matricama) sa pozicijom istog piksela u prethodnom kadru (koristeći prethodne matrice). Za objekte koji se kreću (animirani karakteri, pokretne platforme), velocity buffer čuva per-pixel velocity koji uključuje i kretanje kamere i kretanje objekta.

Custom Depth i Custom Stencil

Ovo nisu deo G-Buffer-a u strogom smislu, ali se generišu u sličnoj fazi i koriste za specifične efekte:

Custom Depth: Opcioni depth buffer koji se može koristiti u post-processing materijalima za efekte kao što su outline rendering, X-ray vizija, ili selekcija objekata. Objekti koji pišu u custom depth moraju imati uključenu opciju "Render Custom Depth Pass" u svojim podešavanjima.

Custom Stencil: 8-bitna stencil vrednost po pikselu koja se može čitati u post-processing materijalima. Korisno za kategorijsku selekciju (npr. "svi neprijatelji imaju stencil vrednost 1, svi saveznici vrednost 2").

29.4.2 Memorijska cena G-Buffer-a

G-Buffer zauzima značajnu količinu video memorije. Hajde da izračunamo:

Veličina jednog piksela u G-Buffer-u:

Buffer Format Bajti po pikselu
G-Buffer A (Normale) RGB10A2 4
G-Buffer B (PBR params) RGBA8 4
G-Buffer C (Base Color) RGBA8 4
Depth/Stencil D24S8 ili D32F 4
Velocity RG16F 4
Ukupno 20 bajti/piksel

Na rezoluciji 1920×1080 (Full HD):

1920 × 1080 = 2,073,600 piksela
2,073,600 × 20 bajti = 41,472,000 bajti ≈ 39.5 MB

Na rezoluciji 2560×1440 (QHD / 2K):

2560 × 1440 = 3,686,400 piksela
3,686,400 × 20 bajti = 73,728,000 bajti ≈ 70.3 MB

Na rezoluciji 3840×2160 (4K / UHD):

3840 × 2160 = 8,294,400 piksela
8,294,400 × 20 bajti = 165,888,000 bajti ≈ 158.2 MB

Ovo su samo osnovni G-Buffer-i. U praksi, UE5 može da koristi dodatne buffer-e zavisno od konfiguracije (npr. subsurface scattering buffer, clear coat buffer, Lumen radiance cache, itd.), što može da poveća ukupnu memorijsku potrošnju za 30-50%.

Sa uključenim Lumen, TSR, i virtualnim shadow map-ovima na 4K rezoluciji, ukupna memorijska potrošnja render target-ova može lako da pređe 500 MB — čak i 1 GB. Ovo je jedan od razloga zašto moderne igre zahtevaju GPU-ove sa 8+ GB video memorije.

29.4.3 Zašto je kodiranje bitno

Primetite da je G-Buffer veoma "zbijen" — svaka informacija je kompresovana u minimum kanala i bitova. Zašto?

Memorijski bandwidth je kritičan resurs. Svaki bajt u G-Buffer-u mora da se:

  1. Zapiše u base pass-u (za svaki vidljivi piksel)
  2. Pročita u lighting pass-u (za svaki piksel na ekranu)
  3. Potencijalno pročita ponovo u Lumen, SSAO, SSR, i drugim pass-ovima

Na 4K rezoluciji, sa 20 bajti po pikselu, samo jedno čitanje G-Buffer-a zahteva čitanje ~158 MB podataka. Lighting pass koji evaluira 10 svetala čita G-Buffer 10 puta — to je 1.58 GB memorijskog saobraćaja samo za čitanje G-Buffer-a!

Zato je bitno minimizovati broj bafera i veličinu svakog bafera:

Svaki ušteđeni bajt po pikselu, pomnožen sa milionima piksela i brojem čitanja, rezultira značajnom uštedom bandwidth-a.

29.4.4 Vizualizacija G-Buffer-a u UE5 Editoru

Možete vizualizovati G-Buffer u UE5 editoru koristeći Buffer Visualization mode:

  1. U viewport-u, kliknite na padajući meni pored "Lit"
  2. Izaberite "Buffer Visualization"
  3. Odatle možete izabrati:
    • Overview: Svi G-Buffer-i prikazani kao mali preview-i
    • Base Color: Samo base color kanal
    • World Normal: Normale kodirane kao boje (XYZ → RGB)
    • Roughness: Grayscale prikaz hrapavosti
    • Metallic: Grayscale prikaz metalnosti
    • Specular: Grayscale prikaz spekularne vrednosti
    • Ambient Occlusion: Grayscale prikaz AO
    • Scene Depth: Depth buffer vizualizacija

Ovo je izuzetno korisno za debagovanje materijala — ako nešto izgleda pogrešno u finalnom renderu, vizualizacija G-Buffer-a vam omogućava da vidite da li je problem u materijalu (pogrešne vrednosti u G-Buffer-u) ili u osvetljenju (pogrešno izračunavanje u lighting pass-u).

Takođe, konzolna komanda vis (npr. vis GBufferA) može da prikaže specifičan G-Buffer kanal u runtime-u, što je korisno za profajliranje na target hardveru.


29.5 Lighting Pass — Gde se svetlo rađa

Lighting pass je korak u kome se svi podaci iz G-Buffer-a kombinuju sa informacijama o svetlima da bi se proizvela finalna osvetljena slika. Ovo je najinteligentniji deo deferred renderinga i zaslužuje detaljno razumevanje.

29.5.1 Osnovan princip

Konceptualno, lighting pass je jednostavan:

Za svaki piksel na ekranu:
    Pročitaj Normal, BaseColor, Metallic, Roughness, Specular iz G-Buffer-a
    Pročitaj Depth iz depth buffer-a
    Rekonstruiši World Position iz depth-a i screen koordinata

    LitColor = float3(0, 0, 0)  // Počni od crnog

    Za svako svetlo koje utiče na ovaj piksel:
        ShadowFactor = EvaluateShadow(piksel, svetlo)
        LightContribution = CalculatePBR(
            Normal, BaseColor, Metallic, Roughness, Specular,
            LightDirection, LightColor, LightIntensity,
            ShadowFactor
        )
        LitColor += LightContribution

    LitColor += AmbientLight * AO  // Ambient / GI doprinos
    OutputColor = LitColor

Ali u praksi, naivna implementacija "za svaki piksel, za svako svetlo" je previše spora za scene sa velikim brojem svetala. Tu ulazi light culling.

29.5.2 Light Culling — Tile-Based i Cluster-Based

Light culling je optimizacija koja osigurava da se za svaki piksel evaluiraju samo svetla koja zaista utiču na njega. Postoje dva glavna pristupa:

Tile-Based Light Culling

Ekran se deli na pravougaone tile-ove (tipično 16×16 ili 32×32 piksela). Za svaki tile:

  1. Izračunaj bounding box tile-a u world-space-u (koristeći min/max depth piksela u tile-u)
  2. Testiraj koji light volume-i (sfere za point lights, konusi za spot lights) presecaju ovaj bounding box
  3. Napravi listu svetala koja utiču na ovaj tile
  4. U lighting pass-u, za piksele u ovom tile-u, evaluiraj samo svetla sa liste

Ovo dramatično smanjuje broj evaluacija svetala. U sceni sa 100 svetala, svaki tile tipično ima listu od samo 5-15 relevantnih svetala.

Primer: Ekran 1920×1080, tile veličina 16×16
Broj tile-ova: (1920/16) × (1080/16) = 120 × 67.5 ≈ 8,100 tile-ova

Bez light culling-a: 2M piksela × 100 svetala = 200M evaluacija
Sa tile-based culling-om: 2M piksela × ~10 svetala (prosečno) = 20M evaluacija
Ušteda: ~10x manje posla!

Cluster-Based Light Culling

Cluster-based pristup je evolucija tile-based pristupa. Umesto 2D tile-ova, ekran se deli u 3D clustere — tile-ovi se dodatno dele po dubini (depth slicing), formirajući 3D grid. Ovo daje preciznije rezultate jer tile sa velikim rasponom dubina (npr. pod ispred kamere koji se pruža do horizonta) može da "vidi" mnoga svetla koja zapravo utiču samo na deo tog dubinskog raspona.

Tile-based (2D):
    Tile pokriva dubinu od 1m do 100m
    → Sva svetla u tom rasponu su na listi (mnogo nepotrebnih)

Cluster-based (3D):
    Tile je podeljen na cluster-e po dubini:
    Cluster 1: 1m - 5m   → samo bliska svetla
    Cluster 2: 5m - 20m  → samo srednja svetla
    Cluster 3: 20m - 100m → samo daleka svetla
    → Svaki cluster ima mnogo kraću listu svetala

29.5.3 Tiled Deferred u UE5

UE5 koristi varijaciju tiled deferred shading pristupa za svoj lighting pass. Evo kako to funkcioniše:

  1. Light culling compute shader: Compute shader prolazi kroz sve tile-ove ekrana i za svaki tile formira listu svetala koja ga pogađaju. Rezultat se čuva u structured buffer-u na GPU-u.

  2. Lighting compute shader: Za svaki piksel, shader:

    • Identifikuje kom tile-u piksel pripada
    • Čita listu svetala za taj tile
    • Čita G-Buffer podatke za piksel
    • Evaluira lighting jednačinu za svako svetlo sa liste
    • Akumulira rezultate
  3. Specijalna svetla: Neka svetla (posebno directional light — sunce) se obrađuju posebno jer utiču na sve piksele. Za directional light, UE5 koristi full-screen pass umesto tiled pristupa jer bi tile culling bio besmislen (svaki tile bi imao sunce na listi).

  4. Shadow evaluation: Za svako svetlo sa senkama, shader uzorkuje shadow map i izračunava shadow factor. Ovo je često najskuplji deo lighting pass-a, posebno za shadow map-ove sa filtriranjem (soft shadows).

29.5.4 Lighting jednačina — PBR u praksi

U lighting pass-u, UE5 koristi Physically Based Rendering (PBR) model zasnovan na Cook-Torrance BRDF-u. Kompletna lighting jednačina za jedan piksel i jedno svetlo izgleda ovako:

// Pojednostavljena PBR lighting jednačina

// Ulazni podaci (iz G-Buffer-a)
N = WorldNormal          // Normala površine
V = normalize(CameraPos - WorldPos)  // Vektor ka kameri
L = normalize(LightPos - WorldPos)   // Vektor ka svetlu
H = normalize(V + L)                 // Half vektor

// PBR parametri
albedo = BaseColor
metal = Metallic
rough = Roughness
spec = Specular

// Fresnel (Schlick approximation)
F0 = lerp(0.04 * spec, albedo, metal)
F = F0 + (1 - F0) * pow(1 - dot(H, V), 5)

// Distribution (GGX/Trowbridge-Reitz)
alpha = rough * rough
D = alpha^2 / (PI * (dot(N,H)^2 * (alpha^2 - 1) + 1)^2)

// Geometry (Smith GGX)
k = (rough + 1)^2 / 8
G1_V = dot(N,V) / (dot(N,V) * (1-k) + k)
G1_L = dot(N,L) / (dot(N,L) * (1-k) + k)
G = G1_V * G1_L

// Specular BRDF
specularBRDF = (D * F * G) / (4 * dot(N,V) * dot(N,L))

// Diffuse BRDF (Lambert)
kD = (1 - F) * (1 - metal)
diffuseBRDF = kD * albedo / PI

// Konačan doprinos svetla
NdotL = max(dot(N, L), 0)
radiance = LightColor * LightIntensity * Attenuation(distance)
contribution = (diffuseBRDF + specularBRDF) * radiance * NdotL * ShadowFactor

Svaka od ovih komponenti služi specifičnoj fizičkoj svrsi:

29.5.5 Deferred Shading vs Deferred Lighting

Vredi napomenuti da postoje dve varijacije deferred pristupa:

Deferred Shading (ono što UE5 koristi):

Deferred Lighting (alternativni pristup):

UE5 koristi deferred shading jer je fleksibilniji i eliminiše potrebu za ponovnim renderovanjem geometrije, uprkos većoj memorijskoj potrošnji G-Buffer-a.

29.5.6 Kako UE5 hendluje više shading modela

Jedan od izazova deferred renderinga je podrška za više shading modela — različite materijale koji zahtevaju različite lighting jednačine (npr. koža vs. metal vs. tkanina vs. kosa).

UE5 rešava ovo elegantno koristeći Shading Model ID u G-Buffer-u B (alfa kanal). U lighting pass-u:

// Konceptualni pseudokod UE5 lighting shader-a

uint ShadingModelID = GBufferB.a >> 4;  // Gornja 4 bita

switch (ShadingModelID)
{
    case SHADINGMODELID_DEFAULT_LIT:
        // Standardna PBR jednačina
        color = StandardPBR(GBufferData, LightData);
        break;

    case SHADINGMODELID_SUBSURFACE:
        // Subsurface scattering — svetlost prolazi kroz materijal
        color = SubsurfaceLighting(GBufferData, LightData);
        break;

    case SHADINGMODELID_CLEAR_COAT:
        // Dva sloja — clear coat (lak) preko baznog materijala
        color = ClearCoatLighting(GBufferData, LightData);
        break;

    case SHADINGMODELID_HAIR:
        // Anizotropna refleksija za vlasi kose (Marschner model)
        color = HairLighting(GBufferData, LightData);
        break;

    case SHADINGMODELID_CLOTH:
        // Tkanina — šin model sa difuznim retrorefleksijama
        color = ClothLighting(GBufferData, LightData);
        break;

    case SHADINGMODELID_EYE:
        // Specijalizovani model za realistične oči
        color = EyeLighting(GBufferData, LightData);
        break;

    // ... ostali modeli
}

Prednost ovog pristupa: Raznovrsni materijali koegzistiraju u istoj sceni bez komplikovanja base pass-a. Base pass uvek piše iste G-Buffer kanale, samo sa različitim Shading Model ID.

Mana: Lighting shader postaje velik i sadrži branching, što može da smanji GPU efikasnost (divergentni thread-ovi u istom warp/wavefront-u mogu da izvršavaju različite grane). U praksi, ovo obično nije veliki problem jer su pikseli istog shading modela uglavnom grupisani na ekranu (npr. svi pikseli jednog karaktera koriste isti model).

Dodatna mana: Specijalizovani shading modeli ponekad zahtevaju dodatne podatke koji se ne uklapaju u standardni G-Buffer layout. Na primer, subsurface scattering zahteva informaciju o boji rasipanja i dubini prodiranja svetlosti. UE5 rešava ovo "prenamenom" postojećih G-Buffer kanala — za subsurface materijale, specular kanal može da čuva subsurface opacity umesto standardne spekularne vrednosti. Ovo funkcioniše jer je lighting shader svestan shading modela i zna kako da interpretira podatke.


29.6 Deferred Shading — Kompromisi u praksi

Do sada smo se fokusirali na to kako deferred rendering funkcioniše. Sada hajde da detaljno sagledamo kompromise — prednosti i mane koje ovaj pristup donosi u realnom UE5 projektu.

29.6.1 Prednosti u praksi

Razdvojena geometrija i osvetljenje

Ovo je možda najvažnija praktična prednost. Razmislite o implikacijama:

Ova separacija značajno pojednostavljuje razvoj i debagovanje.

Efikasno rukovanje velikim brojem svetala

Evo tipičnog primera. Zamislite unutrašnjost kafića sa:

U forward renderingu, svaki piksel svakog objekta bi morao da evaluira svih 50 svetala — kompletnu PBR jednačinu za svako. Sa tile-based culling-om, svaki piksel u deferred renderingu evaluira samo svetla koja zaista utiču na njega — tipično 3-8 svetala po pikselu.

Screen-space efekti su "besplatni"

Budući da G-Buffer sadrži kompletne informacije o površini za svaki piksel, screen-space efekti kao SSAO (Screen-Space Ambient Occlusion), SSR (Screen-Space Reflections), i contact shadows mogu da se implementiraju kao jednostavni post-processing pass-ovi koji čitaju iz G-Buffer-a.

29.6.2 Mane u praksi

Memorijski bandwidth

Ovo je najveće praktično ograničenje deferred renderinga u UE5. Na 4K rezoluciji:

Ukupan memorijski saobraćaj za G-Buffer može lako da premaši 1-2 GB po kadru. Na 60 FPS, to je 60-120 GB/s samo za G-Buffer — značajan deo ukupnog memorijskog bandwidth-a GPU-a.

Na mobilnim GPU-ovima, gde je bandwidth mnogo niži, ovo postaje prohibitivno — zato mobile renderer u UE5 koristi forward rendering.

Nema hardverskog MSAA

Ovo je posebno vidljiv problem na oštrim ivicama geometrije. TAA (koji UE5 koristi kao zamenu) može da proizvede artefakte:

TSR (Temporal Super Resolution) u UE5 značajno poboljšava kvalitet u poređenju sa starijim TAA implementacijama, ali hardverski MSAA i dalje daje "čistiju" sliku na ivicama — posebno za sadržaj koji nije u pokretu.

Ograničenja shading modela

Svaki shading model mora da pakuje sve potrebne podatke u fiksne G-Buffer kanale. Ovo znači:

U praksi, ovo retko postaje problem jer UE5 nudi dovoljan broj ugrađenih shading modela za većinu slučajeva, ali predstavlja fundamentalno ograničenje arhitekture.

Transparentni objekti

Kao što smo već pomenuli, transparentni objekti ne mogu da koriste deferred pipeline. Moraju da se renderuju forward pristupom, što znači:

29.6.3 Memory bandwidth optimizacije u UE5

UE5 primenjuje nekoliko strategija da ublaži bandwidth problem:

  1. G-Buffer kompresija: Pakovanje podataka u minimum kanala i bitova (octahedron encoding za normale, bit-packing za shading model ID, itd.)

  2. Bandwidth-svestan rendering: Nanite-ov visibility buffer pristup smanjuje bandwidth jer u prvom pass-u piše samo mali visibility buffer umesto kompletnog G-Buffer-a. Materijal evaluacija i G-Buffer pisanje se dešavaju tek u drugom pass-u, samo za vidljive piksele.

  3. Tile-based GPU arhitektura: Na mobilnim GPU-ovima (koji koriste tile-based architecturu), UE5 mobile renderer koristi on-chip tile memory za G-Buffer podatke, izbegavajući skupe main memory pristupe. Ali ovo funkcioniše samo sa forward rendering putom.

  4. Selectivni G-Buffer kanali: UE5 može da onemogući neke G-Buffer kanale koji nisu potrebni za projekat (npr. velocity buffer se može isključiti ako ne koristite TAA ili motion blur).


29.7 Forward Shading Put u UE5

Iako je deferred rendering podrazumevani i najčešće korišćeni pristup u UE5, forward rendering put postoji i služi važnim svrhama. Hajde da ga detaljno razmotrimo.

29.7.1 Kada se koristi Forward Rendering

UE5 nudi forward rendering put za sledeće scenarije:

Mobilni rendering

Mobilni uređaji (iOS, Android) koriste GPU-ove sa tile-based deferred rendering (TBDR) arhitekturom (Apple GPU, Mali, Adreno). Zanimljivo je da ovi GPU-ovi interno koriste "deferred" pristup na hardverskom nivou, ali to je drugačiji koncept od softverskog deferred renderinga koji smo opisali gore.

Mobilni GPU-ovi imaju:

Forward rendering na mobilnom koristi prednosti TBDR arhitekture — sve se radi unutar tile buffer-a bez skupog pisanja u main memory. Deferred rendering bi zahtevao pisanje G-Buffer-a u main memory (jer G-Buffer ne staje u mali tile buffer), što bi bilo previše sporo na mobilnom bandwidth-u.

VR (Virtual Reality)

VR projekti često preferiraju forward rendering jer:

  1. MSAA podrška: Hardverski MSAA je čistiji od TAA za VR. TAA artefakti (ghosting, blurriness) su posebno neprijatni u VR-u jer:

    • Korisnik primećuje zamućenje mnogo lakše u HMD-u nego na monitoru
    • Ghosting izaziva nelagodu i može doprineti motion sickness-u
    • Subpixel detalji su kritični za čitljivost teksta i UI elemenata u VR-u
  2. Niži latency: Forward rendering ima potencijalno nižu latenciju jer ima manje render pass-ova i manje čitanja/pisanja u memoriju.

  3. Manji memorijski footprint: VR renderuje dva puta (jednom za svako oko), pa ušteda na G-Buffer-u se duplira.

Specifični stilovi renderinga

Neki projekti koji koriste Non-Photorealistic Rendering (NPR) ili stilizovane vizuale mogu da preferiraju forward rendering jer im nije potreban veliki broj dinamičkih svetala i žele čistiju sliku sa MSAA.

29.7.2 Aktivacija Forward Renderinga u UE5

Forward rendering se aktivira u Project Settings:

  1. Edit → Project Settings → Rendering
  2. Forward Shading: Uključite ovu opciju
  3. Restartujte editor

Nakon aktivacije, UE5 koristi forward rendering za neprozirne objekte (umesto deferred). G-Buffer se ne generiše na uobičajen način, i MSAA postaje dostupan.

Za mobilno renderovanje, forward rendering se automatski koristi kada je target platforma Mobile.

29.7.3 Clustered Forward u UE5

Ključna razlika između "naivnog" forward renderinga i UE5 implementacije je clustered forward light culling. Bez ove optimizacije, forward rendering bi bio praktično neupotrebljiv sa više od 5-10 svetala.

Clustered forward u UE5 funkcioniše ovako:

  1. Prostor kamere se deli u 3D grid cluster-a (kombinacija screen-space tile-ova i depth slicing-a)

  2. Compute shader prolazi kroz sva svetla u sceni i za svaki cluster određuje koja svetla ga pogađaju. Rezultat se čuva u light grid buffer-u.

  3. Forward pixel shader, za svaki piksel:

    • Identifikuje kom cluster-u piksel pripada (na osnovu screen pozicije i depth-a)
    • Čita listu svetala za taj cluster iz light grid buffer-a
    • Evaluira lighting samo za svetla sa liste
// Konceptualni pseudokod clustered forward u UE5

// U compute shader-u (jednom po kadru):
for each cluster in grid:
    cluster.lightList = []
    for each light in scene:
        if (light.boundingSphere intersects cluster.bounds):
            cluster.lightList.append(light)
    StoreLightList(cluster.id, cluster.lightList)

// U forward pixel shader-u (za svaki piksel):
float3 worldPos = ReconstructWorldPos(screenUV, depth)
int3 clusterID = WorldPosToClusterID(worldPos)
LightList lights = LoadLightList(clusterID)

float3 color = float3(0,0,0)
for each light in lights:
    color += EvaluatePBR(surfaceData, light)

output = color

Ovo omogućava forward renderingu da efikasno rukuje desetinama svetala (mada i dalje ne tako efikasno kao deferred za stotine svetala).

29.7.4 Forward vs Deferred — Tabelarno poređenje

Aspekt Deferred (Default) Forward
Anti-aliasing TAA/TSR (softverski) MSAA (hardverski)
Broj svetala Stotine, efikasno Desetine, umereno efikasno
G-Buffer memorija Da (~40-160 MB) Ne
Memorijski bandwidth Visok Niži
Shading modeli Svi podržani Ograničen skup
Transparentnost Forward pass (hibridno) Nativno
Screen-space efekti Da (koriste G-Buffer) Ograničeno
Lumen GI Potpuno podržan Ograničeno podržan
Nanite Potpuno podržan Ograničena podrška
Mobilno Ne Da
VR Da (ali TAA artefakti) Da (sa MSAA)
Compute shader zavisnost Da Manje
Overdraw cena Niska (Early-Z + jeftin base pass) Visoka (kompletan lighting po pikselu)

29.7.5 Ograničenja Forward Renderinga u UE5

Kada aktivirate forward rendering u UE5, gubite pristup nekim mogućnostima:

  1. Lumen: Lumen GI i Reflections su dizajnirani za deferred pipeline i imaju ograničenu ili nikakvu podršku u forward modu. Za forward rendering, koristite baked lighting (Lightmass) ili screen-space metode.

  2. Nanite: Nanite je duboko integrisan sa deferred rendering putom (visibility buffer → G-Buffer). Forward rendering ima ograničenu Nanite podršku.

  3. Screen-Space efekti: SSAO, SSR, i slični efekti koji zavise od G-Buffer-a nisu dostupni ili su ograničeni.

  4. Broj render target-a: Forward shader mora da čita informacije o svetlima i računa osvetljenje u istom shader-u, što povećava register pressure i može da smanji GPU efikasnost.

  5. Shading model raznolikost: Svaki forward shader mora da uključi kompletnu lighting logiku, što povećava shader kompleksnost i kompilaciono vreme.

29.7.6 Hibridni pristup za transparentne objekte

Čak i u deferred rendering modu, UE5 koristi forward rendering za transparentne objekte. Ovo je "hibridni" pristup koji kombinuje najbolje od oba sveta:

Ovaj hibridni model znači da su transparentni objekti uvek nešto skuplji za renderovanje od neprozirnih, jer moraju da evaluiraju kompletnu lighting logiku za svaki piksel, za svako svetlo. Ovo je jedan od razloga zašto je "previše transparentnih objekata" čest izvor performansnih problema u UE5 projektima — ne samo zbog blending overhead-a, već i zbog forward lighting cene.


29.8 Napredne teme i dublje razumevanje

29.8.1 Stencil Buffer u deferred pipeline-u

UE5 koristi stencil buffer (deo depth/stencil teksture) za nekoliko svrha u deferred pipeline-u:

  1. Markiranje piksela koji zahtevaju lighting: Pikseli neba (koji nemaju geometriju i ne treba da se osvetle) se markiraju u stencilu tako da lighting pass može da ih preskoči.

  2. Razdvajanje shading modela: Stencil se koristi kao dodatni mehanizam za razdvajanje piksela različitih shading modela, omogućavajući lighting shader-u da efikasnije procesira piksele istog tipa.

  3. Custom stencil operacije: Korisnički definisane stencil vrednosti za post-processing efekte (outline rendering, selektivni bloom, itd.).

29.8.2 Async Compute i preklapanje pass-ova

Moderni GPU-ovi mogu da izvršavaju compute shader-e paralelno sa graphics shader-ima koristeći async compute. UE5 koristi ovo za preklapanje nezavisnih pass-ova:

Ovo je transparentno za korisnika — UE5 RDG (Render Dependency Graph) automatski identifikuje nezavisne pass-ove i raspoređuje ih za paralelno izvršavanje.

29.8.3 Render Dependency Graph (RDG)

UE5 koristi Render Dependency Graph (ranije poznat kao "Render Graph" ili "Frame Graph") za organizaciju render pass-ova. RDG je directed acyclic graph (DAG) koji opisuje:

Na osnovu ovog grafa, RDG:

  1. Automatski određuje redosled izvršavanja pass-ova
  2. Identifikuje pass-ove koji mogu da se izvršavaju paralelno
  3. Upravlja životnim ciklusom resursa (alocira ih tek kada su potrebni, dealocira kad više nisu)
  4. Postavlja memory barriers između zavisnih pass-ova

Ovo je mnogo efikasnije od ručnog upravljanja redosledom pass-ova i omogućava engine-u da optimizuje pipeline za specifičan GPU.

29.8.4 Debug i profajliranje rendering pipeline-a

UE5 nudi nekoliko alata za razumevanje i profajliranje rendering pipeline-a:

GPU Profiler (ProfileGPU komanda ili Ctrl+Shift+,):

RenderDoc integracija:

Buffer Visualization (opisano u sekciji 29.4.4):

Stat komande:

29.8.5 Substrate (Strata) — Budućnost shading modela u UE5

UE5 uvodi Substrate (ranije poznat kao Strata) — novi shading model sistem koji pokušava da prevaziđe ograničenja fixed shading modela u deferred renderingu.

Umesto fiksnog skupa shading modela sa predefinisanim G-Buffer layout-om, Substrate omogućava:

Substrate je u vreme pisanja ove knjige još uvek u eksperimentalnoj fazi, ali predstavlja pravac u kome se UE5 rendering arhitektura razvija. On adresira jedno od fundamentalnih ograničenja tradicionalnog deferred renderinga — rigidnost G-Buffer formata.


29.9 Praktični saveti za rad sa UE5 Rendering arhitekturom

29.9.1 Optimizacija Base Pass-a

  1. Smanjite kompleksnost materijala gde je moguće: Svaka dodatna tekstura i svaka matematička operacija u materijalu povećava cenu base pass-a. Koristite Material Quality Levels za različite LOD nivoe materijala.

  2. Koristite Material Instances: Material Instances omogućavaju promenu parametara bez kreiranja novog shader-a. Ovo smanjuje broj shader varijanti i poboljšava batching.

  3. Pazite na overdraw: Koristite GPU Profiler da identifikujete oblasti sa visokim overdraw-om. Depth prepass pomaže, ali prevencija (pravilno postavljanje geometrije, korišćenje occlusion culling volumena) je bolja.

  4. Nanite za složenu geometriju: Za statičnu geometriju sa velikim brojem trouglova, Nanite dramatično smanjuje cenu base pass-a jer ima efikasniji culling i rasterizaciju.

29.9.2 Optimizacija Lighting Pass-a

  1. Ograničite domet svetala: Svako svetlo sa prevelikim dometom (Attenuation Radius) će uticati na više tile-ova nego što je potrebno. Postavite domet svetla na minimum koji daje vizualno zadovoljavajuć rezultat.

  2. Koristite statična svetla gde je moguće: Statična svetla (Mobility: Static) se bake-uju u lightmap-ove i nemaju cenu u runtime lighting pass-u.

  3. Smanjite broj senki: Shadow map renderovanje je skupo jer zahteva ponovni prolaz kroz geometriju scene za svako svetlo. Koristite senke samo za svetla gde su vizualno neophodne.

  4. Virtual Shadow Maps: Koristite Virtual Shadow Maps umesto tradicionalnih shadow map-ova — posebno u kombinaciji sa Nanite-om, VSM su značajno efikasniji.

29.9.3 Memorijske optimizacije

  1. Profajlirajte memorijsku potrošnju: Koristite stat RHI komandu da vidite koliko memorije zauzimaju render target-i.

  2. Razmotriti render rezoluciju: TSR omogućava renderovanje na nižoj rezoluciji (npr. 1080p) i upsampling na nativnu rezoluciju (npr. 4K). Ovo dramatično smanjuje G-Buffer veličinu i bandwidth.

  3. Onemogućite nepotrebne buffer-e: Ako ne koristite motion blur, razmislite o onemogućavanju velocity buffer-a. Ako ne koristite custom depth/stencil efekte, onemogućite ih.

29.9.4 Debagovanje vizualnih problema

Kada nešto ne izgleda kako treba, koristite sistematičan pristup:

  1. Prvo proverite G-Buffer (Buffer Visualization): Da li su surface atributi ispravni? Da li normale izgledaju korektno? Da li je roughness u očekivanom rasponu?

  2. Zatim proverite lighting: Isključite sva svetla osim jednog i proverite da li to svetlo daje očekivan rezultat.

  3. Proverite senke: Da li shadow map-ovi imaju dovoljnu rezoluciju? Da li je shadow bias ispravno podešen?

  4. Proverite post-processing: Onemogućite post-processing efekte jedan po jedan da biste identifikovali koji efekat izaziva problem.


29.10 Unakrsne reference sa drugim poglavljima

Ovo poglavlje je čvrsto povezano sa nekoliko drugih poglavlja u knjizi:

Poglavlje 07 — Pregled render pipeline-a

U poglavlju 07 smo uveli opšti koncept render pipeline-a: vertex processing → rasterizacija → fragment processing → output. Sada vidimo kako UE5 konkretno implementira ovaj pipeline, razdvajajući ga na multiple pass-ove sa specifičnim svrhama. Deferred rendering dodaje slojeve kompleksnosti na ovaj osnovni pipeline — base pass i lighting pass su oba "prolazi" kroz grafički pipeline, ali sa potpuno različitim svrhama.

Poglavlje 09 — Depth Buffer i Early-Z

Poglavlje 09 je objasnilo kako depth buffer funkcioniše i zašto je depth prepass važan za eliminaciju overdraw-a. U kontekstu UE5 deferred renderinga, depth prepass je još važniji nego u forward renderingu, jer base pass piše u multiple render targets (G-Buffer), pa je svaki nepotrebno obrađen piksel skuplja greška.

Takođe, depth buffer generisan u depth prepass-u se koristi u svim kasnijim pass-ovima: lighting pass ga koristi za rekonstrukciju world pozicije, shadow pass-ovi ga koriste za optimizaciju, screen-space efekti ga koriste za prostornu analizu, i post-processing ga koristi za depth-based efekte.

Poglavlje 15 — Post-Processing

Poglavlje 15 je detaljno obradilo post-processing efekte. Sada vidimo gde se post-processing uklapa u UE5 rendering pipeline — na samom kraju, nakon što su svi geometrijski, lighting, i GI pass-ovi završeni. Post-processing u deferred pipeline-u ima pristup bogatim informacijama iz G-Buffer-a (normale, depth, velocity), što omogućava efekte kao što su SSAO i SSR koji ne bi bili mogući u čistom forward pipeline-u.

TAA/TSR, koji su opisani u poglavlju 15 u kontekstu anti-aliasing-a, ovde vidimo u drugačijem svetlu — kao neophodnu zamenu za hardverski MSAA koji deferred rendering ne podržava.


29.11 Tabela ključnih pojmova

Termin Objašnjenje
Deferred Rendering Rendering pristup koji razdvaja geometriju i osvetljenje u odvojene pass-ove, koristeći G-Buffer kao intermedijer
Forward Rendering Rendering pristup koji računa kompletno osvetljenje za svaki piksel u istom pass-u sa geometrijom
G-Buffer (Geometry Buffer) Skup tekstura pune rezolucije ekrana koje čuvaju surface atribute (normale, boja, PBR parametri) za deferred lighting
Base Pass Render pass u kome se neprozirna geometrija renderuje i materijal atributi zapisuju u G-Buffer
Lighting Pass Render pass u kome se G-Buffer podaci kombinuju sa informacijama o svetlima za izračunavanje konačne osvetljene slike
Depth Prepass (Early-Z) Render pass koji popunjava depth buffer pre base pass-a, omogućavajući Early-Z rejection za eliminaciju overdraw-a
MRT (Multiple Render Targets) GPU mogućnost pisanja u više tekstura istovremeno iz jednog pixel shader-a
Tile-Based Light Culling Optimizacija koja deli ekran na tile-ove i za svaki tile određuje koja svetla ga pogađaju
Cluster-Based Light Culling Evolucija tile-based pristupa koja deli prostor u 3D cluster-e (tile + depth slicing)
Shading Model ID Identifikator u G-Buffer-u koji govori lighting pass-u koji shading model da koristi za piksel
Shadow Map Depth tekstura renderovana iz perspektive svetla, koristi se za izračunavanje senki
Virtual Shadow Maps (VSM) UE5 sistem koji koristi virtualne teksture za adaptivne shadow map-ove
Cascaded Shadow Maps (CSM) Sistem senki za directional light koji koristi više shadow map-ova na različitim rezolucijama
TAA (Temporal Anti-Aliasing) Softverski anti-aliasing koji koristi podatke iz prethodnih kadrova
TSR (Temporal Super Resolution) UE5 napredni temporal upsampling koji kombinuje anti-aliasing sa super resolution
MSAA (Multisample Anti-Aliasing) Hardverski anti-aliasing dostupan samo u forward rendering modu
Overdraw Situacija kada se isti piksel renderuje više puta jer se objekti preklapaju
RDG (Render Dependency Graph) UE5 sistem za automatsko upravljanje redosledom i zavisnostima render pass-ova
Visibility Buffer Nanite-ov intermedijarni buffer koji čuva informacije o vidljivosti pre materijal evaluacije
PBR (Physically Based Rendering) Rendering model zasnovan na fizičkim zakonima interakcije svetlosti sa materijalima
Cook-Torrance BRDF Matematički model za refleksiju svetlosti sa mikro-fasetkaste površine, korišćen u UE5 PBR
Octahedron Encoding Tehnika kompresije 3D vektora (normala) u 2 kanala, korišćena za uštedu G-Buffer prostora
Substrate (Strata) Eksperimentalni UE5 sistem za fleksibilnije shading modele u deferred renderingu
Async Compute GPU mogućnost paralelnog izvršavanja compute i graphics shader-a

29.12 Preporučena literatura i resursi

Zvanična Epic Games dokumentacija

GDC i Unreal Fest prezentacije

Akademski i industrijski resursi

Online resursi


Rezime poglavlja

U ovom poglavlju smo detaljno razmotrili rendering arhitekturu Unreal Engine 5. Evo ključnih zaključaka:

  1. UE5 koristi deferred rendering kao podrazumevani pristup, razdvajajući geometriju (base pass) od osvetljenja (lighting pass) koristeći G-Buffer kao intermedijer. Forward rendering je dostupan za mobilne i VR projekte.

  2. Rendering pipeline se sastoji od pažljivo organizovane sekvence pass-ova: depth prepass → base pass → shadow depth → lighting → Lumen GI → translucency → post-processing. Svaki pass zavisi od rezultata prethodnih.

  3. G-Buffer čuva kompletne surface atribute u 3-4 teksture pune rezolucije: normale, base color, metallic, roughness, specular, shading model ID, AO, i motion vectors. Na 4K rezoluciji, G-Buffer zauzima ~160 MB.

  4. Lighting pass koristi tile-based culling za efikasno rukovanje velikim brojem svetala, evaluirajući PBR jednačinu samo za svetla koja zaista utiču na svaki piksel.

  5. Deferred rendering donosi kompromise: efikasno rukovanje svetlima i screen-space efekti na jednoj strani, visok memorijski bandwidth i nemogućnost hardverskog MSAA na drugoj.

  6. Forward rendering u UE5 koristi clustered light culling i podržava hardverski MSAA, ali ima ograničenu podršku za Lumen, Nanite, i screen-space efekte.

  7. Transparentni objekti se uvek renderuju forward pristupom, čak i u deferred pipeline-u, jer G-Buffer ne može da čuva podatke za više slojeva transparentnosti po pikselu.

Razumevanje ove arhitekture je osnova za sve što sledi u petom delu knjige — od Nanite-a i Lumen-a do materijal sistema i post-processing optimizacija. Svaki od tih sistema je dizajniran da radi unutar okvira koji smo opisali u ovom poglavlju.

U sledećem poglavlju, zaronićemo dublje u specifične UE5 sisteme koji se oslanjaju na ovu rendering arhitekturu.


U sledećem poglavlju: Poglavlje 30 — dublje u UE5-specifične rendering sisteme.