Poglavlje 5: Teksture i teksturiranje
U ovom poglavlju učiš sve o teksturama — od toga šta su i kako ih GPU koristi, preko mip-mapa i kompresije, do toga kako engine upravlja teksturama u memoriji. Teksture su tipično najveći potrošač VRAM-a u igri, pa je razumevanje kako rade ključno za optimizaciju.
Šta je tekstura?
U najjednostavnijem smislu, tekstura je slika koja se preslikava na 3D površinu. Kad vidiš cigleni zid u igri, geometrija je možda samo ravan pravougaonik — sav vizuelni detalj dolazi iz teksture.
Ali u modernom renderovanju, teksture su mnogo više od "slike". Tekstura je zapravo 2D niz podataka koji shader čita tokom renderovanja. Ti podaci mogu da budu:
- Boja (base color / albedo) — osnovna boja površine
- Normale (normal map) — pravci površine za simulaciju detalja geometrije
- Roughness — koliko je površina hrapava ili glatka
- Metalness — da li je površina metal ili ne
- Ambient Occlusion — koliko je deo površine "zaklonjen" okolnom geometrijom
- Height — visina površine za displacement ili parallax
- Emissive — koliko površina emituje svetlost
- Opacity — prozirnost
- Bilo šta drugo — tekstura je generičan kontejner za 2D podatke
Ovo je ključna mentalna promena: prestani da razmišljaš o teksturama kao "slikama" i počni da razmišljaš o njima kao "tabelama podataka koje shader čita za svaki piksel". Neke od tih tabela sadrže boje (i zaista izgledaju kao slike kad ih otvoriaš u editoru), a neke sadrže apstraktne podatke koji ne izgledaju kao ništa smisleno ljudskom oku (normal map, roughness map).
Rezolucija i texeli
Rezolucija
Rezolucija teksture je broj piksela po svakoj dimenziji — širina × visina. Tekstura 2048×2048 ima 2048 piksela u svakom redu i 2048 redova, ukupno 4.194.304 piksela (oko 4 miliona).
Rezolucije su gotovo uvek stepen dvojke (power of two — POT): 256, 512, 1024, 2048, 4096, 8192. Razlog je praktičan:
- Mip-mape — svaki naredni mip nivo je duplo manji. Ako kreneš od POT rezolucije, svaki nivo je takođe POT.
- GPU optimizacija — mnoge GPU operacije (tiling, caching) su optimizovane za POT dimenzije.
- Kompresija — blok-bazirani formati kompresije (BC, ASTC) rade sa blokovima fiksne veličine (4×4 ili 8×8), pa se POT rezolucije dele bez ostatka.
Non-POT (NPOT) teksture su podržane na modernom hardveru, ali mogu da imaju performance penalte i ne podržavaju sve feature-e.
Teksture ne moraju da budu kvadratne — 2048×1024 je validna rezolucija i česta za panoramske ili horizontalno izdužene teksture.
Texel
Texel (texture element) je piksel teksture. Termin "texel" se koristi da bi se razlikovao od "piksela" ekrana. Jedan texel teksture može da pokriva više piksela na ekranu (kad je objekat blizu kamere i tekstura izgleda krupno) ili jedan piksel ekrana može da pokriva više texela (kad je objekat daleko i tekstura izgleda sitno).
Odnos texela i piksela na ekranu je ključan za vizuelni kvalitet:
- Texel < piksel (tekstura je "prevelika" za prikazani deo) — detalj se gubi, ali nema artefakata. Mip-mape ovo optimizuju.
- Texel > piksel (tekstura je "premala" za prikazani deo) — vidljivo pikseliranje, mutnoća. Ovo znači da treba veća tekstura ili da je objekat preblizu kamere za datu rezoluciju.
- Texel ≈ piksel — idealan odnos. Svaki texel odgovara otprilike jednom pikselu ekrana.
Mip-mape (Mipmaps)
Problem koji rešavaju
Zamislite daleki objekat — na ekranu zauzima samo 10×10 piksela. Ali njegova tekstura je 2048×2048. To znači da svakih 10 piksela ekrana mora da "pokrije" 2048 texela teksture. Šta se dešava?
Bez mip-mapa: GPU pokušava da sampleuje jedan texel za svaki piksel ekrana, ali taj piksel zapravo pokriva ogroman region teksture. Rezultat je aliasing — treperenje, šum, moiré pattern-i. Detalji teksture postaju besmisleni na toj udaljenosti i umesto glatke boje dobiješ vizuelni haos.
Ovo je kao kad fotokopiraš sliku na 10% veličine — detalji se pretvaraju u šum.
Šta su mip-mape
Mip-mapa (od latinskog multum in parvo — "mnogo u malom") je niz unapred izračunatih verzija teksture, svaka duplo manja od prethodne:
Mip 0: 2048×2048 (originalna)
Mip 1: 1024×1024
Mip 2: 512×512
Mip 3: 256×256
Mip 4: 128×128
Mip 5: 64×64
Mip 6: 32×32
Mip 7: 16×16
Mip 8: 8×8
Mip 9: 4×4
Mip 10: 2×2
Mip 11: 1×1
Svaki nivo se generiše filtriranjem (prosekom) prethodnog — četiri texela postaju jedan. Ovo "prosečna" vrednost pravilno reprezentuje veći region teksture.
Kako GPU bira mip nivo
GPU automatski bira odgovarajući mip nivo za svaki piksel na osnovu toga koliko se UV koordinate menjaju između susednih piksela (UV derivatives / gradijenti). Ako se UV menja brzo (objekat je daleko ili pod uglom), koristi se viši mip nivo (manja verzija teksture). Ako se UV menja sporo (objekat je blizu), koristi se niži mip nivo (veća verzija).
Za piksele gde izračunati mip nivo pada između dva cela broja (npr. 3.7), GPU koristi trilinearno filtriranje — interpolira između mip nivoa 3 i 4. Ovo sprečava vidljive "skokove" između nivoa.
Memorijski overhead mip-mapa
Mip-mape zahtevaju dodatnu memoriju. Koliko?
Mip 0 = 1 (bazna veličina) Mip 1 = 1/4 Mip 2 = 1/16 Mip 3 = 1/64 ...
Zbir: 1 + 1/4 + 1/16 + 1/64 + ... = 4/3 ≈ 1.333
Mip-mape zahtevaju otprilike 33% više memorije od same bazne teksture. Za teksturu od 16 MB, mip-mape dodaju oko 5.3 MB.
Ovo je relativno mali overhead za ogromnu korist u kvalitetu i performansama (jer GPU čita manju teksturu kad je objekat daleko, što znači manje bandwidth-a).
Mip bias
Mip bias je prilagođavanje koje pomera selekciju mip nivoa gore ili dole:
- Negativan bias (npr. -1) — koristi detaljniji mip nego što bi GPU normalno birao. Slika je oštrija ali može da ima aliasing.
- Pozitivan bias (npr. +1) — koristi manje detaljan mip. Slika je mutnija ali sa manje aliasing-a.
Mip bias se koristi globalno (za sve teksture) ili per-teksturu. Upscaling tehnike poput TSR i DLSS renderuju na nižoj rezoluciji pa koriste negativan mip bias da kompenzuju — jer pri nižoj render rezoluciji GPU bi birao previše blurry mip.
Kompresija tekstura
Zašto je kompresija neophodna
Nekompresovana tekstura 4096×4096 u RGBA8 formatu (4 bajta po texelu — po bajt za crvenu, zelenu, plavu i alfa kanal) zauzima:
4096 × 4096 × 4 = 67.108.864 bajta = 64 MB
Scena u igri može da ima stotine tekstura. Bez kompresije, same teksture bi zauzele desetine gigabajta VRAM-a — daleko više nego što ijedan GPU ima.
Ali kompresija za teksture ima specifičan zahtev: mora da omogući random access — GPU mora da može da pročita bilo koji texel trenutno, bez potrebe da dekompresuje celu teksturu. Standardni formati kompresije (ZIP, PNG, JPEG) ovo ne podržavaju — moraju da se dekompresuju u celosti.
Block Compression (BCn) formati
Block Compression (BC, ranije zvani DXT, S3TC) je familija formata dizajniranih specifično za GPU teksture. Rade tako što dele teksturu na blokove od 4×4 texela i kompresuju svaki blok nezavisno. GPU može da dekompresuje bilo koji 4×4 blok instant, bez pristupa drugim blokovima.
Evo pregleda glavnih BC formata:
BC1 (DXT1) — 4 bita po texelu (8:1 kompresija za RGB)
- Čuva: RGB boju, opcioni 1-bit alfa
- Kvalitet: dobar za boje bez alfa ili sa binarnim alfa (potpuno providno ili potpuno neprovridno)
- Typičan za: diffuse/albedo teksture bez smooth alfa
- Memorija: 64 MB → 8 MB za 4096×4096
BC3 (DXT5) — 8 bita po texelu (4:1 kompresija za RGBA)
- Čuva: RGB boju + 8-bit alfa kanal
- Kvalitet: dobar za boje sa glatkim alfa kanalom
- Tipičan za: diffuse sa alpha, decali
- Memorija: 64 MB → 16 MB
BC4 — 4 bita po texelu (za jednokanalne teksture)
- Čuva: jedan kanal (R) sa visokom preciznošću
- Tipičan za: height mape, roughness, AO — bilo šta sa jednim kanalom grayscale
- Kvalitet: odličan za grayscale podatke
BC5 — 8 bita po texelu (za dvokanalne teksture)
- Čuva: dva kanala (RG) sa visokom preciznošću
- Tipičan za: normal mape — čuva X i Y komponente normale, Z se rekonstruiše u shaderu
- Kvalitet: odličan za normal mape — mnogo bolji od BC1/BC3 koji uvode vidljive kompresione artefakte u normalama
BC6H — 8 bita po texelu (za HDR teksture)
- Čuva: RGB u half-float (16-bit floating point)
- Tipičan za: HDR environment mape, skybox-ovi
- Kvalitet: odličan za HDR podatke
BC7 — 8 bita po texelu (najviši kvalitet za LDR)
- Čuva: RGBA sa najvišim kvalitetom od svih BC formata
- Tipičan za: sve gde je kvalitet kritičan — normal mape (alternativa BC5), albedo sa alfa
- Kvalitet: značajno bolji od BC1 i BC3, ali ista veličina kao BC3
- Nedostatak: sporija kompresija (vreme potrebno za kreiranje, ne za dekompresiju na GPU-u)
Izbor formata — praktične smernice
| Tip teksture | Preporučeni format | Razlog |
|---|---|---|
| Base color (bez alfa) | BC1 | Najmanji, dovoljan kvalitet |
| Base color (sa alfa) | BC3 ili BC7 | BC7 ako je kvalitet bitan |
| Normal map | BC5 ili BC7 | BC5 je standard, BC7 za viši kvalitet |
| Roughness (solo) | BC4 | Jednokanalna |
| Metalness (solo) | BC4 | Jednokanalna |
| ORM packed | BC1 ili BC7 | O+R+M u jednoj teksturi |
| Height map | BC4 | Jednokanalna |
| HDR environment | BC6H | HDR podaci |
| UI tekstura | BC7 ili nekompresovana | Kvalitet je prioritet |
ASTC (Adaptive Scalable Texture Compression)
ASTC je noviji format kompresije koji je flexibilniji od BC familije. Podržava:
- Varijabilnu veličinu bloka: 4×4, 5×5, 6×6, 8×8, 10×10, 12×12
- Veći blok = veća kompresija = niži kvalitet
- LDR i HDR
- 1-4 kanala
ASTC je standard na mobilnim platformama (Android, iOS) gde BC formati nisu podržani. Na PC-u i konzolama, BC je i dalje dominantan, ali ASTC se sve više koristi.
Prednost ASTC-a je fleksibilnost — možeš da biraš tačku na spektru kvalitet/veličina. Za teksturu koja ne zahteva visok kvalitet, koristi veći blok (npr. 8×8) za agresivniju kompresiju. Za teksturu gde je kvalitet kritičan, koristi manji blok (4×4).
Kompresioni artefakti
Svaka kompresija gubi informaciju (lossy compression), pa uvodi artefakte:
Block artefakti — jer se kompresija radi po blokovima od 4×4, ponekad su granice blokova vidljive, posebno na glatkim gradijentima.
Color banding — BC1 čuva samo 2 bazne boje po 4×4 bloku i interpolira između njih. Na regionima sa suptilnim varijacijama boje, ovo može da proizvede vidljive "stepenaiste" prelaze umesto glatkih gradijenata.
Normal map artefakti — kompresioni artefakti na normal mapama se ne manifestuju kao vizuelni šum u teksturi, već kao nepravilno osvetljenje na 3D modelu. Zato su BC5 i BC7 bitni za normal mape — BC1 na normal mapi daje primetno lošije osvetljenje.
Texture streaming
Problem
Moderna igra može da ima teksture ukupne veličine od desetina gigabajta. VRAM tipičnog GPU-a je 8-16 GB, a deo toga zauzimaju framebuffer-i, depth buffer-i, shadow mape i drugi render targets. Za teksture ostaje možda 4-8 GB.
Očigledno, ne mogu sve teksture biti u VRAM-u istovremeno.
Rešenje: Texture streaming
Texture streaming je sistem koji dinamički učitava i otpušta teksture (i mip nivoe) na osnovu toga šta je trenutno vidljivo i koliko je blizu kamere.
Princip rada:
- Engine određuje koje teksture su potrebne i u kojoj rezoluciji (mip nivou)
- Teksture koje su vidljive i blizu kamere dobijaju veće mip nivoe (veću rezoluciju)
- Teksture koje su daleko ili van vidokruga dobijaju niže mip nivoe ili se potpuno otpuštaju
- Kad se kamera pomeri, sistem ažurira prioritete i učitava/otpušta po potrebi
Texture streaming pool
UE5 ima koncept texture streaming pool — fiksna količina VRAM-a rezervisana za streaming tekstura. Engine upravlja ovim pool-om:
- Kad je pool pun i treba učitati novu teksturu, otpušta se najmanje prioritetna (najdalja, najmanje vidljiva)
- Ako je pool premali, teksture mogu biti prikazane u nižoj rezoluciji nego što je idealno — vidljivo kao "blurry" teksture koje se postepeno izoštre
Ovo "postepeno izoštririvanje" si verovatno video u igrama — objekat koji je blizu ali čija tekstura se tek učitava iz diska. To je texture streaming u akciji.
Streaming prioritet
Nije svaka tekstura jednako bitna. Engine mora da prioritizuje:
- Teksture koje igrač gleda direktno > periferne teksture
- Teksture bliže kameri > dalje
- Teksture na većim objektima > manji
- Teksture sa forced full resolution flag-om > normalne
Veza sa mip-mapama
Mip-mape su ono što čini streaming moguć. Umesto da učitavaš celu 64 MB teksturu (mip 0) ili ništa, možeš da učitaš samo mip 5 (256 KB) i postepeno dodaješ detaljnije nivoe kako tekstura postaje prioritetnija. Ovo omogućava brzo inicijalno učitavanje (učitaj malo za sve) i postepeno poboljšanje (dodaj detalj za ono što je bitno).
Tipično, najniži mip nivoi (mip 7+, nekoliko KB) su uvek u VRAM-u — nikad se ne otpuštaju. Viši mip nivoi se streamuju po potrebi.
Texture atlasi
Texture atlas je velika tekstura koja sadrži mnogo manjih tekstura "zapakanih" zajedno.
Zašto?
Svaka tekstura u igri zahteva:
- Memory allocation — GPU mora da alocira memoriju
- State change pri renderovanju — kad GPU prelazi sa jedne teksture na drugu, to je state change koji košta vreme
- Descriptor/slot — GPU ima ograničen broj tekstura koje mogu biti aktivne istovremeno
Ako imaš 100 malih tekstura (npr. za UI ikonice ili 2D sprite-ove), svaka zahteva zaseban state change. Ako ih sve staviš u jedan atlas, GPU može da ih sve renderuje sa jednom teksturom — jedan state change umesto 100.
Kako rade
Atlas je obična tekstura (npr. 4096×4096) u kojoj su manje slike organizovane u pravougaonim regionima. Svaki objekat koji koristi atlas ima UV koordinate koje referenciraju odgovarajući region.
Na primer, ako imaš atlas sa 16 ikonica po 256×256:
| Ikona 1 | Ikona 2 | Ikona 3 | Ikona 4 |
| Ikona 5 | Ikona 6 | Ikona 7 | Ikona 8 |
| Ikona 9 | Ikona 10| Ikona 11| Ikona 12|
| Ikona 13| Ikona 14| Ikona 15| Ikona 16|
Ikona 7 ima UV koordinate: U=[0.5, 0.75], V=[0.25, 0.5]
Problemi sa atlasima
Mip-map bleeding — na nižim mip nivoima, texeli susednih regiona u atlasu se mešaju. Ikona 7 "krvari" u ikonu 6 i 8. Ovo je ozbiljan problem za tile-bazirane atlase.
Rešenja:
- Padding između regiona (ali troši prostor)
- Klamping UV koordinata u shaderu
- Korišćenje texture arrays umesto atlasa (svaka "slika" je zaseban sloj, nema mešanja)
Rezolucija — sve u atlasu ima istu rezoluciju po texelu atlasa. Ako je jedan element bitniji i zahteva veću rezoluciju, mora da zauzme veći deo atlasa.
Texture arrays vs atlasi
Texture Array je moderan alternativa atlasu. Umesto jedne teksture sa pod-regionima, koristi se niz tekstura iste rezolucije ali sa odvojenim "slojevima" (layers). Svaki sloj ima sopstvene mip-mape bez bleeding-a između slojeva.
Texture arrays su generalno bolji od atlasa za materijale jer nemaju bleeding problem, ali zahtevaju da sve teksture u nizu budu iste rezolucije i formata.
Kanali tekstura — šta se čuva gde
RGBA kanali
Tekstura ima do četiri kanala: Red (R), Green (G), Blue (B), i Alpha (A). Svaki kanal čuva jednu vrednost po texelu, obično 8 bita (0-255).
Za color teksture, kanali nose informaciju o boji:
- R = količina crvene svetlosti
- G = količina zelene svetlosti
- B = količina plave svetlosti
- A = transparentnost (255 = potpuno neprovidan, 0 = potpuno providan)
Ali ne moraju da nose informaciju o boji. Kanal je samo niz brojeva — možeš da čuvaš šta god hoćeš.
Channel packing
Channel packing je tehnika gde se više nezavisnih grayscale podataka čuva u kanalima jedne teksture. Umesto tri odvojene teksture za roughness, metalness i ambient occlusion (svaka sa jednim korisnim kanalom i dva prazna), možeš da sve tri staviš u jednu RGB teksturu:
- R = Ambient Occlusion
- G = Roughness
- B = Metalness
Ovo se obično zove ORM tekstura (Occlusion, Roughness, Metalness) ili ARM ili RMA zavisno od redosleda kanala.
Prednosti channel packinga:
- Manje tekstura — 3 teksture → 1
- Manje memorije — jedna BC1 tekstura umesto tri
- Manje texture samples — shader čita jednu teksturu i razdvaja kanale, umesto tri čitanja
- Manje state changes — manje tekstura za binding
Nedostaci:
- Svi pakani kanali moraju da imaju istu rezoluciju
- Kompresija utiče na sve kanale — BC1 na pakanoj teksturi može da ima artefakte na kanalima koji zahtevaju visoku preciznost (normal mape se nikad ne pakuju sa color kanalima)
- Otežava pojedinačno podešavanje rezolucije — ne možeš da imaš roughness na 512 a metalness na 256 ako su u istoj teksturi
Konvencija kanala u UE5
UE5 očekuje materijalne teksture u specifičnim kanalima. Standardna PBR setup:
| Tekstura | Sadržaj | Tipičan format |
|---|---|---|
| Base Color | RGB boja, opcioni A za opacity | BC1 (bez alfa) ili BC3/BC7 (sa alfa) |
| Normal | RG normala (tangent space) | BC5 |
| ORM / ARM | R=AO, G=Roughness, B=Metalness | BC1 ili BC7 |
| Emissive | RGB emisija svetlosti | BC1 ili BC7 |
Ova konvencija nije fiksna — UE5 material editor dozvoljava priključivanje bilo kog kanala na bilo koji ulaz. Ali poštovanje konvencije olakšava rad u timu i sa marketplace asset-ima.
Linearan vs sRGB
Ovo je izuzetno važna distinkcija i čest izvor grešaka.
sRGB je color space (prostor boja) koji je nelinearan — tamne vrednosti imaju više preciznosti nego svetle. Ljudsko oko je osetljivije na razlike u tamnim tonovima, pa sRGB dodeljuje više bitova tamnim vrednostima. Kad monitor prikaže sRGB sliku, primenjuje gamma korekciju da je prevede u linearne vrednosti svetlosti.
Linear je matematički korektan prostor — dvostruka vrednost znači dvostruku količinu svetlosti.
Pravilo:
- Color teksture (base color, emissive) se čuvaju u sRGB — jer su pravljene za ljudsko oko
- Data teksture (normal, roughness, metalness, AO, height) se čuvaju u linear — jer sadrže matematičke podatke, ne boje
Ako importuješ normal mapu kao sRGB, shader će pogrešno interpretirati vrednosti (primeniti gamma korekciju na normalu, što nema smisla), i osvetljenje će biti pogrešno. Ovo je česta greška — tekstura izgleda "nekako čudno" i rešenje je promenom sRGB flag-a.
UE5 obično automatski detektuje tip na osnovu imena ili konvencije, ali uvek proveri.
Tipovi tekstura u renderovanju
Base Color (Albedo)
Osnovna boja površine — boja materijala bez osvetljenja, senki, ili refleksija. U PBR workflow-u, base color ne sadrži informacije o osvetljenju — nema "pečenih" senki ili highlights-a.
Za metale, base color je boja refleksije (zlato je žuto, bakar narandžast). Za nemetale (dielektrike), base color je boja difuzne refleksije (drvo je braon, trava zelena).
Vrednosti base colora u PBR su ograničene: ne smeju da budu potpuno crne (0, 0, 0) niti potpuno bele (255, 255, 255) — u stvarnosti ne postoji materijal koji apsorbuje ili reflektuje 100% svetlosti. Tipičan opseg je 50-240 za nemetale.
Normal Map
Normal mapa je tekstura koja čuva pravce (normale) površine za svaki texel. Umesto da modeluješ sitne detalje geometrijom (što bi zahtevalo milione trouglova), "laječeš" ih normal mapom — shader čita normalu iz teksture umesto da koristi interpoliranu normalu geometrije, i osvetljenje se izračunava kao da površina ima detalje kojih zapravo nema.
Normal mapa je jedan od najvažnijih alata u real-time grafici — omogućava ekstremno detaljan izgled sa minimalnim geometry cost-om. Detaljno o normal mapping-u u poglavlju 19.
Vrednosti u normal mapi:
- RGB = (Nx, Ny, Nz) komponente normala vektora
- Mapiraju se iz opsega [-1, 1] u [0, 255]: vrednost 128 = 0, 0 = -1, 255 = 1
- "Flat" normala (koja ne menja ništa) je (128, 128, 255) — zato normal mape imaju karakterističnu ljubičastu/plavu boju
Roughness Map
Definiše koliko je površina hrapava ili glatka:
- 0 (crno) = savršeno glatka površina (ogledalo)
- 1 (belo) = potpuno hrapava površina (mat)
Roughness kontroliše koliko su refleksije "razbijene" — glatka površina daje oštre refleksije, hrapava daje mutne, razmazane refleksije. Detaljno u poglavlju 11 o PBR-u.
Metalness Map
Binarna mapa (uglavnom crno ili belo, retko siva):
- 0 (crno) = dielektrik (ne-metal: drvo, kamen, plastika, koža)
- 1 (belo) = metal (čelik, zlato, aluminijum)
U praksi, vrednosti između 0 i 1 se koriste samo za prelaz metal/ne-metal (npr. zarđali metal gde je deo još uvek metalan a deo je oksidiran). Čiste površine su ili 0 ili 1.
Ambient Occlusion (AO) Map
Grayscale mapa koja pokazuje koliko je svaki deo površine "zaklonjen" okolnom geometrijom — pukotine, uglovi, mesta gde se dva dela spajaju. Tamnije = zaklonjeno, svetlije = izloženo.
AO daje subtilan ali bitan efekat dubine i kontakta — bez njega, objekti izgledaju "ravno" i kao da lebde.
AO mapa je statična — ne menja se sa osvetljenjem. Za dinamički AO, koriste se screen-space tehnike (SSAO, GTAO) — poglavlje 15.
Height Map (Displacement)
Grayscale mapa gde svetlije vrednosti predstavljaju "više" delove površine a tamnije "niže". Koristi se za:
- Parallax mapping — simulacija dubine bez dodavanja geometrije (poglavlje 19)
- Displacement — stvarno pomeranje geometrije na osnovu height mape (zahteva tessellation)
- Height-based blending — u materijalima, koristi se za blendovanje tekstura na osnovu visine (npr. sneg se skuplja na "višim" delovima kamena)
Emissive Map
RGB mapa koja definiše koliko površina emituje svetlost. Crno = ne emituje, svetle boje = emituje.
Emissive se dodaje na finalnu boju nakon osvetljenja — emissive objekti svetle čak i u potpunom mraku. Koristi se za ekrane, svetleće znakove, lava, magične efekte.
U HDR renderovanju, emissive vrednosti mogu da budu veće od 1.0, omogućavajući bloom efekat.
Opacity / Alpha Map
Grayscale mapa za transparentnost:
- 1 (belo) = potpuno neprovidan
- 0 (crno) = potpuno providan
Koristi se za:
- Lišće drveća (modelovano kao quad sa alfa mapom u obliku lista)
- Rešetke, ograde
- Decali
- Postepeno nestajanje (dissolve efekat)
Transparency je skupa za renderovanje (detaljno u poglavlju 9) — kad god je moguće, koristi se masked (binarna) transparentnost umesto translucent (glatke).
Memorija i bandwidth — budžetiranje tekstura
Koliko memorije troše teksture?
Hajde da izračunamo za tipičnu PBR setup:
Jedan objekat sa 2048×2048 teksturama:
- Base Color (BC1): 2048×2048 × 0.5 B/texel × 1.33 (mips) ≈ 2.8 MB
- Normal (BC5): 2048×2048 × 1 B/texel × 1.33 ≈ 5.6 MB
- ORM (BC1): 2048×2048 × 0.5 B/texel × 1.33 ≈ 2.8 MB
Ukupno po objektu: ~11.2 MB
Scena sa 100 unikatnih objekata: ~1.12 GB samo za teksture.
Za 4096×4096 teksture, to je 4× više: ~4.48 GB za 100 objekata.
A ovo je pre nego što dodamo lightmape, shadow mape, framebuffere, GBuffer, i sve ostale render targets.
Texture budget
U profesionalnom razvoju, teksture imaju budžet — maksimalnu količinu memorije koja može da se potroši na teksture za datu platformu.
Tipični budžeti:
- PC (high-end): 4-6 GB za teksture
- Konzole: 2-4 GB za teksture
- Mobile: 256-512 MB za teksture
U okviru budžeta, teksture se raspoređuju po prioritetu:
- Hero assets (igrač, glavni likovi): najveće teksture
- Srednji plan (props, namještaj): srednje teksture
- Pozadina, daleki objekti: male teksture
Texture streaming pomaže — ne moraju sve teksture da budu u VRAM-u istovremeno. Ali streaming pool i dalje ima ograničenu veličinu.
Memory bandwidth
Osim čuvanja tekstura u VRAM-u, GPU mora da ih i čita tokom renderovanja. Svaki texture sample (čitanje jednog texela) zahteva pristup memoriji. Za složen materijal koji čita 5-6 tekstura po pikselu, na 4K rezoluciji pri 60 fps:
3840 × 2160 × 6 tekstura × 60 fps × (overhead za filtriranje i mip) ≈ ogromna količina čitanja
Memory bandwidth (propusni opseg memorije) je često bottleneck — GPU može da izračuna shader brže nego što može da čita teksture iz VRAM-a. Kompresija pomaže (manje bajta za čitanje), mip-mape pomažu (bliži mip nivoi su manji), i texture cache pomaže (čitani texeli se keširaju za ponovnu upotrebu).
Specijalne vrste tekstura
Cube Map
Tekstura koja se sastoji od 6 strana kocke — gore, dole, levo, desno, napred, nazad. Koristi se za:
- Environment mapping — refleksija okoline na reflektivnim površinama
- Skybox — prikaz neba i udaljene okoline
- Irradiance maps — predračunato ambijentalno osvetljenje
Sampleovanje cube mape koristi 3D vektor (pravac) umesto 2D UV koordinata — GPU čita texel sa strane kocke u tom pravcu.
Volume Texture (3D Texture)
Tekstura sa tri dimenzije — širina × visina × dubina. Sampleuje se sa 3D koordinatama (u, v, w). Koristi se za:
- Volumetričke efekte (dim, oblaci)
- 3D noise
- Look-up tables (LUT) za color grading
Volume teksture troše mnogo memorije — 256×256×256 × 4 kanala = 64 MB nekompresovano!
Render Target
Render target je tekstura u koju GPU renderuje umesto na ekran. Koriste se za:
- GBuffer — skup tekstura koje čuvaju informacije o sceni (pozicije, normale, boje, roughness) za deferred rendering (poglavlje 29)
- Shadow maps — teksture koje čuvaju informacije o senkama (poglavlje 13)
- Refleksije — renderovanje scene iz ugla refleksije
- Post-processing chain — svaki post-processing efekat čita iz jednog render target-a i piše u drugi
Render targets troše VRAM ali se ne streamuju — moraju da budu u memoriji celo vreme dok se koriste. Na 4K rezoluciji, GBuffer može da zauzme 100+ MB.
Virtual Textures — uvod
Virtual Textures su tehnika koja rešava problem tekstura koje su prevelike da bi bile kompletno u memoriji. Koncept je sličan virtualnoj memoriji u operativnim sistemima.
Umesto da cela tekstura bude u VRAM-u, samo stranice (pages) koje su trenutno potrebne se učitavaju. Stranica je mali blok teksture (npr. 128×128 texela). GPU vodi tabelu koja mapira virtualne adrese na fizičke lokacije stranica.
Dva tipa u UE5:
Streaming Virtual Textures (SVT) — standardne teksture koje se streamuju po stranicama umesto po celim mip nivoima. Efikasnije od regularnog texture streaming-a.
Runtime Virtual Textures (RVT) — teksture koje se generišu u realnom vremenu, tipično za landscape rendering. Umesto da se materijal landscapea izračunava za svaki piksel svaki frejm, rezultat se "keširia" u RVT i čita kao obična tekstura.
Detaljno o virtual texturama u poglavlju 34.
Tekstura generisanje i workflow
Fotografija (Photogrammetry)
Teksture se mogu kreirati iz fotografija realnih materijala:
- Fotografiši materijal sa različitih uglova i osvetljenja
- Softver analizira slike i extrahuje base color, normal, roughness
- Rezultat se obradi za tiling (da se tekstura može ponavljati bez vidljivih seams-ova)
Ovo daje izuzetno realitične rezultate i koristi se u AAA igrama i archviz-u.
Ručno crtanje
Tradicionalni pristup — artist crta teksturu u Photoshop-u ili Substance Painter-u. Potpuna kontrola nad izgledom, ali zahteva veštinu i vreme.
Proceduralna generacija
Alati poput Substance Designer-a koriste node-based graf za proceduralnu generaciju tekstura. Umesto da crtaš piksele, definišeš pravila — "ovo je cigleni zid, cigle su ove veličine, malter je ovako debeo, svaka cigla ima blagu varijaciju boje".
Prednosti:
- Parametrično — promeniš jedan parametar i cela tekstura se ažurira
- Tiling po definiciji — algoritam generiše beskonačno tileable teksture
- Konzistentne varijacije — lako generišeš 10 varijacija istog materijala
Baking
Baking je proces prenosa informacija sa jednog mesh-a na teksturu drugog:
- Normal map baking — detalji high-poly mesh-a (milioni trouglova) se "peku" u normal mapu za low-poly mesh (hiljade trouglova)
- AO baking — ambient occlusion se izračunava na high-poly i čuva u teksturi
- Curvature baking — informacija o zakrivljenosti površine
- Position baking — world-space pozicija za shader efekte
Baking je fundamentalna tehnika u game development-u — omogućava vizuelnu kompleksnost high-poly modela sa performansama low-poly modela.
Rezime ključnih pojmova
| Pojam | Značenje |
|---|---|
| Tekstura | 2D niz podataka koji se mapira na 3D površinu |
| Texel | Piksel teksture |
| Mip-mapa | Niz unapred izračunatih verzija teksture u opadajućoj rezoluciji |
| BC (Block Compression) | Familija GPU-nativnih formata kompresije (BC1-BC7) |
| ASTC | Flexibilan format kompresije, standard na mobilnim platformama |
| Texture streaming | Dinamičko učitavanje/otpuštanje tekstura po potrebi |
| Texture atlas | Velika tekstura koja sadrži mnogo manjih tekstura |
| Channel packing | Čuvanje više grayscale mapa u R, G, B, A kanalima jedne teksture |
| sRGB | Nelinearan color space za color teksture |
| Linear | Matematički linearan prostor za data teksture |
| Normal map | Tekstura koja čuva pravce površine za simulaciju detalja |
| Roughness | Hrapavost površine (0=glatka, 1=hrapava) |
| Metalness | Da li je površina metal (0 ili 1) |
| AO | Ambient Occlusion — koliko je deo zaklonjen |
| Cube map | 6-strana tekstura za environment mapping |
| Render target | Tekstura u koju GPU renderuje |
| Virtual Texture | Tekstura gde se samo potrebne stranice drže u memoriji |
| Mip bias | Prilagođavanje selekcije mip nivoa |
| Baking | Prenos informacija sa jednog izvora u teksturu |
Sledeće poglavlje se bavi koordinatnim prostorima i transformacijama — kako se geometrija transformiše od lokalnog prostora modela do piksela na ekranu. Ovo je potpuni "putopis" jednog verteksa kroz rendering pipeline.
📖 Dalje čitanje: