Poglavlje 46: Teksture i Memorija — Optimizacija

Poglavlje 46: Teksture i Memorija — Optimizacija

„Teksture su najlepši deo igre — i najskuplji. Naučite da upravljate njihovom memorijom, i vaša igra će raditi glatko na svakoj platformi."


Sadržaj poglavlja

  1. Uvod — Zašto je memorija tekstura toliko važna
  2. Texture Pool Budgeting — Kontrola VRAM-a
  3. Streaming Priority — Kako UE5 bira šta da učita
  4. Mip Bias — Globalni i per-texture pristup
  5. Virtual Textures za uštedu memorije
  6. Texture Compression — Kompromisi između kvaliteta i veličine
  7. Shared Textures i ponovna upotreba tekstura
  8. Texture Atlases za UI i 2D elemente
  9. Identifikovanje rasipničkih tekstura
  10. Praktični audit workflow
  11. Platform-specific budžeti za teksture
  12. Tabela ključnih pojmova
  13. Korisni linkovi i dodatno čitanje

46.1 Uvod — Zašto je memorija tekstura toliko važna {#461-uvod}

Dobrodošli u jedno od najvažnijih poglavlja ove knjige. Ako ste pratili naš put od nule do heroja, sada znate kako da napravite prelepe materijale, kako da uvezete teksture i kako da konfigurišete mip-mape (vidite Poglavlje 05). Znate i kako Virtual Textures funkcionišu na konceptualnom nivou (Poglavlje 34) i kako asset pipeline upravlja vašim resursima (Poglavlje 37). Sada je vreme da sve to povežemo u jednu koherentnu strategiju za upravljanje memorijom tekstura.

Zašto baš teksture?

U tipičnom UE5 projektu, teksture zauzimaju 60-80% ukupne memorije GPU-a (VRAM). To nije greška u dizajnu — to je prirodna posledica činjenice da su teksture ogromne. Jedna 4096×4096 tekstura u RGBA formatu bez kompresije zauzima 64 MB. Sa kompresijom (recimo BC7) to pada na oko 22 MB sa svim mip nivoima, ali kada imate stotine ili hiljade takvih tekstura u sceni, brojevi brzo rastu.

Evo šta se dešava u praksi:

Rezolucija Format Bez kompresije BC1 (DXT1) BC7
1024×1024 RGBA 4 MB 0.5 MB 1 MB
2048×2048 RGBA 16 MB 2 MB 4 MB
4096×4096 RGBA 64 MB 8 MB 16 MB
8192×8192 RGBA 256 MB 32 MB 64 MB

Tabela 46.1: Veličine tekstura u memoriji po rezoluciji i formatu (uključujući sve mip nivoe, veličine su približne).

Kada vaša igra cilja GPU sa 8 GB VRAM-a (što je i dalje veoma česta konfiguracija na PC-u, a konzole imaju slične ograničene budžete), i kada uzmete u obzir da frame buffer, depth buffer, render targets i drugi resursi zauzimaju 2-3 GB, ostaje vam možda 5 GB za teksture. Pet gigabajta zvuči mnogo — dok ne shvatite da 300 tekstura u 4K rezoluciji sa BC7 kompresijom zauzima skoro 5 GB.

Šta ćete naučiti u ovom poglavlju

Ovo poglavlje pokriva kompletnu strategiju za upravljanje memorijom tekstura u UE5:

Hajde da počnemo.


46.2 Texture Pool Budgeting — Kontrola VRAM-a {#462-texture-pool-budgeting}

Šta je Texture Pool?

Texture pool je UE5-ov sistem za upravljanje ukupnom količinom VRAM-a koju teksture smeju da zauzmu. Zamislite ga kao budžet za mesečne troškove — imate fiksnu sumu, i morate da odlučite kako da je raspodelite.

Kada engine učitava teksture, on ne učitava uvek sve mip nivoe svake teksture. Umesto toga, on prati koliko memorije je trenutno zauzeto i, ako se približava limitu, počinje da snižava rezoluciju (učitava niže mip nivoe) manje važnih tekstura da bi ostao u budžetu.

Podešavanje Texture Pool limita

Texture pool limit se podešava preko console varijable:

r.Streaming.PoolSize=2048

Ova vrednost je u megabajtima. Dakle, 2048 znači da UE5 sme da koristi do 2 GB VRAM-a za streamovane teksture.

Možete ovo podesiti na više mesta:

1. Preko konzole u editoru ili runtime-u:

r.Streaming.PoolSize 3072

2. Preko DefaultEngine.ini:

[SystemSettings]
r.Streaming.PoolSize=2048

3. Preko Scalability settings (preporučeno za shipping):

; Engine/Config/BaseScalability.ini ili vaš CustomScalability.ini

[TextureQuality@0]    ; Low
r.Streaming.PoolSize=1024

[TextureQuality@1]    ; Medium
r.Streaming.PoolSize=1536

[TextureQuality@2]    ; High
r.Streaming.PoolSize=2048

[TextureQuality@3]    ; Epic
r.Streaming.PoolSize=3072

[TextureQuality@Cinematic]
r.Streaming.PoolSize=4096

Savet: Scalability settings su pravi način za shipping jer se automatski prilagođavaju hardveru igrača. Više o scalability sistemu možete naći u poglavljima o performansama.

Šta se dešava kada se pool prekorači?

Ovo je kritično pitanje koje mnogi developeri ne razumeju dovoljno. Kada texture streaming sistem detektuje da je pool pun, dešava se sledeće:

  1. Detekcija prekoračenja — Streaming manager proverava ukupnu potrošnju nakon svakog frame-a (ili u definisanim intervalima).

  2. Prioritizacija — Sistem sortira sve streamovane teksture po važnosti (o prioritetima ćemo detaljno u sledećem odeljku).

  3. Degradacija manje važnih tekstura — Teksture sa najnižim prioritetom dobijaju komandu da izbace svoje najviše mip nivoe (highest-resolution mips) iz memorije. Ovo se dešava postepeno — ne u jednom frame-u.

  4. „Mip dropping" — Umesto da se tekstura učita u punoj rezoluciji (recimo 4096×4096), učitava se samo do 2048×2048 ili čak 1024×1024, u zavisnosti od toga koliko je pool pod pritiskom.

  5. Vizuelni artefakti — Ako je pool drastično premali, videćete zamućene teksture (blurry textures) čak i na objektima koji su blizu kamere. Ovo je najočigledniji znak da vam treba veći pool ili bolja optimizacija.

Vizuelni primer degradacije:

Pool stanje:     | Tekstura blizu kamere    | Tekstura daleko
-----------------+--------------------------+------------------
Pool slobodan    | 4096×4096 (full res)     | 2048×2048
Pool 80% pun     | 4096×4096 (full res)     | 1024×1024
Pool 95% pun     | 2048×2048 (degradiran!)  | 512×512
Pool prekoračen  | 1024×1024 (vidljivo!)    | 256×256

Kako da odredite pravi pool size

Ne postoji univerzalan odgovor, ali evo smernica:

Za PC (shipping):

Za konzole:

Upozorenje: Ovi brojevi su smernice, ne pravila. Vaš projekat može zahtevati drugačije vrednosti u zavisnosti od broja i veličine tekstura, kompleksnosti scene i drugih faktora.

Monitoring texture pool-a u realnom vremenu

UE5 nudi nekoliko načina za praćenje stanja texture pool-a:

Stat komande:

stat streaming        ; Opšte informacije o streaming sistemu
stat streamingoverview ; Detaljan pregled streaming stanja
stat streamingdetails  ; Per-tekstura informacije

Console varijable za debug:

r.Streaming.PoolSize           ; Trenutni limit
r.Streaming.UsedSize           ; Trenutna potrošnja (read-only)
r.Streaming.OverBudget         ; Koliko ste preko budžeta
r.Streaming.FullyLoadedTextureSize ; Koliko bi zauzelo sve na max res

Texture Streaming vizualizacija:

U editoru, idite na View Mode → Optimization Viewmodes → Texture Streaming Accuracy. Ovo prikazuje scenu obojenu prema tome koliko je svaka tekstura blizu svog idealnog mip nivoa:

Plava boja je jednako loša kao crvena — znači da trošite VRAM na nepotrebno visoke mip nivoe.

Texture Pool i ne-streamovane teksture

Važno je razumeti da ne ulaze sve teksture u texture pool. Sledeće teksture se NE streamuju i zauzimaju VRAM nezavisno od pool limita:

Ovo znači da vaš stvarni VRAM budžet za streamovane teksture može biti znatno manji od ukupnog VRAM-a. Uvek računajte koliko „fiksnih" tekstura imate pre nego što odredite pool size.


46.3 Streaming Priority — Kako UE5 bira šta da učita {#463-streaming-priority}

Osnove streaming sistema

UE5-ov texture streaming sistem je sofisticiran i uzima u obzir mnogo faktora kada odlučuje koje teksture treba da budu na punoj rezoluciji, a koje mogu da se degradiraju. Razumevanje ovog sistema je ključno za optimizaciju.

Faktori koji utiču na streaming prioritet

1. Screen Size (Veličina na ekranu)

Ovo je najvažniji faktor. Engine izračunava koliko piksela tekstura zauzima na ekranu i na osnovu toga određuje koji mip nivo je potreban. Formula je u suštini:

IdealMipLevel = log2(TextureSize / ScreenPixelsCovered)

Ako tekstura od 2048×2048 pokriva samo 64×64 piksela na ekranu, idealan mip nivo je mip 5 (2048 / 64 = 32, ali se računa po osi, pa 2048→1024→512→256→128→64, što je mip 5).

2. Udaljenost od kamere

Udaljenost od kamere direktno utiče na screen size, ali engine je koristi i kao sekundarni faktor. Objekti koji su bliže kameri dobijaju viši prioritet čak i ako imaju sličan screen size kao udaljeni objekti (jer je veća verovatnoća da će igrač da ih pogleda izbliza).

3. Boost Factor

Svaka tekstura može imati Streaming Priority boost u svom asset editoru. Ova vrednost se koristi kao množilac prioriteta:

// U Texture Editor → Details → Level of Detail
LOD Bias = 0          // Bez promene
Streaming Priority = 1.0  // Normalan (default)
Streaming Priority = 2.0  // Dvostruki prioritet

Kada koristiti boost: Koristite viši prioritet za teksture koje su uvek vidljive i kritične za kvalitet — recimo, tekstura glavnog lika, oružja u prvom licu, ili ključnih HUD elemenata koji se renderuju u world space.

4. Forced Mip Levels

Neke teksture možete prisiliti da uvek budu na određenom mip nivou:

// U Texture Editor → Details → Level of Detail
Min LOD Size = 512     // Nikada neće pasti ispod 512x512
Max LOD Size = 2048    // Nikada neće biti veća od 2048x2048

Ovo je korisno za:

5. Vidljivost (Visibility)

UE5 koristi informacije iz rendering pipeline-a da odredi da li je objekat sa teksturom vidljiv. Teksture na objektima koji nisu vidljivi (occluded ili izvan frustum-a) dobijaju niži prioritet i postepeno se degradiraju.

Međutim, ovo nije instant — engine zadržava teksture u memoriji neko vreme nakon što objekat prestane da bude vidljiv, za slučaj da se igrač brzo okrene. Ovo se kontroliše preko:

r.Streaming.HiddenPrimitiveScale=0.5

Vrednost 0.5 znači da skriveni objekti koriste polovinu svog normalnog prioriteta. Vrednost 0.0 bi značila da se teksture skrivenih objekata odmah degradiraju (što može dovesti do pop-in efekata).

6. Manually Prioritized Areas (Level Streaming)

Kada koristite Level Streaming, možete postaviti Texture Streaming Volume u svetu koji kaže engine-u: „Teksture u ovom volumenu su važne, drži ih na visokoj rezoluciji."

// U Blueprints ili C++
UTextureStreamingVolume* Volume = ...;
Volume->StreamingUsage = SVB_ForceOn;  // Uvek streemuj na max

Kako streaming odluke funkcionišu — korak po korak

Evo simplifikovanog, ali tačnog opisa onoga što se dešava u svakom frame-u (ili svakih nekoliko frame-ova):

1. Engine prikuplja listu svih streamovanih tekstura u sceni.

2. Za svaku teksturu izračunava "wanted mip level":
   - Proverava sve instance te teksture u svetu
   - Za svaku instancu računa screen size
   - Uzima najviši (best quality) wanted mip od svih instanci
   - Primenjuje boost faktor i eventualne Min/Max LOD ograničenja

3. Sortira sve teksture po prioritetu (wanted mip level × boost × visibility).

4. Počinje da "popunjava" pool od vrha prioriteta ka dnu:
   - Tekstura 1 (highest priority): učitaj wanted mip level
   - Tekstura 2: učitaj wanted mip level
   - ...
   - Tekstura N: pool je pun, smanji mip level za 1
   - Tekstura N+1: smanji mip level za 2
   - itd.

5. Šalje zahteve za loading/unloading mip nivoa async I/O sistemu.

6. Mip nivoi se učitavaju/izbacuju tokom sledećih frame-ova
   (ne instant — da bi se izbegao stuttering).

Latencija streaming-a i pop-in

Jedan od najčešćih vizuelnih problema sa texture streaming-om je pop-in — efekat kada se tekstura naglo promeni iz blurry u sharp dok je igrate. Ovo se dešava jer učitavanje mip nivoa sa diska zahteva vreme.

Faktori koji utiču na pop-in:

Kako smanjiti pop-in:

; Povećajte "lookahead" streaming-a
r.Streaming.Boost=1.5          ; Traži mip nivoe unapred (default 1.0)
r.Streaming.MinMipForSplitRequest=0  ; Dozvoli split učitavanje (mali mip odmah, veliki kasnije)

; Koristite preload-ovanje za poznate tranzicije
; (recimo pre otvaranja vrata u novu sobu)

Takođe, razmislite o korišćenju Texture Streaming preload volumes oko ključnih tačaka u nivou — postavljanjem ovih volumena oko uglova, vrata i teleportera, engine može da počne da učitava teksture pre nego što igrač stigne do njih.


46.4 Mip Bias — Globalni i per-texture pristup {#464-mip-bias}

Šta je Mip Bias?

Mip bias je offset koji se dodaje na izračunati idealni mip nivo teksture. Pozitivan bias znači „koristi niži mip nivo" (manje detalja, manje memorije), dok negativan bias znači „koristi viši mip nivo" (više detalja, više memorije).

Efektivan mip nivo = Izračunati idealni mip + Mip Bias

Primer sa teksturom 4096×4096:
  Idealni mip = 2 (→ 1024×1024)
  Mip Bias = +1 → Efektivno mip 3 (→ 512×512)    // Ušteda memorije
  Mip Bias = -1 → Efektivno mip 1 (→ 2048×2048)   // Više detalja
  Mip Bias = 0  → Efektivno mip 2 (→ 1024×1024)   // Normalno

Globalni Mip Bias

Globalni mip bias se primenjuje na SVE streamovane teksture u sceni:

r.Streaming.MipBias=0        ; Default — bez promene
r.Streaming.MipBias=1        ; Sve teksture gube jedan mip nivo
r.Streaming.MipBias=2        ; Sve teksture gube dva mip nivoa
r.Streaming.MipBias=-1       ; Sve teksture dobijaju jedan mip nivo više

Globalni mip bias od +1 može da prepolovi potrošnju memorije za teksture (jer svaki mip nivo je 4× manji od prethodnog u ukupnoj površini, ali u praksi ušteda je manja jer niži mip nivoi su već mali).

Tipična upotreba globalnog mip bias-a:

; U Scalability settings:
[TextureQuality@0]    ; Low
r.Streaming.MipBias=2
r.Streaming.PoolSize=1024

[TextureQuality@1]    ; Medium
r.Streaming.MipBias=1
r.Streaming.PoolSize=1536

[TextureQuality@2]    ; High
r.Streaming.MipBias=0
r.Streaming.PoolSize=2048

[TextureQuality@3]    ; Epic
r.Streaming.MipBias=0
r.Streaming.PoolSize=3072

Per-Texture Mip Bias

Možete postaviti mip bias i na individualnu teksturu. Ovo se radi u Texture Editor → Details → Level of Detail → LOD Bias:

LOD Bias = 0    ; Normalno (default)
LOD Bias = 1    ; Ova tekstura uvek gubi jedan mip nivo
LOD Bias = -1   ; Ova tekstura uvek dobija jedan mip nivo više

Kada koristiti per-texture bias:

Mip Bias i TSR (Temporal Super Resolution)

Ovo je jedna od najmoćnijih tehnika u UE5 za optimizaciju memorije tekstura, i zaslužuje posebnu pažnju.

TSR (Temporal Super Resolution) je UE5-ov ugrađeni upscaler koji renderuje scenu na nižoj rezoluciji i zatim je pametno skalira na izlaznu rezoluciju. Na primer, može da renderuje na 1080p i skalira na 4K, dajući rezultat koji je veoma blizak nativnom 4K.

Ključna stvar: TSR koristi informacije iz više frame-ova da rekonstruiše detalje. To znači da može da izvuče više detalja iz tekstura nego što bi jedan frame mogao. Zbog toga ima smisla koristiti negativan mip bias sa TSR-om — dajte TSR-u teksture sa više detalja, i on će te detalje bolje rekonstruisati.

; Kada je TSR aktivan (tipično na "Quality" ili "Balanced" preset-u):
r.Streaming.MipBias=-1

; Ovo znači: učitaj teksture na jedan mip nivo višoj rezoluciji
; nego što bi inače trebalo. TSR će koristiti te ekstra detalje
; za bolju rekonstrukciju slike.

Ali pažnja! Negativan mip bias povećava potrošnju memorije. Morate to kompenzovati:

; Primer konfiguracije za TSR sa negativnim mip bias-om:
[SystemSettings]
; TSR na "Quality" mode-u renderuje na ~67% rezolucije
r.TemporalAA.Upsampling=1
r.ScreenPercentage=67

; Negativan mip bias za bolje TSR rezultate
r.Streaming.MipBias=-1

; ALI: povećajte pool size da kompenzujete
r.Streaming.PoolSize=3072

Matematika:

Bez negativnog mip bias-a:
  - Teksture: 2.0 GB u poolu
  - TSR kvalitet: dobar

Sa mip bias = -1:
  - Teksture: ~3.0-3.5 GB u poolu (svaka tekstura zauzima više)
  - TSR kvalitet: odličan (vidljivo poboljšanje na finim detaljima)

Ušteda od nižeg render resolution-a (67% vs 100%):
  - Frame buffer i GBuffer: ~55% manje memorije
  - Ova ušteda može da kompenzuje veći texture pool

Pro tip: Epic Games koristi ovu tehniku u Fortnite-u i The Matrix Awakens demo-u. Negativan mip bias od -1 sa TSR-om na Quality preset-u daje rezultate koji su subjektivno bolji od nativne rezolucije bez TSR-a, uz manju ukupnu GPU potrošnju (jer je render resolution niži).

Mip Bias per-material (napredna tehnika)

U nekim slučajevima, želite da primenite mip bias samo na određene materijale, ne na celu teksturu (jer ista tekstura može biti korišćena u više materijala). To se radi u Material Editor-u pomoću Texture Sample node-a:

// U Material Editor-u:
// Texture Sample node → Advanced → MipValueMode = "MipLevel" ili "MipBias"
// Zatim povežite konstantu ili parametar na Mip Level input

// Za MipBias mode:
MipBias input = -1.0   // Jedan nivo više detalja u ovom materijalu
MipBias input = ScalarParameter("TextureMipBias")  // Kontrolisano parametrom

Ovo je korisno kada imate shared teksture (o kojima ćemo govoriti kasnije) gde ista tekstura treba da bude oštrija u jednom materijalu a manje oštra u drugom.


46.5 Virtual Textures za uštedu memorije {#465-virtual-textures}

Virtual Textures su jedna od najvažnijih tehnologija za upravljanje memorijom tekstura u modernim game engine-ima. Ako ste pročitali Poglavlje 34, znate osnove. Ovde ćemo se fokusirati specifično na aspekte memorije i optimizacije.

Kratki podsetnik: Šta su Virtual Textures?

Tradicionalno, svaka tekstura se učitava u memoriju u celosti (ili bar do određenog mip nivoa). Virtual Textures (VT) menjaju ovu paradigmu — umesto da učitavaju cele teksture, oni učitavaju samo stranice (pages) koje su zaista potrebne za trenutni frame.

Zamislite ogromnu teksturu od 32768×32768 piksela. Bez VT, morali biste da je učitate celu (ili bar nekoliko mip nivoa). Sa VT, engine učitava samo one delove (tiles/pages) koje kamera zaista vidi. Ako kamera gleda samo u jedan ugao te teksture, samo taj deo je u memoriji.

Dva tipa Virtual Textures u UE5

1. Runtime Virtual Texture (RVT)

RVT se generiše u realnom vremenu tokom gameplay-a. Najčešća upotreba je za landscape materijale.

Kako RVT štedi memoriju za landscape:

Tradicionalni pristup za landscape sa 4 layer-a:
  - Layer 1 (Trava): Albedo 4K + Normal 4K = ~32 MB
  - Layer 2 (Zemlja): Albedo 4K + Normal 4K = ~32 MB
  - Layer 3 (Stena): Albedo 4K + Normal 4K = ~32 MB
  - Layer 4 (Pesak): Albedo 4K + Normal 4K = ~32 MB
  - Blend mapa: 4K = ~16 MB
  - UKUPNO u memoriji: ~144 MB
  (I svaki tile landscape-a ponavlja ovo!)

RVT pristup:
  - Iste izvorne teksture, ALI:
  - Engine renderuje samo vidljive delove u RVT cache
  - RVT cache veličina: 128 MB (fiksna, konfigurabilna)
  - Cache pokriva CEO landscape, ne samo jedan tile
  - Potrošnja memorije ne raste sa brojem layer-a!

Podešavanje RVT cache-a:

; U DefaultEngine.ini ili Project Settings → Rendering → Virtual Textures
r.VT.PoolSizeInMB=128           ; Ukupna veličina VT page pool-a
r.VT.TileSize=128                ; Veličina jednog tile-a u pikselima
r.VT.TileBorderSize=4            ; Border za filtriranje
r.VT.MaxAnisotropy=8             ; Anisotropic filtering nivo

Primer RVT podešavanja za landscape:

  1. Kreirajte Runtime Virtual Texture asset (Content Browser → desni klik → Textures → Runtime Virtual Texture)
  2. Postavite tip na "Base Color, Normal, Roughness, Specular" ili potrebne kanale
  3. U landscape Actor-u, dodajte Runtime Virtual Texture Volume komponentu
  4. U landscape materijalu, koristite Runtime Virtual Texture Output node za izlaz
  5. Koristite Runtime Virtual Texture Sample node u mesh materijalima da čitate iz RVT-a (za blending terena sa meshevima)
// Landscape material (pojednostavljen):
// Standardni layer blending → RVT Output node
//
// Mesh material koji se blenda sa terenom:
// Runtime Virtual Texture Sample → Lerp sa mesh teksturom
//   basiran na visini ili normali

Memorijska ušteda sa RVT za landscape:

Scenario Bez RVT Sa RVT Ušteda
4 terrain layer-a, mali level ~200 MB ~128 MB (cache) 36%
4 terrain layer-a, ogroman open world ~800 MB+ ~128 MB (cache) 84%!
8 terrain layer-a, ogroman open world ~1.6 GB+ ~128 MB (cache) 92%!

Ključna prednost RVT-a je da je memorijska potrošnja fiksna — ne raste sa veličinom sveta ili brojem layer-a.

2. Streaming Virtual Texture (SVT)

SVT je „pravi" virtual texture sistem koji radi sa unapred pripremljenim teksturama (nije runtime-generated). SVT deli teksturu na stranice (pages) i učitava samo one koje su potrebne.

Kako SVT page-level streaming radi:

Tekstura 8192×8192, SVT tile size 128:
  - Podeljeno na 64×64 = 4096 tile-ova (stranica)
  - Plus mip-ovi: 32×32 + 16×16 + 8×8 + ... tile-ova

Bez SVT:
  - Cela tekstura u memoriji: ~64 MB (BC7)
  
Sa SVT:
  - Samo vidljivi tile-ovi se učitavaju
  - Tipično 10-30% teksture je vidljivo u jednom frame-u
  - Realna potrošnja: ~6-20 MB za ovu teksturu

Aktiviranje SVT za teksturu:

  1. Otvorite teksturu u editoru
  2. U Details panelu: Virtual Texture Streaming → Enable (checkbox)
  3. Reimportujte ili Apply changes

Ili globalno za sve nove teksture:

; U DefaultEditor.ini
[/Script/UnrealEd.MaterialEditorOptions]
bDefaultVirtualTextureStreaming=True

Podešavanje SVT page pool-a:

r.VT.PoolSizeInMB=256         ; Ukupna veličina VT stranica u memoriji
r.VT.MaxUploadsPerFrame=8      ; Koliko novih stranica se učitava po frame-u
r.VT.MaxPagesProducedPerFrame=32 ; Max novih stranica generisanih po frame-u

Kada koristiti Virtual Textures

Koristite RVT za:

Koristite SVT za:

Ne koristite VT za:

Virtual Texture debugging

; Vizualizacija VT stranica
r.VT.Borders=1                  ; Prikaži granice tile-ova
r.VT.Feedback.Resolution=1024   ; Rezolucija feedback buffer-a

; Statistike
stat VirtualTextureMemory        ; Memorija VT sistema
stat VirtualTexturing            ; Performanse VT sistema

Napomena: Više detalja o Virtual Textures implementaciji, uključujući napredne scenarije i debugging, možete naći u Poglavlju 34.


46.6 Texture Compression — Kompromisi između kvaliteta i veličine {#466-texture-compression}

Pregled formata kompresije

UE5 podržava mnogo formata kompresije tekstura, ali za desktop i konzole, dva dominiraju: BC1 (ranije DXT1) i BC7. Razumevanje razlika između njih je ključno za optimizaciju.

BC1 (DXT1) — Brzi i mali

Karakteristike:

Kada koristiti BC1:

BC3 (DXT5) — BC1 sa boljom alphom

Karakteristike:

Kada koristiti BC3:

BC5 — Za Normal mape

Karakteristike:

Kada koristiti BC5:

Važno: UE5 podrazumevano koristi BC5 za normal mape. Ako ručno menjate kompresiju normal mape, nikada ne koristite BC1 — artefakti su užasni na normalama.

BC7 — Visoki kvalitet, veća veličina

Karakteristike:

Kada koristiti BC7:

Uporedna tabela

Osobina BC1 (DXT1) BC3 (DXT5) BC5 BC7
Veličina (bpp) 4 8 8 8
RGB kvalitet ★★☆☆☆ ★★☆☆☆ N/A ★★★★★
Alpha 1-bit/nema 8-bit N/A 8-bit
Normal mape ★☆☆☆☆ ★★☆☆☆ ★★★★★ ★★★★☆
Build vreme Brzo Brzo Brzo Sporo
Upotreba Roughness, maske Albedo+alpha Normal mape Kvalitetni albedo

Kako odabrati kompresiju u UE5

U Texture Editor → Details → Compression:

Compression Settings:
  - Default (DXT1/5, BC1/3)     — Engine bira BC1 ili BC3 automatski
  - Normalmap (DXT5, BC5)        — Za normal mape
  - BC7                          — Visoki kvalitet
  - HDR (RGBA16F)                — Za HDR teksture (skybox, lightmape)
  - VectorDisplacementmap        — Za displacement mape
  - Grayscale (G8, BC4)          — Za single-channel teksture
  - Alpha (BC4)                  — Za alpha-only teksture
  - DistanceFieldFont            — Za SDF fontove

Strategija kompresije za tipičan projekat

Evo preporučene strategije za izbor kompresije:

Albedo/Base Color:
  - Glavni lik, oružje, vozila → BC7
  - Okruženje (zidovi, pod, plafon) → BC7 ili Default
  - Pozadinski objekti, props → Default (BC1)
  - Nebo, oblaci → BC7

Normal mape:
  - SVE → Normalmap (BC5) — bez izuzetka!

Roughness/Metallic/AO (packed):
  - ORM mape (packed R=AO, G=Roughness, B=Metallic) → Default (BC1)
  - Pojedinačne channel mape → Grayscale (BC4)

Alpha/Opacity:
  - Smooth alpha (lišće, kosa) → BC3 ili BC7
  - Binary alpha (prozori, ograde) → BC1 sa alpha

Emissive:
  - LDR emissive → Default ili BC7
  - HDR emissive → HDR (RGBA16F)

Maske:
  - Jednostavne maske → Grayscale (BC4)
  - Višekanalne maske → Default (BC1)

Kompresija i vizuelni kvalitet — čest problem

Jedan od najčešćih vizuelnih problema sa BC1 kompresijom su blok artefakti (block artifacts). Ovi artefakti su posebno vidljivi na:

Ako primetite ove artefakte, prebacite teksturu na BC7. Razlika u veličini je 2× (BC7 je duplo veća od BC1), ali je kvalitet drastično bolji.

ASTC — Za mobilne platforme

Ako ciljate mobilne platforme (Android, iOS), koristićete ASTC kompresiju umesto BC formata:

ASTC 4×4:   1 bajt/piksel  — Najviši kvalitet, kao BC7
ASTC 6×6:   0.89 b/p       — Veoma dobar kvalitet
ASTC 8×8:   0.5 b/p        — Dobar kvalitet, kao BC1
ASTC 12×12: 0.22 b/p       — Nizak kvalitet, za memorijski kritične situacije

UE5 automatski koristi ASTC za Android i iOS build-ove. Možete kontrolisati ASTC kvalitet per-tekstura ili globalno.


46.7 Shared Textures i ponovna upotreba tekstura {#467-shared-textures}

Filozofija ponovne upotrebe

Jedan od najefektivnijih načina da smanjite memorijsku potrošnju tekstura nije optimizacija pojedinačnih tekstura — već korišćenje istih tekstura na više mesta. Ovo je fundamentalni princip art pipeline-a u igrama.

Trim Sheet teksture

Trim sheet je tekstura koja sadrži više manjih elemenata poređanih u trake ili grid, dizajniranih da se koriste na različitim meshevima pomoću pažljivog UV mappinga.

Primer Trim Sheet layout-a:
┌─────────────────────────┐
│  Metal ivica  │  Šraf   │
├─────────────────────────┤
│  Beton panel  │  Rešetka│
├─────────────────────────┤
│  Drvo daska   │  Čelik  │
├─────────────────────────┤
│  Plastika     │  Guma   │
└─────────────────────────┘

Prednosti trim sheet-a za memoriju:

Bez trim sheet-a:
  - Metal ivica: 2K albedo + 2K normal + 2K ORM = ~12 MB
  - Beton panel: 2K × 3 = ~12 MB
  - Drvo daska: 2K × 3 = ~12 MB
  - Čelik: 2K × 3 = ~12 MB
  Ukupno: ~48 MB za 4 materijala

Sa trim sheet-om:
  - Jedna 4K trim sheet: 4K albedo + 4K normal + 4K ORM = ~48 MB
  ALI: pokriva 8+ materijala, ne 4!
  - Efektivno: ~6 MB po materijalu

Još bolje sa 2K trim sheet-om:
  - 2K × 3 = ~12 MB za 8+ materijala
  - Efektivno: ~1.5 MB po materijalu!

Tiling materijali

Tiling (ponavljajuće) teksture su još jedan moćan alat za uštedu memorije. Umesto da imate jednu ogromnu unique teksturu za svaki zid u igri, koristite malu tiling teksturu koja se ponavlja:

Unique tekstura za zid 10m × 3m:
  - Potrebna rezolucija za dobar texel density: 4096×1024
  - Memorija: ~8 MB (BC7)
  - Problem: Svaki zid je jedinstvena tekstura!

Tiling tekstura za isti zid:
  - Rezolucija: 1024×1024 (ponavlja se)
  - Memorija: ~1 MB (BC7)
  - Ista tekstura za SVE zidove istog materijala!

Kako izbećit monotoniju tiling-a:

Tiling teksture mogu izgledati repetitivno. Evo tehnika za razbijanje ponavljanja:

  1. Detail teksture — Dodatni layer detalja koji se ponavlja na drugoj frekvenciji
  2. Macro varijacija — Maska velike skale koja varira boju/intenzitet
  3. Decals — Lokalni detalji (prljavština, ogrebotine) postavljeni preko tiling materijala
  4. Vertex color blending — Mešanje varijacija koristeći per-vertex podatke
// U Material Editor-u, kombinacija tiling-a sa varijacijom:
//
// Tiling albedo (1K, tile UV × 4)
//    ↓
// Lerp ← Macro variation mask (512×512, tile UV × 0.1)
//    ↓
// Multiply ← Detail texture (512×512, tile UV × 8)
//    ↓
// Final Base Color
//
// Ukupna memorija: 1 MB + 0.25 MB + 0.25 MB = ~1.5 MB
// Pokriva ogromne površine bez vidljivog ponavljanja!

Material Instances i deljenje tekstura

Material Instances su ključni za efikasnu ponovnu upotrebu tekstura. Osnovna ideja: jedan parent materijal definiše logiku, a instance menjaju samo parametre (boje, vrednosti) ili teksture.

Ali pravi trik je ovo: više material instanci može deliti iste bazne teksture uz promenu samo parametara:

Parent Material: M_StandardSurface
  ├── Albedo Texture (parametar)
  ├── Normal Texture (parametar)  
  ├── Tint Color (parametar)
  ├── Roughness Value (parametar)
  └── UV Tiling (parametar)

MI_BrickRed (instance):
  ├── Albedo: T_Brick_Albedo      ← Deljena tekstura!
  ├── Normal: T_Brick_Normal      ← Deljena tekstura!
  ├── Tint: (0.8, 0.3, 0.2)      ← Samo parametar
  ├── Roughness: 0.85             ← Samo parametar
  └── UV Tiling: (2, 2)           ← Samo parametar

MI_BrickGray (instance):
  ├── Albedo: T_Brick_Albedo      ← ISTA tekstura!
  ├── Normal: T_Brick_Normal      ← ISTA tekstura!
  ├── Tint: (0.5, 0.5, 0.5)      ← Samo drugi parametar
  ├── Roughness: 0.9              ← Samo parametar
  └── UV Tiling: (2, 2)           ← Samo parametar

Memorija: JEDNA kopija T_Brick_Albedo i T_Brick_Normal u VRAM-u
          Dve instance koriste istu memoriju za teksture!

Channel Packing

Channel packing je tehnika gde se više single-channel informacija pakuje u jednu teksturu koristeći R, G, B i A kanale:

Standardni pristup (4 teksture):
  - T_AO.tga (grayscale)        → 2K BC4 = ~0.5 MB
  - T_Roughness.tga (grayscale)  → 2K BC4 = ~0.5 MB
  - T_Metallic.tga (grayscale)   → 2K BC4 = ~0.5 MB
  - T_Opacity.tga (grayscale)    → 2K BC4 = ~0.5 MB
  Ukupno: 2.0 MB, 4 texture sample-a u shader-u

Channel-packed pristup (1 tekstura):
  - T_ORM.tga:
    R = Ambient Occlusion
    G = Roughness
    B = Metallic
    (A = Opacity, ako je potreban)
  - 2K BC1 (ako nema alpha) = ~0.5 MB
  - 2K BC3 (sa alpha) = ~1.0 MB
  Ukupno: 0.5-1.0 MB, 1 texture sample u shader-u!

Prednosti:

Konvencija pakovanja u UE5: UE5 i mnogi AAA studiji koriste ORM konvenciju:

Napomena: Kada pakujete kanale, koristite teksture bez sRGB korekcije! Roughness, Metallic i AO su linearne vrednosti. U UE5, uverite se da je sRGB checkbox ISKLJUČEN za packed teksture.


46.8 Texture Atlases za UI i 2D elemente {#468-texture-atlases}

Šta je Texture Atlas?

Texture atlas je velika tekstura koja sadrži mnogo manjih slika (sprites, ikone, UI elemente) poređanih zajedno. Umesto da svaki UI element bude zasebna tekstura, svi su u jednoj velikoj slici, a UV koordinate određuju koji deo se koristi za koji element.

Zašto koristiti atlase za UI?

1. Smanjenje Draw Call-ova

Ovo je možda i važnija prednost od uštede memorije. Svaka zasebna tekstura zahteva promenu stanja GPU-a (texture binding), što znači novi draw call. Sa atlasom:

Bez atlasa:
  - 50 ikona u inventaru = 50 različitih tekstura
  - Minimum 50 draw call-ova samo za ikone
  - Plus font tekstura, background, i ostali UI
  - Ukupno: 100+ draw call-ova za UI

Sa atlasom:
  - 50 ikona u jednom atlasu = 1 tekstura
  - Sve ikone u 1-2 draw call-a (batched)
  - Ukupno: 10-20 draw call-ova za UI

2. Ušteda memorije

Mnogo malih tekstura zauzima više memorije od jedne velike zbog:

Bez atlasa:
  - 64 ikone, svaka 128×128, BC3
  - 64 × (128×128 × 1 byte + mip chain overhead + metadata)
  - ≈ 64 × ~21.5 KB = ~1.34 MB + overhead

Sa atlasom:
  - 1 atlas 1024×1024, BC3 (sadrži svih 64 ikona u 8×8 grid-u)
  - 1 × ~1 MB + minimalan overhead
  - Ušteda: ~25%+ plus dramatično manje draw call-ova

Kako napraviti Texture Atlas u UE5

Metod 1: Paper2D Sprite Atlas (za 2D igre)

1. Content Browser → desni klik → Paper2D → Sprite Atlas
2. Dodajte teksture u atlas
3. Podesite Atlas Max Width/Height
4. Generate Atlas

Metod 2: UMG/Slate sa atlasima

Za UI, UE5 koristi Slate Brush sistem. Možete ručno kreirati atlas i koristiti UV offsete:

// U UMG Widget Blueprint-u ili C++:
// Koristite jednu atlas teksturu
// Podesite UV region za svaku ikonu

FSlateIcon MyIcon;
MyIcon.SetResourceObject(AtlasTexture);
MyIcon.UVRegion = FBox2D(
    FVector2D(0.0, 0.0),    // Top-left UV
    FVector2D(0.125, 0.125)  // Bottom-right UV (1/8 atlasa)
);

Metod 3: Automatski atlas sa Texture Packer (eksterni alat)

Mnogi timovi koriste eksterne alate kao TexturePacker ili ShoeBox za generisanje atlasa:

  1. Exportujte sve ikone kao zasebne PNG-ove
  2. Importujte u TexturePacker
  3. Generišite atlas + JSON/XML sa UV koordinatama
  4. Importujte atlas u UE5
  5. Parsirajte UV podatke u vašem UI kodu

Best practices za atlase

  1. Grupisanje po upotrebi — Stavite zajedno ikone koje se prikazuju na istom ekranu
  2. Power-of-two dimenzije — Atlas treba da bude 512×512, 1024×1024, 2048×2048, itd.
  3. Padding između elemenata — Ostavite 1-2 piksela prostora između ikona da izbegnete bleeding
  4. Mip-map oprez — Na nižim mip nivoima, bliske ikone mogu da „procure" jedna u drugu; koristite dovoljno padding-a ili isključite mip-mape za UI atlase
  5. Ne preterujte sa veličinom — Atlas od 4096×4096 koji je samo 30% popunjen je gori od dve 1024×1024 teksture

Atlasi i Font rendering

UE5-ov font rendering sistem već koristi atlase interno. Svaki font generiše glyph atlas koji sadrži sve korišćene karaktere. Možete kontrolisati ovo:

// U Font asset settings:
// Font Cache Type: Runtime (generisani atlas)
// Atlas Width/Height: 1024 (default)
// Max Font Atlas Pages: 1-4

Za lokalizovane igre sa velikim character set-ovima (kineski, japanski, korejski), font atlasi mogu postati značajan izvor memorijske potrošnje. U tom slučaju:


46.9 Identifikovanje rasipničkih tekstura {#469-identifikovanje-rasipnickih-tekstura}

Tri kategorije rasipanja

Rasipničke teksture obično spadaju u jednu od tri kategorije:

  1. Prevelike teksture — Tekstura ima veću rezoluciju nego što je ikada potrebno
  2. Nekorišćene teksture — Tekstura je u projektu ali se ne koristi nigde
  3. Nepotreban sadržaj — Tekstura ima kanale ili podatke koji nisu potrebni

Hajde da svaku kategoriju razmotrimo detaljno.

Kategorija 1: Prevelike teksture (texel density mismatch)

Ovo je najčešći oblik rasipanja. Tekstura je 4096×4096, ali objekat na koji se primenjuje nikada ne zauzima dovoljno piksela na ekranu da bi ta rezolucija bila vidljiva.

Kako proceniti pravu veličinu teksture:

Idealna rezolucija teksture zavisi od:

Tipični texel density standardi:
  - AAA first-person igra: 10-20 px/cm (blizu kamere)
  - AAA third-person igra: 5-10 px/cm
  - Open world igra (srednji plan): 2-5 px/cm
  - Pozadinski objekti: 1-2 px/cm

Formula za potrebnu rezoluciju:

TextureSize = ObjectSize(cm) × TexelDensity(px/cm)

Primer 1: Kutija 100cm × 100cm, texel density 10 px/cm
  TextureSize = 100 × 10 = 1000 → zaokružite na 1024×1024

Primer 2: Zid 500cm × 300cm, texel density 5 px/cm
  TextureSize = 500 × 5 = 2500 → 2048×2048 je dovoljan
  (4096 bi bio rasipanje za texel density od 5 px/cm!)

Primer 3: Mali prop (čaša) 10cm × 15cm, texel density 10 px/cm
  TextureSize = 15 × 10 = 150 → 256×256 je sasvim dovoljan!
  (Tekstura od 2048×2048 za čašu je ogromno rasipanje!)

UE5 alat za vizualizaciju texel density-ja:

; View Mode → Optimization → Texture Streaming Accuracy
; Ovo vam pokazuje gde su teksture prevelike (plavo) ili premale (crveno)

; Texture density vizualizacija:
; View Mode → Optimization → Texel Density
; Prikazuje uniformni grid da vidite koliko je texel density konzistentan

Kategorija 2: Nekorišćeni mip nivoi

Čest problem je tekstura koja ima mip nivo 0 (punu rezoluciju) od 4096×4096, ali taj mip nivo se nikada ne učitava jer objekat nikada nije dovoljno blizu kameri.

Kako identifikovati ovo:

; Tokom gameplay-a, koristite:
stat streamingdetails

; Ovo prikazuje za svaku teksturu:
; - Wanted Mip: koji mip nivo je potreban
; - Loaded Mip: koji mip nivo je trenutno učitan
; - Max Mip: koji je najviši dostupan mip nivo
;
; Ako vidite teksture gde Max Mip = 0 (4096) ali
; Wanted Mip nikada ne pada ispod 2 (1024),
; ta tekstura je nepotrebno velika!

Rešenje: Postavite Max LOD Size u teksturi da ograničite maksimalnu rezoluciju:

// U Texture Editor → Details → Level of Detail
Max LOD Size = 2048   // Ova tekstura nikada neće biti veća od 2048×2048
                      // čak i ako je source fajl 4096×4096

Ili koristite LOD Group za automatsko ograničenje:

// LOD Groups u Project Settings → Engine → Texture
// Grupisani limiti po kategoriji:

TEXTUREGROUP_World:          MaxLODSize=2048
TEXTUREGROUP_WorldNormalMap: MaxLODSize=2048
TEXTUREGROUP_Character:      MaxLODSize=4096   // Karakteri zaslužuju veću rezoluciju
TEXTUREGROUP_CharacterNormalMap: MaxLODSize=2048
TEXTUREGROUP_Weapon:         MaxLODSize=2048
TEXTUREGROUP_UI:             MaxLODSize=1024
TEXTUREGROUP_Skybox:         MaxLODSize=2048
TEXTUREGROUP_Effects:        MaxLODSize=1024

Kategorija 3: Nepotreban alpha kanal

Ovo je iznenađujuće čest problem. Mnoge teksture su importovane kao RGBA (sa alpha kanalom) iako alpha kanal nije potreban. Pošto BC3/BC7 sa alphom zauzima duplo memorije u odnosu na BC1 bez alpha-e, ovo je značajno rasipanje.

Kako identifikovati:

1. Otvorite teksturu u Texture Editor-u
2. Kliknite na "Alpha" dugme u toolbar-u da vidite alpha kanal
3. Ako je alpha kanal potpuno beo (255) — nije potreban!
4. Promenite Compression na "Default (DXT1/BC1, no alpha)"

Automatizovano čišćenje:

# Python skripta za UE5 Editor (Editor Utility Script)
import unreal

asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()
texture_assets = asset_registry.get_assets_by_class(
    unreal.TopLevelAssetPath("/Script/Engine", "Texture2D")
)

for asset_data in texture_assets:
    texture = asset_data.get_asset()
    if texture:
        # Proveri da li tekstura ima nepotreban alpha kanal
        if texture.has_alpha_channel and texture.compression_settings == \
           unreal.TextureCompressionSettings.TC_DEFAULT:
            # Loguj za ručnu proveru
            unreal.log(f"Mogući nepotreban alpha: {asset_data.asset_name}")

Čest scenario rasipanja — studija slučaja

Zamislite tipičan UE5 projekat — third-person RPG. Nakon audita, pronalazimo:

PROBLEMATIČNE TEKSTURE:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. T_RockWall_Albedo (4096×4096, BC7)
   Problem: Koristi se na pozadinskim stenama koje igrač nikada
   ne vidi izbliza. Wanted mip je uvek 2+.
   Rešenje: Max LOD Size = 2048. Ušteda: ~12 MB

2. T_Barrel_Albedo (4096×4096, BC7)
   Problem: Bure je 50cm visoko sa texel density od 80 px/cm.
   Standardni props ne treba da pređu 10 px/cm.
   Rešenje: Smanji na 1024×1024. Ušteda: ~15 MB

3. T_TreeLeaf_Albedo (2048×2048, BC3)
   Problem: Alpha kanal je potpuno beo — nema prozirnih delova
   u OVOJ teksturi (alpha je u zasebnoj maski).
   Rešenje: Prebaci na BC1. Ušteda: ~2 MB

4. T_OldWall_01 do T_OldWall_15 (svaka 2048×2048, BC7)
   Problem: 15 skoro identičnih zidnih tekstura sa minimalnim
   razlikama. Mogu se zameniti sa 2-3 tiling teksture + varijacije.
   Rešenje: Konsoliduj u 3 teksture. Ušteda: ~48 MB

5. T_Debug_Grid (4096×4096, BC7)
   Problem: Debug tekstura koja je ostala u projektu.
   Rešenje: Obriši. Ušteda: ~16 MB

UKUPNA POTENCIJALNA UŠTEDA: ~93 MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

93 MB ne zvuči mnogo, ali ovo je samo 5 primera od potencijalno stotina tekstura. U praksi, temeljni audit može da uštedi 500 MB - 2 GB u velikom projektu.


46.10 Praktični audit workflow za memoriju tekstura {#4610-prakticni-audit-workflow}

Korak 1: Prikupljanje podataka

Pre svega, potreban vam je pregled celokupne situacije sa teksturama u projektu.

Size Map u Content Browser-u:

1. Content Browser → desni klik na folder → Size Map
2. Filtrirajte po Texture2D asset tipu
3. Vizuelizacija pokazuje relativne veličine svih tekstura
4. Kliknite na najveće "balone" — to su vaši prioriteti za optimizaciju

Texture Statistics komanda:

; U konzoli:
ListTextures                    ; Lista SVIH učitanih tekstura sa veličinama
ListTextures sorted=size        ; Sortirano po veličini (najveće prvo)
ListTextures sorted=group       ; Grupisano po LOD grupi

Reference Viewer:

1. Desni klik na teksturu → Reference Viewer
2. Vidite koji materijali/meshevi koriste ovu teksturu
3. Ako nema referenci — kandidat za brisanje!

Korak 2: Identifikovanje "top offenders"

Fokusirajte se na teksture koje zauzimaju najviše memorije. U većini projekata, 20% tekstura zauzima 80% memorije (Pareto princip važi i ovde).

Skripta za identifikovanje najvećih tekstura:

# Editor Utility Script (Python)
import unreal

asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()

# Prikupi sve Texture2D asset-e
texture_list = []
textures = asset_registry.get_assets_by_class(
    unreal.TopLevelAssetPath("/Script/Engine", "Texture2D")
)

for asset_data in textures:
    tex = asset_data.get_asset()
    if tex:
        size_x = tex.blueprint_get_size_x()
        size_y = tex.blueprint_get_size_y()
        # Proceni memoriju (pojednostavljeno)
        bpp = 8 if tex.compression_settings in [
            unreal.TextureCompressionSettings.TC_BC7,
            unreal.TextureCompressionSettings.TC_NORMALMAP
        ] else 4
        mem_kb = (size_x * size_y * bpp) / 8 / 1024
        texture_list.append((asset_data.package_name, size_x, size_y, mem_kb))

# Sortiraj po memoriji (najveće prvo)
texture_list.sort(key=lambda x: x[3], reverse=True)

# Prikaži top 50
unreal.log("=== TOP 50 TEKSTURA PO MEMORIJI ===")
for i, (name, sx, sy, mem) in enumerate(texture_list[:50]):
    unreal.log(f"{i+1}. {name}: {sx}x{sy} = {mem:.0f} KB ({mem/1024:.1f} MB)")

Korak 3: Analiza texel density-ja

Za svaku od "top offender" tekstura, proverite da li je rezolucija opravdana.

Checklist za svaku teksturu:

□ Na kom objektu se koristi?
□ Koliko je taj objekat velik u svetu (world units)?
□ Koliko blizu kamera može da priđe?
□ Koji je ciljni texel density za tu kategoriju objekta?
□ Koja rezolucija je potrebna na osnovu kalkulacije?
□ Da li je tekstura veća od potrebne? Koliko?
□ Da li tekstura ima nepotreban alpha kanal?
□ Da li se ista ili slična tekstura koristi na više objekata?
   (Kandidat za deljenje/atlas)

Korak 4: Provera nekorišćenih tekstura

Nekorišćene teksture su „mrtav teret" koji povećava veličinu build-a i (ponekad) potrošnju memorije.

; Način 1: Reference Viewer za jednu teksturu
; Desni klik → Reference Viewer → proveri referencu

; Način 2: Batch proveravame svih tekstura
; Editor Utility → "Audit Assets" window
; Window → Developer Tools → Audit Assets
; Filtriraj po "Unreferenced" statusu

; Način 3: Console komanda za učitane teksture
obj list class=Texture2D

Skripta za pronalaženje nekorišćenih tekstura:

# Editor Utility Script
import unreal

asset_registry = unreal.AssetRegistryHelpers.get_asset_registry()
textures = asset_registry.get_assets_by_class(
    unreal.TopLevelAssetPath("/Script/Engine", "Texture2D")
)

unreferenced = []
for asset_data in textures:
    # Proveri da li bilo šta referencira ovu teksturu
    refs = asset_registry.get_referencers(
        asset_data.package_name,
        unreal.AssetRegistryDependencyOptions()
    )
    if len(refs) <= 1:  # 1 = samo self-referenca
        unreferenced.append(asset_data.package_name)

unreal.log(f"=== NEREFERENCIRANIH TEKSTURA: {len(unreferenced)} ===")
for name in unreferenced:
    unreal.log(f"  - {name}")

Korak 5: Provera streaming efikasnosti

Tokom gameplay-a, proverite da li streaming sistem radi efikasno.

Gameplay audit procedura:

1. Pokrenite igru sa sledećim komandama:
   stat streaming
   stat streamingdetails

2. Igrajte normalno 5-10 minuta

3. Obratite pažnju na:
   - "Over Budget" vrednost u stat streaming
     → Ako je stalno > 0, pool je premali
   - "Wanted/Loaded mip" razlike u stat streamingdetails
     → Velike razlike = loš streaming, pop-in problemi
   - "Num Wanted" vs "Num Streaming" brojeve
     → Ako je Num Wanted >> Num Streaming, I/O je bottleneck

4. Uključite vizuelizaciju:
   viewmode texturestreamingaccuracy
   → Crvene oblasti = problem (under-streamed)
   → Plave oblasti = rasipanje (over-streamed)

5. Zapišite problematična mesta za dalju analizu

Korak 6: Kreiranje akcionog plana

Na osnovu prikupljenih podataka, napravite prioritizovanu listu akcija:

PRIORITET 1 (Najveći uticaj, najmanji napor):
  □ Smanjiti nepotrebno velike teksture na pravu veličinu
  □ Ukloniti nepotrebne alpha kanale
  □ Obrisati nekorišćene teksture
  □ Podesiti texture pool size ispravno

PRIORITET 2 (Značajan uticaj, srednji napor):
  □ Prebaciti odgovarajuće teksture na BC1 umesto BC7
  □ Implementirati channel packing za ORM mape
  □ Podesiti LOD Group limite
  □ Dodati per-texture streaming priority za kritične teksture

PRIORITET 3 (Dugoročne investicije):
  □ Konvertovati repetitivne teksture u tiling materijale
  □ Kreirati trim sheet-ove za modularne objekte
  □ Implementirati RVT za landscape
  □ Razmotriti SVT za velike unique teksture
  □ Kreirati texture atlase za UI

Korak 7: Validacija nakon optimizacije

Nakon primene optimizacija, ponovo pokrenite audit da potvrdite rezultate:

Metrike za praćenje:
  ├── Ukupna veličina tekstura u build-u (MB)
  ├── Peak VRAM potrošnja tokom gameplay-a (MB)
  ├── Prosečan procenat texture pool-a u upotrebi (%)
  ├── Broj tekstura sa "Over Budget" statusom
  ├── Pop-in incidenti po minutu gameplay-a
  └── Vizuelni kvalitet (subjektivna ocena, ali važna!)

Savet za tim: Automatizujte audit proces koliko god možete. Kreirajte Editor Utility Widgets ili skripte koje će vaš tim moći da pokrene jednim klikom. Uključite audit u vaš CI/CD pipeline (vidite Poglavlje 37 za više o asset pipeline-u).


46.11 Platform-specific budžeti za teksture {#4611-platform-specific-budzeti}

Zašto su platform-specific budžeti potrebni?

Različite platforme imaju drastično različite količine dostupne memorije i različite GPU arhitekture. Tekstura koja savršeno radi na PC-u sa 12 GB VRAM-a može da sruši igru na Nintendo Switch-u sa 4 GB ukupne RAM memorije.

UE5 nudi robustan sistem za upravljanje platform-specific podešavanjima tekstura.

Pregled memorijskih budžeta po platformama

┌─────────────────────────────────────────────────────────────────┐
│                    MEMORIJSKI BUDŽETI                           │
├─────────────────┬──────────────┬────────────┬──────────────────┤
│    Platforma    │ Ukupna mem.  │ Za teksture│    Napomena      │
├─────────────────┼──────────────┼────────────┼──────────────────┤
│ PC (Low-end)    │ 4 GB VRAM    │ 1.0-1.5 GB │ GTX 1650, itd.  │
│ PC (Mid-range)  │ 8 GB VRAM    │ 2.0-3.0 GB │ RTX 3060/4060   │
│ PC (High-end)   │ 12+ GB VRAM  │ 3.0-5.0 GB │ RTX 3080+       │
│ PS5             │ 16 GB unified│ 2.5-3.5 GB │ Deli sa CPU      │
│ Xbox Series X   │ 10+6 GB      │ 2.5-3.5 GB │ 10GB brza mem.  │
│ Xbox Series S   │ 8 GB unified │ 1.5-2.0 GB │ Cilja 1080-1440p│
│ Nintendo Switch │ 4 GB unified │ 0.5-1.0 GB │ Veoma ograničeno│
│ Steam Deck      │ 16 GB unified│ 1.5-2.5 GB │ APU, deli sa CPU│
│ Android (mid)   │ 3-4 GB       │ 0.5-1.0 GB │ ASTC kompresija  │
│ iOS (modern)    │ 6 GB unified │ 1.0-2.0 GB │ ASTC kompresija  │
└─────────────────┴──────────────┴────────────┴──────────────────┘

Platform-specific teksture u UE5

UE5 omogućava različita podešavanja tekstura za različite platforme.

1. Per-Platform Texture Settings:

U Texture Editor-u, možete overridovati podešavanja za svaku platformu:

Texture Editor → Details → Per Platform Settings
  ├── Windows
  │   ├── Max Texture Size: 4096
  │   └── Compression: BC7
  ├── PS5
  │   ├── Max Texture Size: 4096
  │   └── Compression: BC7
  ├── XboxSeriesX
  │   ├── Max Texture Size: 4096
  │   └── Compression: BC7
  ├── XboxSeriesS
  │   ├── Max Texture Size: 2048      ← Niža za Series S
  │   └── Compression: BC7
  ├── Switch
  │   ├── Max Texture Size: 1024      ← Znatno niža za Switch
  │   └── Compression: ASTC_6x6       ← Drugačija kompresija
  └── Android
      ├── Max Texture Size: 2048
      └── Compression: ASTC_6x6

2. LOD Group per-platform limiti:

; DefaultDeviceProfiles.ini

[Windows DeviceProfile]
+TextureLODGroups=(Group=TEXTUREGROUP_World, MaxLODSize=4096)
+TextureLODGroups=(Group=TEXTUREGROUP_Character, MaxLODSize=4096)

[XboxSeriesS DeviceProfile]
+TextureLODGroups=(Group=TEXTUREGROUP_World, MaxLODSize=2048)
+TextureLODGroups=(Group=TEXTUREGROUP_Character, MaxLODSize=2048)

[Switch DeviceProfile]
+TextureLODGroups=(Group=TEXTUREGROUP_World, MaxLODSize=1024)
+TextureLODGroups=(Group=TEXTUREGROUP_Character, MaxLODSize=1024)
+TextureLODGroups=(Group=TEXTUREGROUP_Skybox, MaxLODSize=512)

3. Scalability per-platform:

; DefaultScalability.ini

[TextureQuality@0]    ; Low (Switch, low-end mobile)
r.Streaming.PoolSize=512
r.Streaming.MipBias=2

[TextureQuality@1]    ; Medium (Xbox Series S, mid mobile)
r.Streaming.PoolSize=1024
r.Streaming.MipBias=1

[TextureQuality@2]    ; High (PS5, Xbox Series X)
r.Streaming.PoolSize=2048
r.Streaming.MipBias=0

[TextureQuality@3]    ; Epic (High-end PC)
r.Streaming.PoolSize=3072
r.Streaming.MipBias=0

Strategije za multi-platform projekte

Strategija 1: „Najviša rezolucija + automatsko smanjenje"

Ovo je najjednostavniji pristup:

Prednosti: Jednostavno, manje posla za art tim Mane: Niže platforme dobijaju samo blurry verzije, ne optimizovane teksture

Strategija 2: „Per-platform source teksture"

Napredniji pristup:

Prednosti: Najbolji kvalitet na svakoj platformi Mane: Mnogo više posla za art tim, komplikovaniji pipeline

Strategija 3: „Hibridni pristup" (preporučeno)

Kombinacija prethodna dva:

Xbox Series X specifičnosti — brza vs spora memorija

Xbox Series X ima neobičnu memorijsku arhitekturu: 10 GB „brze" memorije (10 GB/s bandwidth) i 6 GB „spore" memorije (4.8 GB/s). Ovo utiče na texture streaming:

Brza memorija (10 GB):
  - Render targets, frame buffer
  - Aktivne (hot) teksture — one koje se trenutno renderuju
  - Ukupno za igru: ~8.5 GB (sa OS overhead)

Spora memorija (6 GB):
  - Audio bufferi
  - Manje kritični resursi
  - „Hladne" teksture — učitane ali ne aktivno korišćene
  - Ukupno za igru: ~3 GB

Strategija za Xbox Series X:
  - Držite texture pool u bržoj memoriji
  - Koristite async streaming za prebacivanje iz spore u brzu memoriju
  - UE5 GDK (Game Development Kit) automatski upravlja ovime
    ali možete fine-tune-ovati kroz GDK podešavanja

Nintendo Switch optimizacija

Switch zahteva posebnu pažnju jer je memorijski budžet veoma ograničen.

Switch-specific saveti:

1. Max tekstura rezolucija: 1024×1024 (retko 2048)
2. Koristite ASTC 6×6 ili 8×8 kompresiju
3. Agresivan mip bias: +2 ili čak +3
4. Texture pool: 512-768 MB
5. Razmotrite unique low-res teksture za Switch
   (ne samo downscale od PC verzije)
6. Izbegavajte Virtual Textures na Switch-u
   (overhead može biti prevelik)
7. Koristite agresivniji LOD za mesheve
   (manje poligona = manje vidljivih tekstura)

Mobilne platforme

Za Android i iOS:

1. ASTC je standard (ne BC formati!)
2. Čuvajte se memorijskog pritiska od OS-a
   (Android može ubiti igru bez upozorenja)
3. Tipičan budžet: 500 MB - 1.5 GB za teksture
4. Koristite Adaptive Performance za dinamičko prilagođavanje
5. Power-of-two teksture su OBAVEZNE na nekim starijim GPU-ovima
6. ETC2 kao fallback za starije uređaje bez ASTC podrške

46.12 Tabela ključnih pojmova {#4612-tabela-kljucnih-pojmova}

Pojam (engleski) Objašnjenje
Texture Pool VRAM budžet koji UE5 dodeljuje za streamovane teksture. Kontroliše koliko ukupne memorije GPU-a smeju da zauzmu teksture.
Mip Level (Mip Map) Umanjena verzija teksture. Mip 0 je puna rezolucija, Mip 1 je polovina, Mip 2 četvrtina, itd. Koristi se za optimizaciju i filtriranje. Vidite Poglavlje 05.
Mip Bias Offset koji se dodaje na idealni mip nivo. Pozitivan bias = niža rezolucija (ušteda memorije). Negativan bias = viša rezolucija (više detalja).
Texture Streaming Sistem koji dinamički učitava i izbacuje mip nivoe tekstura na osnovu potrebe, umesto da drži sve teksture u punoj rezoluciji u memoriji.
Streaming Priority Numerička vrednost koja određuje koliko je važno da tekstura bude na visokoj rezoluciji. Zavisi od veličine na ekranu, udaljenosti od kamere i korisničkih podešavanja.
TSR (Temporal Super Resolution) UE5-ov ugrađeni upscaler koji renderuje na nižoj rezoluciji i rekonstruiše sliku koristeći podatke iz više frame-ova. Može da iskoristi negativan mip bias za bolji kvalitet.
RVT (Runtime Virtual Texture) Virtual Texture koji se generiše u realnom vremenu. Najčešće korišćen za landscape materijale i blending sa terenom. Fiksna memorijska potrošnja. Vidite Poglavlje 34.
SVT (Streaming Virtual Texture) Virtual Texture koji koristi page-level streaming za unapred pripremljene teksture. Učitava samo vidljive delove teksture. Vidite Poglavlje 34.
BC1 (DXT1) Format kompresije tekstura sa odnosom 8:1. Mali, brz, ali niži kvalitet. Bez alpha kanala (ili samo 1-bit alpha).
BC3 (DXT5) Format kompresije sa odnosom 4:1. Kao BC1 za RGB, ali sa punim 8-bit alpha kanalom.
BC5 Format kompresije za dva kanala. Koristi se za Normal mape (R i G kanali).
BC7 Moderni format kompresije sa odnosom 4:1. Značajno bolji kvalitet od BC1. Sporija kompresija pri build-u.
ASTC Adaptive Scalable Texture Compression. Koristi se na mobilnim i nekim konzolnim platformama. Fleksibilan block size (4×4 do 12×12).
Texel Density Broj piksela teksture po jedinici svetske veličine (obično pikseli po centimetru). Koristi se za određivanje odgovarajuće rezolucije teksture.
Trim Sheet Tekstura koja sadrži više materijala/detalja u trakama, dizajnirana za UV mapping na različite mesheve. Štedi memoriju kroz ponovnu upotrebu.
Channel Packing Tehnika pakovanja više grayscale informacija (AO, Roughness, Metallic) u R, G, B (i A) kanale jedne teksture.
Texture Atlas Velika tekstura koja sadrži mnogo manjih slika (sprites, ikone). Smanjuje draw call-ove i memorijski overhead.
LOD Group Kategorija tekstura u UE5 koja omogućava grupno podešavanje maksimalne rezolucije i streaming ponašanja.
LOD Bias Per-texture offset za mip level selekciju. Razlikuje se od globalnog Mip Bias-a po tome što se primenjuje samo na jednu teksturu.
Pool Size Veličina texture pool-a u megabajtima. Osnovna kontrola za ukupnu potrošnju VRAM-a za teksture. r.Streaming.PoolSize.
Over Budget Stanje kada ukupna potrebna memorija za teksture premašuje texture pool limit. Engine degradira mip nivoe da se vrati u budžet.
Pop-in Vizuelni artefakt gde se tekstura naglo menja iz niske u visoku rezoluciju dok igrač gleda. Posledica latencije texture streaming-a.
Scalability Settings UE5-ov sistem za automatsko prilagođavanje kvaliteta grafike (uključujući teksture) na osnovu hardvera igrača.
Device Profile UE5-ov sistem za per-platform podešavanja. Omogućava različite texture quality, pool size i kompresiju po platformi.
Never Stream Podešavanje na teksturi koje sprečava da se tekstura streamuje. Tekstura je uvek u memoriji na punoj rezoluciji. Koristite oprezno.
Texture Streaming Volume Volume actor u sceni koji utiče na streaming prioritet tekstura unutar svog prostora.
Size Map UE5 alat koji vizuelno prikazuje relativne veličine asset-a u projektu. Koristan za identifikovanje velikih tekstura.

46.13 Korisni linkovi i dodatno čitanje {#4613-korisni-linkovi}

Zvanična Epic Games dokumentacija

Korisni blog postovi i prezentacije

Alati treće strane

Unakrsne reference u ovoj knjizi

Poglavlje Tema Relevantnost
Poglavlje 05 Teksture, kompresija, mip-mape Osnove na kojima ovo poglavlje gradi — formati, import, mip chain generisanje
Poglavlje 34 Virtual Textures Detaljna implementacija RVT i SVT — koncepti, setup, debugging
Poglavlje 37 Asset Pipeline Kako se teksture procesuiraju tokom build-a, cooking, i distribucije

Rezime poglavlja

Upravljanje memorijom tekstura je jedna od najvažnijih veština za optimizaciju performansi u UE5. Hajde da sumiramo ključne lekcije:

Texture Pool: Postavite razuman budžet za svaku platformu i quality level. Koristite r.Streaming.PoolSize i Scalability settings. Pratite potrošnju sa stat streaming.

Streaming Priority: Razumite kako engine odlučuje šta da učita. Koristite Streaming Priority boost za kritične teksture i Min/Max LOD Size za kontrolu raspona.

Mip Bias: Moćan alat za brzo smanjenje memorije. Koristite globalni bias u kombinaciji sa Scalability settings. Negativan bias sa TSR-om je odlična tehnika za poboljšanje kvaliteta bez povećanja render rezolucije.

Virtual Textures: RVT za landscape (fiksna memorijska potrošnja, ne raste sa veličinom sveta), SVT za velike unique teksture (page-level streaming). Nisu rešenje za sve — koristite ih strateški.

Kompresija: BC1 za jednostavne površine, BC5 za normal mape, BC7 za visokokvalitetne albedo mape. ASTC za mobilne platforme. Pravilna kompresija može prepoloviti memorijsku potrošnju bez vidljivog gubitka kvaliteta.

Ponovna upotreba: Trim sheet-ovi, tiling materijali, channel packing i material instances sa deljenim teksturama — ovo su tehnike koje profesionalni art timovi koriste svakodnevno.

Audit: Redovno pregledajte teksture u projektu. Fokusirajte se na najveće, pronađite nekorišćene, eliminišite nepotrebne alpha kanale. Automatizujte audit koliko god možete.

Platforme: Svaka platforma ima svoj budžet. Koristite Device Profiles i Scalability za automatsko prilagođavanje. Ne zaboravite na Switch i mobilne platforme — one zahtevaju posebnu pažnju.

Zapamtite: optimizacija tekstura nije jednokratan posao. To je kontinuirani proces koji treba da bude deo vaše kulture razvoja. Napravite audit deo vašeg redovnog workflow-a, educirajte art tim o pravilnim rezolucijama i kompresiji, i vaš projekat će raditi glatko na svim platformama.

U sledećem poglavlju ćemo se pozabaviti optimizacijom mesh-eva i geometrije — drugim velikim potrošačem memorije u UE5 projektima. Vidimo se tamo!


Kraj Poglavlja 46