Poglavlje 34: Virtual Textures -- Pametno upravljanje teksturama velikih svetova
Uvod
Zamislite sledecu situaciju: pravite ogroman open-world RPG. Vasa mapa prostire se na 16 kvadratnih kilometara. Teren je prekriven desetinama materijala -- trava, zemlja, pesak, stene, sneg, blato, lisice, mahovine. Svaki od tih materijala koristi bar tri teksture (Base Color, Normal, Roughness), a neke i cetiri-pet. Pomnosite to sa rezolucijom od 4K po teksturi i dobicete cifru od koje ce vam se zavrteti u glavi.
Sada zamislite da engine mora sve te teksture da drzi u VRAM-u, cak i one koje igracev pogled nikada nece videti u datom trenutku. To je, blago receno, neodrzivo.
Upravo tu na scenu stupaju Virtual Textures -- sistem koji fundamentalno menja nacin na koji engine upravlja teksturama. Umesto da ucita kompletnu teksturu u memoriju, engine ucitava samo one delove teksture koji su zaista potrebni na ekranu, u rezoluciji koja odgovara njihovoj velicini na ekranu.
U ovom poglavlju detaljno cemo proci kroz:
- Problem koji Virtual Textures resavaju
- Kako sistem funkcionise "ispod haube"
- Runtime Virtual Textures (RVT) i njihovu primenu na teren
- Streaming Virtual Textures (SVT) za tradicionalne teksture
- Page table mehanizam i indirection
- Feedback buffer i kako GPU komunicira sa CPU-om
- Prakticnu primenu na landscape rendering
- Performance i memory implikacije
Ovo je jedno od onih poglavlja gde cemo zaista "zaroniti ispod povrsine" -- ali obecavam da ce na kraju sve imati smisla. Krenimo!
Napomena o terminologiji: Kao i u prethodnim poglavljima, tehnicke termine (Virtual Texture, page table, feedback buffer, mip level itd.) ostavljamo na engleskom jer su to standardni termini koje cete sretati u dokumentaciji, tutorijalima i svakodnevnom radu sa Unreal Engine-om.
34.1 Problem koji Virtual Textures resavaju
34.1.1 Tradicionalni pristup teksturama
Da bismo razumeli zasto su Virtual Textures toliko vazne, moramo prvo da razumemo kako tradicionalni sistemi upravljaju teksturama.
Kada engine renderuje objekat, shader mora da procita podatke iz teksture -- boju piksela, normalu povrsine, roughness vrednost. Da bi to uradio, ta tekstura mora biti ucitana u VRAM (Video Random Access Memory -- memorija graficke kartice). To je jednostavno pravilo bez izuzetka: ako shader treba podatak iz teksture, ta tekstura mora biti u VRAM-u.
Tradicionalni pristup izgleda ovako:
-
Ucitavanje kompletne teksture -- Engine ucitava celu teksturu sa diska u VRAM. Ako imate 4096x4096 teksturu sa 4 kanala (RGBA) i 8 bita po kanalu, to je 64 MB nekomprimovanih podataka. Sa block compression (BC7 format, o kome smo govorili u Poglavlju 05), to se svodi na oko 16 MB -- ali to je i dalje 16 MB za jednu teksturu.
-
Mipmap streaming -- Moderniji pristup koristi mipmaps (videti Poglavlje 05) za delimicno resenje. Engine moze da ucita samo nize mip nivoe (manje verzije teksture) za objekte koji su daleko, a pune rezolucije samo za bliske objekte. Ovo pomaze, ali streaming se desava na nivou celih mip nivoa -- ili je ucitan ceo mip 0 (puna rezolucija) ili nije.
-
Texture pool -- Engine ima ogranicen bazen memorije za teksture (texture pool). Kada se pool napuni, engine mora da izbacuje teksture koje smatra manje vaznim, sto moze dovesti do vidljivog "pop-in" efekta -- teksture se ucitavaju sa zakasnjnjem i vidite kako se kvalitet postepeno poboljsava.
34.1.2 Gde tradicionalni pristup puca
Razmotrimo konkretne scenarije gde ovaj pristup postaje problematican:
Scenario 1: Veliki landscape sa mnogo slojeva
Landscape sistem u UE5 omogucava vam da koristite vise materijal slojeva (layers) za slikanje terena. Tipican teren moze imati:
- 8-16 razlicitih slojeva (trava, zemlja, kamen, pesak, sneg...)
- Svaki sloj ima Base Color, Normal Map, Roughness/AO packed teksturu -- dakle minimum 3 teksture po sloju
- Rezolucija: 2K ili 4K po teksturi
Brza matematika za 12 slojeva:
12 slojeva x 3 teksture x 16 MB (4K BC7) = 576 MB samo za landscape teksture
Ali problem ne staje tu. Kada engine renderuje piksel terena, on mora da blenduje vise slojeva na tom pikselu. Ako piksel ima tezine za 4 razlicita sloja, shader mora da procita podatke iz sve 4 Base Color teksture, sve 4 Normal Map teksture, sve 4 Roughness teksture -- to je 12 texture sample operacija za jedan piksel. I to radi za svaki piksel, svaki frame.
Za full HD (1920x1080) to je preko 2 miliona piksela. Za 4K (3840x2160) to je preko 8 miliona piksela. Svaki frame. 60 puta u sekundi.
Scenario 2: Mega-teksture i jedinstven teren
Zamislite da zelite da svaki deo vaseg terena bude jedinstven -- bez ponavljajucih paterna. Za teren od 4x4 km sa rezolucijom od 1 texel po centimetru, trebalo bi vam:
400,000 x 400,000 texela = 160 milijardi texela
Sa 4 bajta po texelu = 640 GB nekomprimovanih podataka
Ociggledno, ne postoji graficka kartica sa toliko VRAM-a. Cak ni sa kompresijom, ovo je apsurdna kolicina podataka.
Scenario 3: Filmska produkcija i fotorealisticne scene
U filmskoj produkciji (gde Unreal Engine sve vise nalazi primenu), scene mogu imati stotine unikatnih assets-a sa 8K teksturama. Ukupna kolicina texture podataka lako moze preci 100 GB.
34.1.3 Kljucni uvid: Vidljivost
Kljucni uvid koji stoji iza Virtual Textures je veoma intuitivan:
U bilo kom trenutku, igracev ekran prikazuje samo mali deo svih tekstura u sceni.
Ako stojite na livadi i gledate prema planini, ne trebaju vam teksture pustinje koja je iza vas. Ne trebaju vam teksture poda pecine koja je kilometar daleko. Cak vam ni ne treba puna rezolucija tekstura planine koja je daleko -- na toj udaljenosti, 64x64 texela je sasvim dovoljno.
Virtual Textures koriste ovaj uvid do krajnjih konsekvenci: ucitavaju samo one delove tekstura koji su zaista vidljivi na ekranu, u rezoluciji koja odgovara njihovoj velicini na ekranu.
34.2 Kako Virtual Textures funkcionisu (konceptualno)
Sada cemo zaroniti u mehaniku rada Virtual Texture sistema. Ne brinite -- pocecemo sa velikom slikom, pa cemo postepeno ulaziti u detalje.
34.2.1 Podela teksture na stranice (pages/tiles)
Prvi korak u razumevanju Virtual Textures je podela teksture na male, uniformne blokove koje zovemo pages (stranice) ili tiles (plocice).
Zamislite veliku teksturu od 8192x8192 texela. Virtual Texture sistem je deli na mrezu manjih blokova, tipicno 128x128 ili 256x256 texela:
Originalna tekstura: 8192 x 8192 texela
Velicina stranice: 128 x 128 texela
Broj stranica: 64 x 64 = 4096 stranica
Ili sa vecim stranicama:
Velicina stranice: 256 x 256 texela
Broj stranica: 32 x 32 = 1024 stranica
Svaka stranica je nezavisan blok podataka koji se moze ucitati ili izbaciti iz memorije nezavisno od ostalih stranica. Ovo je fundamentalna razlika u odnosu na tradicionalni sistem gde se cela tekstura (ili ceo mip nivo) tretira kao jedna jedinica.
Analogija sa virtuelnom memorijom:
Ako ste upoznati sa konceptom virtualne memorije u operativnim sistemima, Virtual Textures rade na veoma slican princip:
| Koncept OS-a | Virtual Texture ekvivalent |
|---|---|
| Virtualni adresni prostor | Virtual Texture UV prostor |
| Fizicka memorija (RAM) | Physical page pool (VRAM) |
| Stranica memorije (4KB) | Texture page (128x128 ili 256x256) |
| Page table | Page table (indirection texture) |
| Page fault | Nedostajuca stranica (page miss) |
| Swap file na disku | Tekstura na disku |
Ova analogija nije slucajna -- Virtual Textures su direktno inspirisane virtuelnom memorijom u operativnim sistemima. Princip je isti: dajte iluziju ogromnog resursa (adresnog prostora / teksture) dok zapravo koristite samo onoliko fizickog resursa koliko je u datom trenutku potrebno.
34.2.2 Fizicki page pool
Sada, gde se zapravo cuvaju ucitane stranice? Engine alocira poseban region VRAM-a koji se zove physical page pool (fizicki bazen stranica). To je, u sustini, veliki atlas tekstura -- jedna velika tekstura u koju se "pakuju" pojedinacne stranice virtuelnih tekstura.
Physical Page Pool (primer: 4096 x 4096 texela, sa 128x128 stranicama)
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| A | B | C | D | E | F | | | | | | | | | ...
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| G | H | I | | | | | | | | | | | | ...
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | | | | | | | ...
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
...
Svaka celija (A, B, C...) sadrzi jednu 128x128 stranicu iz
neke virtuelne teksture. Stranice razlicitih tekstura i
razlicitih mip nivoa mogu biti pomesane u istom pool-u.
Velicina physical page pool-a je fiksna i definise se unapred. Tipicne vrednosti su od 256 MB do 1 GB, u zavisnosti od igre i hardvera. Kada se pool napuni, engine mora da izbaci (evict) stranice koje se vise ne koriste da bi napravio mesta za nove.
34.2.3 Page table: mapiranje virtualnog u fizicko
Sada dolazimo do kljucnog pitanja: kada shader zeli da procita texel na virtualnim UV koordinatama (u, v) neke virtuelne teksture, kako zna gde se taj podatak fizicki nalazi u page pool-u?
Odgovor je page table -- struktura podataka koja mapira virtualne adrese u fizicke adrese.
Page table za jednu virtuelnu teksturu izgleda konceptualno ovako:
Page Table za Virtual Texture "TerrainBaseColor" (8192x8192)
Virtualna pozicija | Fizicka pozicija u pool-u | Mip nivo | Status
(page_x, page_y) | (pool_x, pool_y) | |
---------------------|---------------------------|----------|--------
(0, 0) | (5, 12) | 0 | Loaded
(1, 0) | (23, 7) | 0 | Loaded
(2, 0) | - | 0 | Not loaded
(3, 0) | (8, 31) | 2 | Fallback*
... | ... | ... | ...
* Fallback znaci da puna rezolucija (mip 0) nije ucitana,
pa se koristi nizi mip nivo (mip 2) kao zamena.
U praksi, page table se implementira kao tekstura (indirection texture) koja se cuva u VRAM-u. Svaki texel ove teksture sadrzi informaciju o jednoj stranici: gde se nalazi u fizickom pool-u i koji mip nivo je ucitan.
34.2.4 Indirection texture (tekstura preusmeravanja)
Indirection texture je kompaktna, niske rezolucije tekstura koja sluzi kao "telefonski imenik" za Virtual Texture sistem. Pogledajmo kako shader koristi ovu teksturu:
Korak 1: Izracunavanje virtualne stranice
Shader ima UV koordinate fragmenta (piksela) koji renderuje. Na osnovu tih koordinata i velicine virtuelne teksture, odreduje koja mu stranica treba:
// Pseudokod
page_x = floor(uv.x * virtual_texture_width / page_size);
page_y = floor(uv.y * virtual_texture_height / page_size);
Korak 2: Citanje indirection texture
Shader cita indirection teksturu na poziciji (page_x, page_y). Vrednost koju dobija sadrzi:
- Poziciju stranice u fizickom pool-u (pool_x, pool_y)
- Mip nivo koji je ucitan
- Eventualno: da li je stranica uopste ucitana
// Pseudokod
IndirectionData data = indirectionTexture.Sample(page_x, page_y);
physical_page_pos = data.physicalPosition; // (pool_x, pool_y)
loaded_mip = data.mipLevel;
Korak 3: Izracunavanje fizickih UV koordinata
Sada shader zna gde se stranica fizicki nalazi. Izracunava UV koordinate unutar fizickog pool-a:
// Pseudokod
// Offset unutar stranice (lokalna pozicija texela unutar page-a)
in_page_offset.x = frac(uv.x * num_pages_x) * page_size;
in_page_offset.y = frac(uv.y * num_pages_y) * page_size;
// Fizicke UV koordinate u pool-u
physical_uv.x = (physical_page_pos.x * page_size + in_page_offset.x) / pool_width;
physical_uv.y = (physical_page_pos.y * page_size + in_page_offset.y) / pool_height;
Korak 4: Citanje fizicke teksture
Konacno, shader cita boju (ili normalu, roughness, itd.) iz fizickog page pool-a na izracunatim fizickim UV koordinatama:
// Pseudokod
float4 color = physicalPagePool.Sample(physical_uv);
Ceo proces u dijagramu:
Indirection Texture
(low-res "mapa")
|
UV koordinate -----> [Izracunaj page] -----> [Procitaj indirection]
|
physical_page_pos
|
[Izracunaj fizicke UV]
|
physical_uv
|
Physical Page Pool <---------+
(atlas tekstura)
|
Boja piksela
34.2.5 Cena indirection-a
Moramo biti posteni -- ovaj sistem ima svoju cenu. Umesto jednog texture sample-a (citanja teksture), sada imamo dva:
- Citanje indirection teksture (da saznamo gde je stranica)
- Citanje fizicke teksture (da dobijemo stvarni podatak)
To znaci da svaki Virtual Texture sample kosta otprilike duplo u odnosu na obican texture sample, u smislu broja texture fetch operacija. U praksi, indirection tekstura je mala i gotovo uvek u texture cache-u GPU-a, pa je dodatan trosak manji nego sto bi se ocekivalo -- ali nije zanemarljiv.
Zato Virtual Textures nisu uvek pravo resenje. Za jednostavne scene sa malim brojem tekstura, overhead indirection-a ne opravdava ustedu memorije. Ali za velike svetove sa stotinama megabajta (ili gigabajta) tekstura -- ustedja je ogromna.
34.2.6 Feedback buffer: GPU govori CPU-u sta mu treba
Do sada smo objasnili kako shader cita stranice koje su vec ucitane. Ali kako engine zna koje stranice treba da ucita? Kako zna da je igrac skrenuo pogled na levo i da mu sada trebaju potpuno druge stranice?
Tu na scenu stupa feedback buffer (bafer povratnih informacija).
Koncept je sledeci:
-
Tokom renderovanja, shader ne samo da cita virtuelne teksture, vec i zapisuje informaciju o tome koje stranice su mu potrebne. Za svaki piksel (ili tacnije, za svaku grupu piksela), shader zapisuje:
- ID virtuelne teksture
- Koordinate stranice (page_x, page_y)
- Potreban mip nivo (na osnovu udaljenosti objekta od kamere)
-
Feedback buffer je niske rezolucije -- ne zapisuje se informacija za svaki piksel ekrana. Tipicno se koristi 1/8 ili 1/16 rezolucije ekrana. Za 1920x1080, feedback buffer bi bio 240x135 ili 120x68 piksela. Ovo drasticno smanjuje kolicinu podataka koja se prenosi sa GPU-a na CPU.
-
CPU cita feedback buffer (readback sa GPU-a na CPU) i analizira zahteve:
- Koje stranice su potrebne, a nisu ucitane?
- Koji mip nivoi su potrebni?
- Koje stranice imaju najvisi prioritet? (one u centru ekrana, na bliskim objektima)
-
CPU pokrece ucitavanje nedostajucih stranica sa diska (ili iz system RAM-a) u VRAM page pool.
Feedback Buffer tok podataka:
Frame N:
GPU renderuje scenu
|
Shader zapisuje page zahteve u feedback buffer (low-res)
|
GPU zavrsava frame
|
CPU cita feedback buffer (GPU -> CPU readback)
|
CPU analizira zahteve, odreduje prioritete
|
CPU pokrece async ucitavanje nedostajucih stranica sa diska
|
Frame N+1 ili N+2:
Stranice stizu u VRAM page pool
|
Page table (indirection texture) se azurira
|
Shader sada moze da cita nove stranice
Vazna napomena o latenciji: Primetite da postoji kasnjenje od bar 1-2 frame-a izmedju trenutka kada GPU zatrazi stranicu i trenutka kada ta stranica postane dostupna. U tom periodu, shader koristi fallback -- nizi mip nivo koji je vec ucitan. Zato ponekad mozete primetiti da se teksture "izostrravaju" nakon pomeranja kamere. Ovo je inherentno svojstvo sistema i projektovano ponasanje, ne bag.
34.2.7 Mipmap integracija sa Virtual Textures
Virtual Textures i mipmaps prirodno idu zajedno. Svaki mip nivo virtuelne teksture se takode deli na stranice:
Mip 0 (puna rezolucija): 8192 x 8192 = 64 x 64 = 4096 stranica
Mip 1 (1/2 rezolucije): 4096 x 4096 = 32 x 32 = 1024 stranica
Mip 2 (1/4 rezolucije): 2048 x 2048 = 16 x 16 = 256 stranica
Mip 3 (1/8 rezolucije): 1024 x 1024 = 8 x 8 = 64 stranice
Mip 4: 512 x 512 = 4 x 4 = 16 stranica
Mip 5: 256 x 256 = 2 x 2 = 4 stranice
Mip 6: 128 x 128 = 1 x 1 = 1 stranica
Engine ucitava stranice na razlicitim mip nivoima u zavisnosti od udaljenosti od kamere. Za deo terena koji je blizu kamere, ucitava stranice sa mip 0 (puna rezolucija). Za deo koji je daleko, ucitava stranice sa mip 4 ili 5 (niska rezolucija). Ovo je analogno tradicionalnom mipmap streaming-u, ali sa mnogo finom granulacijom -- umesto "ucitaj ceo mip 0 ili nista", sada je "ucitaj samo ove dve stranice sa mip 0 za deo terena ispred igraca".
Nizi mip nivoi (mip 5, mip 6) su dovoljno mali da ceo nivo stane u jednu ili nekoliko stranica. Engine obicno drzi ove nize mip nivoe uvek ucitane kao fallback -- garantovani minimum kvaliteta dok se stranice pune rezolucije ucitavaju.
34.3 Runtime Virtual Textures (RVT)
Sada prelazimo na prvu od dve glavne kategorije Virtual Textures u Unreal Engine-u: Runtime Virtual Textures (RVT). Ovo je, za vecinu korisnika, najvaznija i najprakticnija primena VT tehnologije.
34.3.1 Sta su Runtime Virtual Textures?
Runtime Virtual Textures se razlikuju od obicnih Virtual Textures po jednoj kljucnoj osobini: nisu unapred napravljene (pre-authored), vec se generisu u realnom vremenu tokom igre.
Sta to tacno znaci? Umesto da tekstura postoji kao fajl na disku koji se ucitava, engine renderuje sadrzaj Virtual Texture-a tokom igre i kesira (cache-uje) rezultat. Sledeci put kada mu taj deo treba, umesto da ponovo renderuje, samo procita kesirani rezultat.
Ovo zvuci apstraktno, pa hajde da pogledamo konkretan i najvazniji use case: landscape rendering.
34.3.2 Problem sa tradicionalnim landscape renderingom
Da bismo razumeli zasto je RVT tako vazan za landscape, pogledajmo kako tradicionalni landscape rendering funkcionise.
Tradicionalni pristup (bez RVT-a):
Recimo da imate landscape sa 8 slojeva materijala. Svaki sloj ima Base Color, Normal Map i ORM (Occlusion/Roughness/Metallic) teksturu. Material shader za svaki piksel terena mora da:
- Procita weight map (blend map) da odredi tezinu svakog sloja na tom pikselu
- Za svaki sloj koji ima nenultu tezinu: a. Procita Base Color teksturu sloja b. Procita Normal Map teksturu sloja c. Procita ORM teksturu sloja
- Blenduje sve procitane vrednosti prema tezinama
U najgorem slucaju (piksel na preseku vise slojeva), to moze biti:
1 weight map citanje
+ 4 sloja x 3 teksture = 12 texture citanja
+ blend racunanje
= 13+ texture sample operacija po pikselu
Za svaki piksel, svaki frame!
Na 4K rezoluciji (8.3 miliona piksela), to je preko 100 miliona texture sample operacija samo za teren, svaki frame. Ovo je ogroman trosak za GPU.
A to nije sve -- mnogi landscape materijali koriste i detail textures, macro variation textures, tri-planar mapping i druge efekte koji jos vise umnozavaju broj citanja.
Kljucno zapazanje: U vecini slucajeva, teren se menja veoma retko (ili nikada). Igrac hoda, kamera se pomera, ali sam teren ostaje isti. To znaci da engine svaki frame ponovo racuna isti rezultat -- ogromno trosenje resursa!
34.3.3 RVT resenje: izracunaj jednom, koristi mnogo puta
Runtime Virtual Texture pristup potpuno menja paradigmu:
-
Jednom izracunaj -- Engine renderuje landscape material za deo terena koji je vidljiv, sa svim slojevima, blending-om i efektima. Rezultat (finalna boja, normala, roughness) se zapisuje u RVT stranicu.
-
Kesiraj u Virtual Texture -- Ta stranica se cuva u fizickom page pool-u.
-
Koristi kesiranu verziju -- Svaki sledeci frame, umesto da ponovo racuna ceo material, shader samo procita kesiranu stranicu iz RVT-a. To je jedno texture citanje umesto 13+!
Tradicionalno (svaki frame):
8 slojeva x 3 teksture = 24 texture reads + blend
= veoma skupo
RVT (prvi frame za tu stranicu):
8 slojeva x 3 teksture = 24 texture reads + blend
Rezultat -> zapisi u RVT stranicu
= skupo, ali samo jednom
RVT (svaki sledeci frame):
1 texture read iz RVT-a
= veoma jeftino!
Usteda je dramaticna. Za kompleksne landscape materijale sa mnogo slojeva, RVT moze doneti 5-10x smanjenje broja texture sample operacija po pikselu.
34.3.4 Kako RVT radi -- detaljan pregled
Pogledajmo korak po korak kako engine koristi RVT za landscape:
Faza 1: Setup (u editoru)
- Kreirate Runtime Virtual Texture asset (Content Browser > desni klik > Textures > Runtime Virtual Texture)
- Konfigurisete RVT:
- Virtual Texture Content: sta se kesira (Base Color, Specular, Roughness, Normal, World Height, itd.)
- Tile Count: velicina virtuelne teksture u stranicama
- Tile Size: velicina svake stranice (obicno 256x256)
- Postavite Runtime Virtual Texture Volume u scenu koji definise oblast koju RVT pokriva
- U landscape materialu dodajete Runtime Virtual Texture Output node koji definise sta se zapisuje u RVT
- Landscape materialu takode dodajete Runtime Virtual Texture Sample node koji cita iz RVT-a
Faza 2: Renderovanje (u igri, svaki frame)
1. Engine odreduje vidljive delove landscape-a
2. Za svaku vidljivu stranicu:
a. Da li je stranica vec u cache-u (page pool)?
- DA -> koristi kesiranu verziju (jeftino!)
- NE -> nastavi na korak b
b. Engine renderuje landscape material za tu stranicu:
- Procita sve weight maps
- Procita sve teksture svih slojeva
- Blenduje ih
- Zapise rezultat u RVT stranicu u page pool-u
- Azurira page table (indirection texture)
3. Finalni rendering koristi RVT:
- Shader cita indirection texture
- Odreduje fizicku poziciju stranice u pool-u
- Cita kesiranu boju/normalu/roughness
- Nastavlja sa lighting racunanjem
Faza 3: Invalidacija (kada se nesto promeni)
Sta se desava kada se teren promeni? Na primer:
- U editoru: umetnik promeni landscape painting (dodaje novi sloj)
- U igri: dinamicka deformacija terena, sneg koji se topi, proceduralni efekti
Kada se desi promena, engine mora da invalidira (ponisti) odgovarajuce stranice RVT-a. Invalidirane stranice ce biti ponovo renderovane sledeci put kada budu vidljive. Invalidacija je lokalna -- menja se samo oblast koja je zaista promenjena, ne cela tekstura.
Invalidacija:
Promena na terenu (npr. iskopan krater)
|
Engine odreduje koje RVT stranice su pogodene
|
Te stranice se oznacavaju kao "dirty" (zastarele)
|
Sledeci frame: engine ponovo renderuje te stranice
|
Nove stranice zamenjuju stare u page pool-u
34.3.5 Prakticno podesavanje RVT-a za landscape
Hajde da prodemo kroz konkretan workflow za podesavanje RVT-a u UE5. Ovo su koraci koje cete pratiti u svom projektu:
Korak 1: Kreiranje RVT asset-a
- U Content Browser-u: desni klik > Miscellaneous > Runtime Virtual Texture
- Otvorite kreirani asset i podesite:
- Virtual Texture Content: izaberite YCoCg Base Color, Normal, Roughness, Specular (najcesci izbor za landscape). Ovo definise koje podatke RVT cuva. Opcije su:
- Base Color: samo boja
- Base Color, Normal, Roughness, Specular: kompletan PBR set (najfleksibilniji)
- World Height: visina terena (korisno za blending objekata sa terenom)
- Tile Count: odreduje ukupnu rezoluciju virtuelne teksture. Vece vrednosti = visa rezolucija ali vise memorije. Za manji teren (2x2 km) obicno 256 ili 512. Za veliki teren (8x8 km) mozda 1024 ili 2048.
- Tile Size: velicina pojedinacne stranice. Podrazumevano 256x256, sto je dobar balans.
- Tile Border Size: velicina border-a oko svake stranice (spreccava seam artefakte pri filtriranju). Podrazumevana vrednost je obicno dovoljno dobra.
- Virtual Texture Content: izaberite YCoCg Base Color, Normal, Roughness, Specular (najcesci izbor za landscape). Ovo definise koje podatke RVT cuva. Opcije su:
Korak 2: Postavljanje RVT Volume-a
- U scenu dodajte Runtime Virtual Texture Volume aktor
- U Details panelu, podesite:
- Virtual Texture: povucite referenca na RVT asset koji ste kreirali
- Transform Primitives opcija: odreduje da li Volume transformise (skalira/rotira) i primitive koje renderuje u RVT
- Skalirajte Volume da pokrije ceo landscape
- Volume mora da pokrije celu oblast za koju zelite RVT
- Obicno se postavlja da pokriva ceo landscape
Korak 3: Modifikacija landscape materiala
Ovo je najvazniji korak. Vas landscape material treba modifikovati da koristi RVT na dva nacina:
A) Izlaz u RVT (sta se kesira):
U Material Editor-u dodajte Runtime Virtual Texture Output node. Povezite ga sa:
- Base Color izlazom vaseg landscape material-a
- Normal izlazom
- Roughness izlazom
- Specular izlazom (opciono)
Ovaj node ne utice na finalni izgled -- on samo govori engine-u "zapisi ove podatke u RVT kada renderujes stranicu".
B) Citanje iz RVT-a (koriscenje kesa):
Dodajte Runtime Virtual Texture Sample node. Ovaj node cita kesiranu stranicu iz RVT-a. Povezite njegove izlaze sa glavnim Material Output node-om:
- Base Color izlaz RVT Sample -> Base Color ulaz Material Output
- Normal izlaz RVT Sample -> Normal ulaz Material Output
- Roughness izlaz RVT Sample -> Roughness ulaz Material Output
C) Logika prebacivanja:
Engine automatski odlucuje kada da koristi pun material (za renderovanje u RVT) a kada da cita iz RVT-a. Ovo se kontrolise kroz Virtual Texture Output switch u materialu.
Konceptualno, material ima dva "puta":
Put 1 (RVT Write -- koristi se za generisanje stranica):
Svi slojevi -> Blend -> Runtime Virtual Texture Output node
(Kompleksan, skup, ali se izvrsava retko)
Put 2 (RVT Read -- koristi se za normalno renderovanje):
Runtime Virtual Texture Sample node -> Material Output
(Jednostavan, jeftin, izvrsava se svaki frame)
Korak 4: Podesavanje landscape-a
- Selektujte Landscape aktor u sceni
- U Details panelu, u sekciji Virtual Texture, dodajte referenvu na vas RVT asset
- Ovo govori landscape-u da ucestvuje u RVT sistemu
Korak 5: Testiranje i optimizacija
- Koristite komandu konzole
r.VT.Borders 1da vidite granice RVT stranica na ekranu stat VirtualTextureMemoryprikazuje statistike memorije VT sistemastat VirtualTexturingprikazuje opstu statistiku VT renderovanja
34.3.6 RVT za blending objekata sa terenom
Pored landscape optimizacije, RVT ima jos jednu veoma korisnu primenu: prirodan blending objekata sa terenom.
Zamislite kamen koji lezi na travi. U tradicionalnom pristupu, kamen ima svoju teksturu, a teren ima svoju, i na granici izmedju njih vidite ostar prelaz. Sa RVT-om, material kamena moze da procita RVT terena i koristi tu informaciju za blending:
Material kamena sa RVT blending-om:
1. Procitaj RVT terena na poziciji piksela (Base Color terena)
2. Procitaj teksturu kamena
3. Na donjim delovima kamena (blizu terena):
- Blenduj boju kamena sa bojom terena
- Mozda dodaj mahovinu ili prljavstinu
4. Na gornjim delovima kamena:
- Koristi cistu teksturu kamena
Rezultat je prirodan prelaz izmedju kamena i terena, bez vidljive granice. A posto kamen cita RVT umesto da ponovo racuna landscape material, ovo je i performantno.
Ovo je posebno korisno za:
- Stene i kamenje na terenu
- Puteve i staze koji se stapaju sa okolnim terenom
- Zgrade i ograde cije baze treba da se uklapaju sa terenom
- Vegetacija (koren drveta koji izlazi iz zemlje)
34.3.7 World Height u RVT-u
RVT moze da cuva i World Height informaciju -- visinu terena u svetskom prostoru. Ovo je korisno za:
-
Objekte koji se "ukopavaju" u teren -- material moze da proveri visinu terena i sakrije delove objekta koji bi trebalo da budu ispod povrsine
-
Dinamicka tesselacija -- tessellation shader moze da koristi height informaciju za deformaciju
-
Proracun orijentacije -- material moze da izracuna normalu terena iz height map-e za blending
Podesavanje je isto kao za Base Color/Normal, samo sto u RVT asset-u ukljucite World Height opciju.
34.4 Streaming Virtual Textures (SVT)
Dok su Runtime Virtual Textures dizajnirane za podatke koji se generisu u realnom vremenu, Streaming Virtual Textures (SVT) se primenjuju na tradicionalne, unapred napravljene teksture -- one koje dolaze sa vasim modelima i asset-ima.
34.4.1 Sta su Streaming Virtual Textures?
SVT je sistem koji vase postojece teksture tretira kao virtuelne teksture i primenjuje page-based streaming umesto tradicionalnog mip-based streaming-a.
Tradicionalni texture streaming (mip-based):
Tekstura: 4096 x 4096
Mip 0: 4096x4096 = 16 MB <- Ucitano samo kada je objekat blizu
Mip 1: 2048x2048 = 4 MB <- Ucitano za srednju udaljenost
Mip 2: 1024x1024 = 1 MB <- Ucitano za vecu udaljenost
Mip 3: 512x512 = 256 KB <- Uvek ucitano (fallback)
...
Streaming jedinica: CEO mip nivo (sve ili nista)
Problem: Ako je objekat blizu kamere ali vidite samo mali deo njegove teksture (npr. gledate u ugao velikog zida), engine mora da ucita ceo mip 0 -- svih 16 MB -- iako vam zapravo treba samo mali deo.
SVT streaming (page-based):
Ista tekstura: 4096 x 4096, podeljena na 128x128 stranice
Mip 0: 32 x 32 = 1024 stranica x 16 KB = ukupno 16 MB
Ali: ucitava se samo 10-20 stranica koje su vidljive = 160-320 KB!
Mip 1: 16 x 16 = 256 stranica
Mip 2: 8 x 8 = 64 stranica
...
Streaming jedinica: JEDNA stranica (128x128 texela)
Razlika je ogromna: umesto 16 MB za ceo mip 0, ucitate samo 160-320 KB za stranice koje su zaista vidljive!
34.4.2 Granularnost: page vs mip streaming
Evo vizuelnog poredenja granularnosti dva pristupa:
Mip-based streaming: Page-based streaming (SVT):
+-------------------------------+ +---+---+---+---+---+---+---+---+
| | | | | | L | L | | | |
| Ceo mip 0 | +---+---+---+---+---+---+---+---+
| MORA biti ucitan | | | | L | L | L | L | | |
| cak i ako je samo | +---+---+---+---+---+---+---+---+
| mali deo vidljiv | | | | L | L | L | | | |
| | +---+---+---+---+---+---+---+---+
| 16 MB | | | | | L | | | | |
| | +---+---+---+---+---+---+---+---+
+-------------------------------+
L = Loaded (ucitano), samo vidljive
stranice. Ostale nisu u memoriji.
Ukupno: ~200 KB umesto 16 MB
34.4.3 Kako omoguciti SVT u projektu
SVT se aktivira na nivou projekta:
- Project Settings > Engine > Rendering > Virtual Textures
- Ukljucite Enable Virtual Texture Support
- Opciono: Enable Virtual Texture Lightmaps (lightmaps kao VT)
Kada je VT podrska ukljucena, mozete za svaku teksturu pojedinacno odrediti da li ce koristiti VT streaming:
- Otvorite teksturu u Content Browser-u
- U Details panelu, pronadjite Virtual Texture Streaming checkbox
- Ukljucite ga
Napomena: Ne morate (i ne treba) da ukljucite VT za sve teksture. Male teksture (256x256 ili manje) nemaju koristi od VT sistema -- overhead indirection-a je veci od ustede. VT je najkorisniji za velike teksture (2K+) i za scene sa mnogo razlicitih tekstura.
34.4.4 SVT i UDIM teksture
Posebno interesantna primena SVT-a je podrska za UDIM teksture -- teksture koje se prostiru preko vise UV tile-ova. Ovo je standard u filmskoj produkciji gde se za jedan karakter moze koristiti 10-20 UDIM tile-ova, svaki sa 4K ili 8K rezolucijom.
Bez VT-a, ucitavanje svih UDIM tile-ova bi zahtevalo ogromnu kolicinu VRAM-a. Sa SVT-om, engine ucitava samo one page-ove koji su vidljivi na ekranu, bez obzira na to koliko UDIM tile-ova postoji.
34.4.5 Razlike izmedju RVT i SVT
Hajde da jasno sumiramo razlike:
| Osobina | RVT (Runtime) | SVT (Streaming) |
|---|---|---|
| Izvor podataka | Generise se u realnom vremenu | Pre-authored (vec postoji na disku) |
| Primarna namena | Landscape material caching, blending | Upravljanje memorijom za velike teksture |
| Kada se kreira sadrzaj | Tokom igre, po potrebi | Unapred, u procesu izrade asset-a |
| Invalidacija | Da (kada se teren promeni) | Ne (sadrzaj je fiksan) |
| Tipican use case | Landscape sa mnogo slojeva | Scene sa mnogo velikih tekstura |
| Performance benefit | Smanjenje shader complexity | Smanjenje VRAM koriscenja |
| Overhead | Renderovanje stranica + VT overhead | Samo VT overhead |
Vazan koncept: RVT i SVT dele istu infrastrukturu (page pool, indirection, feedback buffer), ali se razlikuju u tome kako se sadrzaj stranica popunjava. Kod SVT-a, stranice se ucitavaju sa diska. Kod RVT-a, stranice se renderuju u realnom vremenu.
34.5 Page table i indirection -- dublje u detalje
U sekciji 34.2 smo preSli konceptualni pregled page table sistema. Sada cemo ici dublje i objasniti kako UE5 zapravo implementira ovaj mehanizam.
34.5.1 Dvostepeni page table (Two-level page table)
Za veoma velike virtuelne teksture, jednostepeni page table (jedan indirection texel po stranici) postaje nepraktican. Razlog je jednostavan: ako imate virtuelnu teksturu sa milionima stranica (ukljucujuci sve mip nivoe), indirection tekstura bi sama po sebi bila ogromna.
UE5 koristi dvostepeni page table (two-level page table) za resavanje ovog problema:
Two-Level Page Table:
Nivo 1 (grub): Nivo 2 (fin):
+---+---+---+---+ +---+---+---+---+---+---+---+---+
| A | B | C | D | A ------> |a1 |a2 |a3 |a4 |a5 |a6 |a7 |a8 |
+---+---+---+---+ +---+---+---+---+---+---+---+---+
| E | F | G | H | |a9 |a10|a11|a12|a13|a14|a15|a16|
+---+---+---+---+ +---+---+---+---+---+---+---+---+
| I | J | K | L |
+---+---+---+---+ Svaka celija nivoa 1 ukazuje na grupu
| M | N | O | P | celija nivoa 2 koje sadrze konkretne
+---+---+---+---+ fizicke adrese stranica.
Kako shader koristi dvostepeni page table:
- Na osnovu UV koordinata i virtuelne velicine, shader izracuna grubu adresu (koji blok nivoa 1)
- Procita nivo 1 indirection teksture na toj adresi -- dobija offset u nivo 2 tabeli
- Na osnovu UV koordinata i offset-a, izracuna finu adresu u nivou 2
- Procita nivo 2 indirection teksture -- dobija fizicku adresu stranice u page pool-u
- Izracuna fizicke UV koordinate i procita stranicu
Da, to su tri texture citanja umesto dva (dva nivoa indirection-a + fizicka tekstura). Ali prednost je da su indirection teksture mnogo manje:
Jednostepeni page table za 65536 x 65536 VT sa 128x128 stranicama:
512 x 512 indirection tekstura = 1 MB
Dvostepeni page table:
Nivo 1: 32 x 32 = malo
Nivo 2: po potrebi, samo za ucitane regione
Ukupno: mnogo manje jer se nivo 2 alocira samo za aktivne regione
34.5.2 Fizicki page pool -- implementacija
Fizicki page pool je, na hardverskom nivou, jedna ili vise velikih 2D tekstura u VRAM-u. Engine ih alocira pri pokretanju i koristi tokom celog zivotnog veka igre.
Organizacija pool-a:
Page Pool (primer konfiguracije):
Format: BC7 (Block Compressed)
Dimenzije: 8192 x 8192 texela
Velicina stranice: 128 x 128 texela (sa border-om: 132 x 132)
Broj slotova: 62 x 62 = 3844 stranica
Memorija: ~64 MB
Moze biti vise pool-ova za razlicite formate:
- Pool za Base Color (BC7): 64 MB
- Pool za Normal Maps (BC5): 32 MB
- Pool za Roughness/AO (BC4): 16 MB
Border (ivica) oko svake stranice:
Svaka stranica u pool-u ima mali border (obicno 1-4 texela) oko sebe. Ovaj border sadrzi texele susednih stranica i neophodan je za korektno bilinearno filtriranje i anizotropno filtriranje na granicama stranica. Bez border-a, filtriranje bi "zavirilo" u susednu stranicu u pool-u koja pripada potpuno drugoj virtuelnoj teksturi, sto bi stvorilo vidljive artefakte.
Stranica u pool-u sa border-om:
+--+---------------------------+--+
|B | B B B B B B B |B | B = Border texeli (kopirani
+--+---------------------------+--+ iz susednih stranica)
|B | |B |
|B | |B |
|B | Stvarni sadrzaj |B |
|B | stranice (128x128) |B |
|B | |B |
|B | |B |
+--+---------------------------+--+
|B | B B B B B B B |B |
+--+---------------------------+--+
Ukupna velicina u pool-u: (128 + 2*border) x (128 + 2*border)
Sa border = 2: 132 x 132 texela
34.5.3 Eviction policy (politika izbacivanja)
Kada je page pool pun i engine treba da ucita novu stranicu, mora da izbaci neku postojecu. Engine koristi LRU (Least Recently Used) politiku sa modifikacijama:
- Stranice koje nisu koriscene (referencirana u feedback buffer-u) najduze se prve izbacuju
- Stranice nizih mip nivoa (fallback) imaju veci prioritet zadrzavanja
- Stranice u centru pogleda imaju veci prioritet od perifernih
Ovo je transparentno za korisnika -- engine automatski upravlja pool-om. Ali razumevanje ovog mehanizma pomaze u debugovanju situacija gde vidite "blurry" teksture (mnogo eviction-a) ili stalni page loading (pool je premali).
34.5.4 Sampling virtuelne teksture u shader-u -- kompletan tok
Hajde da sve spojimo i prikazemo kompletan tok jednog Virtual Texture sample-a u shader-u, od UV koordinata do finalne boje:
// Pseudokod VT sampling-a u shader-u (pojednostavljen)
float4 SampleVirtualTexture(float2 uv, VirtualTextureInfo vtInfo)
{
// 1. Izracunaj potreban mip nivo na osnovu derivativa UV-a
// (koliko se UV menja od piksela do piksela = koliko je povrsina daleko)
float mipLevel = ComputeMipLevel(uv, ddx(uv), ddy(uv));
// 2. Izracunaj adresu virtualne stranice
float2 pageCoord = floor(uv * vtInfo.numPages[mipLevel]);
// 3. Procitaj indirection teksturu (nivo 1)
// Ovo nam daje fizicku poziciju stranice u page pool-u
float4 indirection = indirectionTexture.Load(pageCoord, mipLevel);
float2 physicalPagePos = indirection.xy; // pozicija u pool-u
float loadedMip = indirection.z; // koji mip je zapravo ucitan
// 4. Izracunaj offset unutar stranice
float2 inPageUV = frac(uv * vtInfo.numPages[mipLevel]);
// 5. Izracunaj finalne fizicke UV koordinate u page pool-u
float2 physicalUV = (physicalPagePos + inPageUV) * vtInfo.pagePoolTexelSize;
// 6. Uzmi u obzir border
physicalUV = AdjustForBorder(physicalUV, vtInfo.borderSize);
// 7. Procitaj fizicku teksturu iz page pool-a
float4 color = pagePool.SampleLevel(physicalUV, 0);
// Napomena: SampleLevel sa 0 jer smo vec izracunali mip --
// fizicka tekstura nema sopstvene mipmaps, VT sistem
// upravlja mip nivoima kroz razlicite stranice.
// 8. (Opciono) Zapisi u feedback buffer
// Samo za podskup piksela (1/8 ili 1/16 rezolucije)
if (IsInFeedbackRegion(screenPos))
{
feedbackBuffer[feedbackPos] = EncodeFeedback(vtInfo.id, pageCoord, mipLevel);
}
return color;
}
Kljucne tacke iz ovog koda:
- Mip nivo se racuna iz UV derivativa -- isto kao za obicne teksture, ali se koristi za odredjivanje koji mip nivo virtuelne teksture treba
- Indirection citanje je dodatni trosak koji ne postoji kod obicnih tekstura
- Page pool nema sopstvene mipmaps -- Virtual Texture sistem sam upravlja mip nivoima kroz razlicite stranice razlicitih mip nivoa
- Feedback se ne zapisuje za svaki piksel -- samo za podskup, da se smanji overhead
34.6 Feedback buffer -- detaljan pregled
Feedback buffer je kljucni mehanizam komunikacije izmedju GPU-a (koji zna sta je vidljivo) i CPU-a (koji upravlja ucitavanjem stranica). Hajde da ga detaljno razmemo.
34.6.1 Kako GPU generise feedback
Tokom renderovanja scene, svaki shader koji koristi Virtual Texture moze da generise feedback. Medjutim, generisanje feedback-a za svaki piksel bi bilo:
- Preskupo -- zahtevalo bi pisanje u buffer za svaki piksel, sto je dodatna operacija
- Previse podataka -- za 4K rezoluciju to bi bilo 8+ miliona feedback zapisa po frame-u, sto je previse za CPU da obradi u realnom vremenu
- Nepotrebno -- susedni pikseli gotovo uvek koriste istu stranicu, pa je redundantno
Zato se feedback generise na smanjenoj rezoluciji:
Ekran: 1920 x 1080 = 2,073,600 piksela
Feedback (1/8): 240 x 135 = 32,400 zapisa
Feedback (1/16): 120 x 68 = 8,160 zapisa
Svaki zapis u feedback buffer-u sadrzi:
FeedbackEntry:
- Virtual Texture ID: koji VT je koriscen (8 bita)
- Page X: X koordinata stranice (12 bita)
- Page Y: Y koordinata stranice (12 bita)
- Mip Level: potreban mip nivo (4 bita)
= Ukupno: 36 bita, pakuje se u 32 ili 64 bita
34.6.2 GPU-to-CPU readback
Nakon sto GPU zavrsi renderovanje frame-a i feedback buffer je popunjen, CPU mora da procita te podatke. Ovo je takozvani readback -- prenos podataka sa GPU memorije u CPU memoriju.
Readback je inherentno spor jer:
- GPU i CPU rade asinhrono
- Prenos podataka preko PCIe bus-a nije trenutan
- CPU mora da saceka da GPU zavrsi pisanje pre nego sto pocne citanje
Zato se tipicno koristi dvostepeni (double-buffered) pristup:
Frame N:
GPU renderuje scenu
GPU zapisuje feedback u Buffer A
CPU cita Buffer B (iz prethodnog frame-a)
Frame N+1:
GPU renderuje scenu
GPU zapisuje feedback u Buffer B
CPU cita Buffer A (iz prethodnog frame-a)
Frame N+2:
GPU renderuje scenu
GPU zapisuje feedback u Buffer A (ponovo)
CPU cita Buffer B (ponovo)
...
Ovo znaci da CPU uvek radi sa feedback podacima koji su bar 1 frame stari. Dodajte na to vreme za ucitavanje stranice sa diska, i ukupna latencija od "kamera se pomerila" do "nova stranica je vidljiva" moze biti 2-4 frame-a (ili vise ako je disk spor).
34.6.3 CPU obrada feedback-a
Kada CPU dobije feedback podatke, prolazi kroz sledece korake:
1. Deduplikacija:
Mnogo zapisa u feedback buffer-u ce referencirati istu stranicu (jer mnogo piksela na ekranu koristi istu stranicu). CPU eliminise duplikate.
Primer:
Feedback buffer ima 32,400 zapisa
Nakon deduplikacije: 150-500 unikatnih stranica
(zavisno od scene i kolicine vidljivih VT-ova)
2. Filtriranje vec ucitanih stranica:
CPU proverava page table i eliminise zahteve za stranice koje su vec u pool-u.
500 unikatnih zahteva
- 400 vec ucitanih = ignorisu se
= 100 novih zahteva za ucitavanje
3. Prioritizacija:
Preostalih 100 zahteva se sortira po prioritetu:
- Stranice u centru ekrana imaju visi prioritet
- Stranice na objektima koji su blizu kamere imaju visi prioritet
- Nizi mip nivoi (grublji, manji) imaju visi prioritet jer sluze kao fallback
- Stranice koje su potrebne vec vise frame-ova (stalan zahtev) imaju visi prioritet
4. Pokretanje ucitavanja:
CPU pokrece asinhrono ucitavanje prioritetnih stranica. Ovo koristi Unreal-ov asinhroni I/O sistem:
za svaku stranicu u prioritetnom redu:
1. Odredi poziciju stranice na disku (u .pak fajlu ili loose fajlu)
2. Pokreni async read sa diska
3. Kada podaci stignu u RAM:
a. Opciono: dekompresiraj (ako je komprimovano na disku)
b. Upload u VRAM page pool
c. Azuriraj page table (indirection teksturu)
4. Stranica je sada dostupna za shader
34.6.4 Budget i throttling
Engine ima budget (ogranicenje) za koliko stranica moze da ucita po frame-u. Ovo je vazno jer:
- Ucitavanje sa diska je sporo i ne sme da blokira game thread
- Upload u VRAM kosta vreme (DMA transfer)
- Azuriranje page table-a zahteva synchronizaciju sa GPU-om
Tipican budget je 8-32 stranice po frame-u. Ako ima vise zahteva nego sto budget dozvoljava, visak se odlaze za sledece frame-ove. To je razlog zasto ponekad vidite postepeno "izostrravanje" tekstura kada brzo pomerite kameru -- engine nije stigao da ucita sve stranice odjednom.
Ovaj budget se moze podesiti konzolnim komandama:
r.VT.MaxUploadsPerFrame -- Maksimalan broj upload-a po frame-u
r.VT.MaxContinuousUpdatesPerFrame -- Maksimalan broj continuous update-a
34.7 Landscape rendering sa RVT -- detaljna analiza
Sada cemo spojiti sve sto smo naucili i detaljno analizirati kako RVT transformise landscape rendering u praksi.
34.7.1 Tradicionalni landscape rendering pipeline
Bez RVT-a, landscape rendering izgleda ovako:
Za svaki piksel terena na ekranu (svaki frame):
1. Procitaj weight map(e) za ovaj piksel
-> Odredi tezine: Trava=0.6, Zemlja=0.3, Kamen=0.1
2. Za sloj "Trava" (tezina 0.6):
a. Izracunaj UV na osnovu tiling parametara
b. Sample Trava_BaseColor na tim UV-ima
c. Sample Trava_Normal na tim UV-ima
d. Sample Trava_Roughness na tim UV-ima
= 3 texture sample-a
3. Za sloj "Zemlja" (tezina 0.3):
a-d. Isto kao za travu
= 3 texture sample-a
4. Za sloj "Kamen" (tezina 0.1):
a-d. Isto
= 3 texture sample-a
5. Blenduj sve:
finalColor = Trava_Color * 0.6 + Zemlja_Color * 0.3 + Kamen_Color * 0.1
finalNormal = blend(Trava_N * 0.6, Zemlja_N * 0.3, Kamen_N * 0.1)
finalRoughness = Trava_R * 0.6 + Zemlja_R * 0.3 + Kamen_R * 0.1
6. Prosledi lighting sistemu
Racunica za 8 slojeva (worst case):
1 weight map read
8 slojeva x 3 teksture = 24 texture sample-a
+ blending racunanje
+ eventualni detail textures, macro variation, itd.
= 25-40+ texture sample operacija po pikselu
Na 4K @ 60fps: 8,294,400 piksela x 30+ reads x 60 = ~15 MILIJARDI texture reads/s
Ovo je ogroman pritisak na GPU texture unit-e i memorijski bandwidth.
34.7.2 Landscape rendering sa RVT
Sa RVT-om, isti teren se renderuje u dva prolaza:
Prolaz 1: RVT Update (retko, samo za nove/invalidirane stranice)
Za svaku RVT stranicu koja treba da se (re)generise:
1. Engine renderuje landscape material za tu stranicu
(isti kompleksan shader kao gore, sa svim slojevima i blending-om)
2. Rezultat se zapisuje u RVT page pool:
- RVT stranica za Base Color
- RVT stranica za Normal
- RVT stranica za Roughness
Ovo se desava JEDNOM za svaku stranicu (dok se ne invalidira).
Prolaz 2: Finalno renderovanje (svaki frame)
Za svaki piksel terena na ekranu:
1. Izracunaj UV u RVT prostoru
2. Procitaj indirection teksturu (1 texture read)
3. Izracunaj fizicke UV u page pool-u
4. Procitaj Base Color iz RVT pool-a (1 texture read)
5. Procitaj Normal iz RVT pool-a (1 texture read)
6. Procitaj Roughness iz RVT pool-a (1 texture read)
7. Prosledi lighting sistemu
= 4 texture sample operacija po pikselu (1 indirection + 3 RVT reads)
Usteda:
Tradicionalno: 25-40 texture reads po pikselu, svaki frame
Sa RVT-om: 4 texture reads po pikselu, svaki frame
+ povremeni skupi update za nove stranice
Usteda: ~85-90% manje texture reads po pikselu!
34.7.3 Component-based caching
Landscape u UE5 je podeljen na komponente (components) -- pravougaone sekcije terena. RVT sistem koristi ovu podelu za inteligentno kesiranje:
Landscape sa 4x4 komponente:
+---+---+---+---+
| A | B | C | D |
+---+---+---+---+
| E | F | G | H |
+---+---+---+---+
| I | J | K | L |
+---+---+---+---+
| M | N | O | P |
+---+---+---+---+
Svaka komponenta ima svoje RVT stranice.
Kada se promeni painting na komponenti F:
- Samo stranice za F se invalidiraju
- A, B, C, D, E, G, H, I, J, K, L, M, N, O, P ostaju kesirane
Ovo znaci da promena na jednom delu terena ne zahteva re-renderovanje celokupnog RVT-a -- samo pogodjena komponenta se azurira. Za veliki teren sa stotinama komponenti, ovo je kljucno za performanse.
34.7.4 Invalidacija -- kada i zasto
RVT stranice se invalidiraju u sledecim situacijama:
1. Promena landscape painting-a (u editoru):
Kada umetnik koristi landscape paint tool da promeni tezine slojeva na nekom delu terena, odgovarajuce RVT stranice se automatski invalidiraju.
2. Promena landscape geometrije (u editoru):
Sculpting terena (podizanje, spustanje, zaravnjivanje) menja geometriju, sto utice na materijale koji koriste World Position ili slope-based blending.
3. Dinamicke promene u igri:
Ako vasa igra menja teren u runtime-u (deformacija, proceduralni efekti), morate eksplicitno invalidirati pogodene stranice:
// C++ primer: invalidacija RVT-a
URuntimeVirtualTextureComponent* VTComponent = ...;
VTComponent->Invalidate(FBoxSphereBounds(ChangedArea));
4. Promena materijala:
Ako promenite parametre landscape materiala (npr. tiling, boju sloja), sve RVT stranice postaju zastarele i moraju se ponovo generisati.
5. Promena osvetljenja (za RVT koji ukljucuje lighting):
Ako vasa RVT konfiguracija ukljucuje lighting informacije (baked lighting u RVT), promena osvetljenja zahteva invalidaciju.
34.7.5 Rezolucija i kvalitet RVT-a
Jedna od najcescih nedoumica je: kolika rezolucija RVT-a je dovoljna?
RVT efektivno "zamrzava" landscape material na odredjenoj rezoluciji. Ako je RVT rezolucija preniska, videcete zamucenje (blurriness) na bliskim delovima terena. Ako je previsoka, trosice previse memorije i vremena za generisanje.
Prakticne smernice:
Velicina terena | Preporuceni Tile Count | Efektivna rezolucija
2 x 2 km | 256 | ~32K x 32K texela*
4 x 4 km | 512 | ~64K x 64K texela*
8 x 8 km | 512-1024 | ~64K-128K texela*
* Sa Tile Size od 128x128 texela
Ali ne morate pogadjati -- UE5 ima vizuelni debug prikaz koji vam pokazuje rezoluciju RVT-a na ekranu. Koristite konzolnu komandu:
r.VT.Borders 1 -- Pokazuje granice stranica
r.VT.ResidencyHeatMap 1 -- Heat mapa ucitanosti stranica
Ako vidite da su RVT stranice prevelike na ekranu (mali broj texela pokriva veliki deo ekrana), treba vam veci Tile Count. Ako su premale (mnogo texela za mali deo ekrana), mozete smanjiti Tile Count i ustedeti memoriju.
34.8 Performance i memorija -- prakticna razmatranja
Sada kada razumemo kako Virtual Textures funkcionisu, hajde da razgovaramo o prakticnim implikacijama na performanse i koriscenje memorije.
34.8.1 Kada Virtual Textures pomazu
VT sistem donosi najvecu korist u sledecim scenarijima:
1. Landscape sa mnogo slojeva (6+)
Ovo je "sweet spot" za RVT. Sa 6+ slojeva, tradicionalni pristup postaje veoma skup, a RVT dramaticno smanjuje broj texture reads.
Slojevi | Trad. reads/piksel | RVT reads/piksel | Usteda
4 | 13 | 4 | 69%
8 | 25 | 4 | 84%
12 | 37 | 4 | 89%
16 | 49 | 4 | 92%
2. Veliki open-world sa mnogo unikatnih tekstura
SVT pomaze kada ukupna kolicina texture podataka prevazilazi raspolozivi VRAM. Page-level streaming obezbedjuje da se memorija koristi samo za vidljive delove.
3. Filmska produkcija sa 8K+ teksturama
UDIM workflowovi i ultra-high-res teksture su prakticno nemoguce bez VT sistema.
4. Blending objekata sa terenom
RVT omogucava prirodan blending bez dodatnog rendering troska.
34.8.2 Kada Virtual Textures NISU pravo resenje
VT sistem ima overhead koji u nekim situacijama nije opravdan:
1. Jednostavne scene sa malo tekstura
Ako imate indoor scenu sa 10-20 tekstura od 2K, tradicionalni streaming radi sasvim dobro. VT overhead (indirection reads, feedback buffer, page management) nije opravdan.
2. Landscape sa malo slojeva (1-3)
Sa 1-3 sloja, tradicionalni shader je vec dovoljno efikasan. RVT overhead (generisanje stranica, dvostruki page pool za RVT i regularne teksture) moze da bude veci od ustede.
3. Veoma dinamicne teksture
Ako se tekstura menja svaki frame (npr. ekran monitora u igri, dinamicka water simulation), kesiranje u RVT nema smisla jer bi se stranice konstantno invalidirale.
4. Mali objekti sa malim teksturama
Za objekat koji koristi jednu 512x512 teksturu, VT dodaje complexity bez koristi. Cela tekstura ionako staje u VRAM bez problema.
34.8.3 Physical page pool -- sizing
Velicina page pool-a je kljucna odluka koja utice na kvalitet i performanse:
Premali pool:
+ Manje VRAM koriscenje
- Cesta eviction/reload ciklusa
- Vidljiv "blurry" efekat na teksturama
- Stalna aktivnost disk I/O
Preveliki pool:
+ Retke evictions
+ Ostar kvalitet tekstura
- Zauzima VRAM koji bi mogao da se koristi za druge svrhe
(shadow maps, render targets, framebuffer, itd.)
- Na hardveru sa malo VRAM-a, moze izazvati out-of-memory
Preporuke:
8 GB VRAM graficka: 256-512 MB page pool
12 GB VRAM graficka: 512-1024 MB page pool
16+ GB VRAM: 1-2 GB page pool (za filmsku produkciju)
Konzolna komanda za podesavanje:
r.VT.PoolSizeInMegabytes XXX -- Velicina fizickog pool-a
34.8.4 Page loading latency
Kao sto smo vec pomenuli, postoji inherentna latencija u VT sistemu:
Latencija od zahteva do vidljivosti:
Frame 0: Kamera se pomeri, novi deo scene vidljiv
Frame 1: GPU renderuje i generise feedback za nove stranice
Frame 2: CPU cita feedback (readback latency)
Frame 2: CPU pokrece async disk read
Frame 2-4: Podaci stizu sa diska u RAM
Frame 3-5: Upload iz RAM-a u VRAM page pool
Frame 4-6: Page table azuriran, stranica vidljiva
Ukupno: 2-6 frame-ova (33-100ms pri 60fps)
U praksi, ovo nije problem jer:
- Nizi mip nivoi su uvek ucitani kao fallback -- vidite blurry verziju odmah
- Ljudsko oko ne primecuje progresivno izostrravanje ako je dovoljno brzo (2-3 frame-a)
- Engine koristi speculative prefetching -- pokusava da predvidi koje ce stranice biti potrebne i ucitava ih unapred
Ali u nekim situacijama, latencija moze biti primetna:
- Brzo kretanje kamere (fast camera cut u filmu)
- Spor disk (HDD umesto SSD-a -- ovde SSD pravi ogromnu razliku!)
- Premali page pool (stalne evictions)
34.8.5 Feedback buffer overhead
Feedback buffer unosi sledece troskove:
GPU overhead:
- Pisanje u feedback buffer za svaki shader koji koristi VT: mali, ali ne zanemarljiv
- Smanjenje rezolucije feedback-a (1/8, 1/16) drasticno smanjuje overhead
- Na modernim GPU-ovima, ovo je obicno < 0.5ms po frame-u
CPU overhead:
- Readback sa GPU-a: moze izazvati sync point (pipeline stall) ako nije pravilno implementiran
- UE5 koristi async readback da minimizuje ovaj uticaj
- Obrada feedback podataka (deduplikacija, prioritizacija): zanemarljiva na modernim CPU-ovima
Memory overhead:
- Feedback buffer zauzima mali deo VRAM-a (tipicno < 1 MB)
- Indirection teksture: nekoliko MB za ceo sistem
- Page table metadata na CPU strani: zanemarljivo
34.8.6 Profiling Virtual Textures u UE5
UE5 pruza odlicne alate za profiling VT sistema:
Konzolne komande:
stat VirtualTexturing -- Opsta statistika (page requests, uploads, evictions)
stat VirtualTextureMemory -- Detaljne memorijske statistike
r.VT.Borders 1 -- Vizuelni prikaz granica stranica
r.VT.ResidencyHeatMap 1 -- Heat mapa koja pokazuje ucitanost stranica
r.VT.FeedbackFactor X -- Podesavanje velicine feedback buffer-a
Unreal Insights (profiler):
Virtual Texture operacije se pojavljuju u Unreal Insights profiler-u pod kategorijama:
- VirtualTexture -- generisanje RVT stranica, page management
- TextureStreaming -- ucitavanje SVT stranica sa diska
GPU profiler (RenderDoc, PIX, Nsight):
U GPU profiler-u mozete videti:
- Vreme utroseno na VT indirection reads
- Vreme utroseno na RVT page rendering
- Feedback buffer write operacije
34.8.7 Najbolje prakse
Na osnovu svega sto smo preSli, evo sazetih najboljih praksi:
1. Koristite RVT za landscape sa 4+ slojeva materijala. Ispod toga, overhead obicno ne opravdava ustedu.
2. Ne pretterujte sa RVT rezolucijom. Pocnite sa razumnom vrednosti (256-512 Tile Count za prosecnu mapu) i povecavajte samo ako vidite blurry teksture izbliza.
3. Koristite SSD. VT sistem intenzivno cita podatke sa diska. SSD dramaticno smanjuje page loading latenciju (sa 10-50ms na HDD-u na 0.1-1ms na SSD-u).
4. Podesite page pool velicinu prema hardveru. Ne treba vam isti pool na razvijnom racunaru sa 24 GB VRAM-a i na konzoli sa 8 GB deljene memorije. Koristite scalability settings.
5. Minimizirajte RVT invalidaciju u igri. Svaka invalidacija zahteva re-renderovanje stranica, sto je skupo. Ako imate dinamicke promene terena, pokusajte da ih lokalizujete.
6. Ne koristite VT za male teksture. Teksture manje od 512x512 nemaju koristi od VT sistema.
7. Grupisajte materijale u zajednicke RVT-ove. Umesto da svaki objekat ima svoj RVT, koristite zajednicke RVT-ove za grupe objekata (npr. sav teren deli jedan RVT).
8. Testirajte na ciljnom hardveru. VT performanse zavise od VRAM-a, bandwidth-a, disk brzine i GPU texture unit-a. Ono sto radi na vasem razvojnom racunaru mozda ne radi na minimum spec hardveru.
34.9 Napredne teme
34.9.1 Virtual Texture i Nanite
UE5-ov Nanite sistem (koji automatski upravlja geometrijom -- videti odgovarajuce poglavlje o Nanite-u) radi u tandemu sa Virtual Textures. Nanite automatski odredjuje LOD geometrije, a VT automatski odredjuje LOD tekstura. Zajedno, oni obezbeduju da i geometrija i teksture budu uvek na optimalnom nivou detalja za datu udaljenost od kamere.
Posebno, Nanite mesh-evi mogu koristiti SVT za svoje teksture, sto znaci da se i geometrija i teksture streamuju na page nivou. Ovo je posebno vazno za scene sa hiljadama unikatnih mesh-eva gde tradicionalni streaming ne bi mogao da se nosi sa kolicinom podataka.
34.9.2 Virtual Texture Lightmaps
UE5 podrzava Virtual Texture Lightmaps -- baked lightmaps koji se cuvaju kao Virtual Textures umesto kao tradicionalne teksture. Prednosti:
- Lightmaps za ogroman svet ne moraju svi biti u memoriji
- Samo vidljivi delovi lightmap-a se ucitavaju
- Posebno korisno za velike open-world igre sa baked lighting-om
Aktivacija: Project Settings > Rendering > Virtual Textures > Enable Virtual Texture Lightmaps
34.9.3 Adaptive Virtual Texture (AVT)
UE5 takodje nudi Adaptive Virtual Texture varijantu koja automatski prilagodjava rezoluciju stranica na osnovu udaljenosti od kamere:
- Blize kameri: stranice pune rezolucije
- Dalje od kamere: stranice nize rezolucije
- Automatska tranzicija bez vidljivih pop-in artefakata
Ovo je posebno korisno za velike svetove gde ne zelite da rucno podesavate LOD za teksture.
34.9.4 Compositing vise RVT-ova
Mozete koristiti vise RVT-ova za razlicite svrhe:
RVT 1: Landscape Base (Base Color, Normal, Roughness)
- Pokriva ceo landscape
- Sadrzi osnovni material terena
RVT 2: Landscape Detail (Detail Normal, Macro Variation)
- Pokriva ceo landscape
- Sadrzi dodatne detalje (puddle maps, snow coverage, itd.)
RVT 3: Object Blending (Base Color, World Height)
- Koristi se za blending objekata sa terenom
- Sadrzi informaciju o visini za depth blending
Vise RVT-ova pruza fleksibilnost ali povecava overhead (svaki RVT ima svoj page pool, indirection, itd.). Koristite mudro.
34.9.5 VT i ray tracing
Kada se koristi hardware ray tracing, VT sistem radi ali sa nekim ogranicenjima:
- Ray tracing shader-i mogu da citaju VT-ove
- Feedback buffer za ray tracing je poseban (jer pikseli mogu da pogode bilo koju povrsinu u sceni, ne samo vidljivu)
- Page loading latencija moze biti veca za ray traced refleksije i GI jer ti pixel-i cesto "vide" delove scene koji nisu direktno vidljivi kameri
34.10 Veza sa prethodnim poglavljima
Virtual Textures se oslanjaju na koncepte koje smo obradili ranije u knjizi:
Poglavlje 04 -- UV Mapping:
Virtual Textures i dalje koriste UV koordinate za mapiranje tekstura na geometriju. Razlika je u tome sto se UV koordinate sada "prevode" kroz indirection system u fizicke adrese u page pool-u. Razumevanje UV prostora (videti Poglavlje 04) je kljucno za razumevanje kako VT mapira virtualne koordinate u fizicke.
Poglavlje 05 -- Textures i Streaming:
U Poglavlju 05 smo obradili:
- Mipmaps -- VT ih koristi ali na page nivou umesto na mip nivou
- Texture compression (BC1, BC3, BC5, BC7) -- stranice u page pool-u su i dalje block-compressed; format kompresije je isti
- Tradicionalni texture streaming -- VT je evolucija ovog koncepta sa finom granulacijom (page umesto mip level)
Ako vam je bilo sta u ovom poglavlju nejasno, vratite se na Poglavlje 05 za osvezavanje znanja o osnovnim konceptima tekstura.
34.11 Rezime poglavlja
Prosli smo dugacak put u ovom poglavlju. Hajde da sumiramo kljucne tacke:
-
Problem: Tradicionalne teksture moraju biti cela u VRAM-u. Za velike svetove sa mnogo slojeva i velikih tekstura, ovo je neodrzivo.
-
Resenje: Virtual Textures dele teksture na male stranice (pages) i ucitavaju samo one koje su vidljive na ekranu.
-
Mehanizam: Page table (indirection texture) mapira virtualne UV koordinate u fizicke pozicije u page pool-u. Feedback buffer omogucava GPU-u da kaze CPU-u koje stranice su potrebne.
-
RVT (Runtime Virtual Textures): Generisu se u realnom vremenu. Kljucna primena je kesiranje kompleksnih landscape materijala -- izracunaj jednom, koristi mnogo puta. Dramaticno smanjuje shader complexity za landscape sa mnogo slojeva.
-
SVT (Streaming Virtual Textures): Primenjuju page-based streaming na tradicionalne teksture. Finija granularnost od mip-based streaming-a. Bolje koriscenje memorije.
-
Latencija: VT sistem ima inherentnu latenciju od 2-6 frame-ova. Fallback mip nivoi obezbedjuju da nikada ne vidite "crnu rupu" -- uvek postoji bar blurry verzija.
-
Trade-off: VT dodaje overhead (indirection reads, feedback buffer, page management). Koristan je za velike, kompleksne scene ali ne opravdava overhead za male, jednostavne scene.
Tabela kljucnih pojmova
| Termin (EN) | Opis |
|---|---|
| Virtual Texture (VT) | Tekstura podeljena na stranice od kojih se ucitavaju samo vidljive. Daje iluziju ogromne teksture sa malim memorijskim otiskom. |
| Page / Tile | Jedan blok virtuelne teksture, tipicno 128x128 ili 256x256 texela. Najmanja jedinica koja se ucitava/izbacuje iz memorije. |
| Physical Page Pool | Fiksni region VRAM-a u koji se smestavaju ucitane stranice. Funkcionise kao atlas tekstura. |
| Page Table | Struktura podataka (implementirana kao tekstura) koja mapira virtuelne adrese stranica u fizicke pozicije u page pool-u. |
| Indirection Texture | Nisko-rezoluciona tekstura koja sluzi kao page table. Shader je cita da bi pronasao fizicku lokaciju stranice. |
| Feedback Buffer | Nisko-rezolucioni bafer u koji GPU zapisuje koje stranice su mu potrebne i na kom mip nivou. CPU cita ovaj bafer da odredi koje stranice treba ucitati. |
| Runtime Virtual Texture (RVT) | Virtuelna tekstura ciji se sadrzaj generise u realnom vremenu (renderovanjem), a ne ucitava sa diska. Primarno se koristi za kesiranje landscape materijala. |
| Streaming Virtual Texture (SVT) | Tradicionalna tekstura kojom upravlja VT sistem. Stranice se ucitavaju sa diska umesto da se generisu. |
| Eviction | Izbacivanje stranice iz page pool-a da bi se oslobodio prostor za novu stranicu. Koristi se LRU politika. |
| Fallback | Nizi mip nivo koji se prikazuje dok se stranica pune rezolucije ucitava. Obezbedjuje da uvek postoji neka verzija teksture. |
| Invalidation | Oznacavanje RVT stranice kao zastarele (dirty) nakon promene na terenu. Stranica ce biti ponovo generisana. |
| Readback | Prenos podataka sa GPU memorije u CPU memoriju. Koristi se za citanje feedback buffer-a. Inherentno spor proces. |
| Page Border | Ivicni texeli oko svake stranice u pool-u, kopirani iz susednih stranica. Neophodan za korektno texture filtriranje. |
| Mip Level | Nivo u mipmap lancu. Mip 0 je puna rezolucija, svaki sledeci nivo je duplo manji u svakoj dimenziji. VT sistem upravlja stranicama na razlicitim mip nivoima nezavisno. |
| Two-level Page Table | Dvostepeni indirection mehanizam koji smanjuje velicinu page table-a za veoma velike virtuelne teksture. |
| UDIM | Standard za UV raspored gde se tekstura prostire preko vise UV tile-ova. SVT omogucava efikasno koriscenje UDIM tekstura. |
| Adaptive Virtual Texture (AVT) | Varijanta VT sistema koja automatski prilagodjava rezoluciju stranica na osnovu udaljenosti od kamere. |
Preporuceni resursi za dalje ucenje
-
Unreal Engine dokumentacija -- Virtual Textures:
- https://docs.unrealengine.com/5.0/en-US/virtual-texturing-in-unreal-engine/
- Zvanicna dokumentacija sa detaljnim opisom podesavanja i opcija.
-
GDC 2015 -- "Adaptive Virtual Texture Rendering in Far Cry 4":
- Ubisoft-ova prezentacija o prakticnoj primeni VT sistema u AAA igri. Odlican uvid u realne probleme i resenja.
-
GDC 2018 -- "Terrain Rendering in Far Cry 5":
- Nastavak prethodne prezentacije sa poboljsanim VT sistemom i lekcijama naucenim iz prethodne generacije.
-
"Software Virtual Textures" -- Sean Barrett (2008):
- Jedan od pionirskih radova o softverskom Virtual Texture sistemu. Pristupacno napisan i odlican za razumevanje fundamentalnih koncepata.
-
id Software -- "id Tech 5 Mega Texture Technology":
- John Carmack-ov MegaTexture sistem u id Tech 5 (Rage, 2011) bio je jedna od prvih komercijalnih implementacija VT koncepta u igrama. Istorijski vazan za razumevanje evolucije tehnologije.
-
Unreal Engine forum i community wiki:
- Aktivna zajednica sa mnogo prakticnih primera i resenja za specifine probleme.
-
YouTube -- "Unreal Engine Virtual Texture Deep Dive" (Epic Games):
- Epic-ov zvanicni deep dive video sa praktinom demonstracijom podesavanja i optimizacije VT sistema.
U sledecem poglavlju nastavicemo sa daljim tehnikama optimizacije renderovanja. Do tada, eksperimentisite sa RVT-om na vasom landscape-u -- razlika u performansama ce vas prijatno iznenaditi!