Poglavlje 6: Coordinate Spaces i transformacije

Poglavlje 6: Coordinate Spaces i transformacije

U ovom poglavlju pratiš putovanje jednog verteksa od njegovog lokalnog prostora, kroz svet, kroz kameru, sve do piksela na ekranu. Razumećeš zašto postoji toliko koordinatnih prostora, šta se dešava u svakom, i kako MVP matrica objedinjuje ceo proces. Ovo poglavlje je most između matematike (poglavlje 2) i rendering pipeline-a (poglavlje 7).


Zašto postoji više koordinatnih prostora?

Na prvi pogled, moglo bi da izgleda komplikovano — zašto ne možemo da držimo sve u jednom koordinatnom sistemu? Odgovor je isti kao u realnom životu: različiti konteksti zahtevaju različite okvire reference.

Kad opisuješ poziciju svog stola, kažeš "u ćošku sobe" (koordinatni sistem sobe). Kad opisuješ poziciju sobe, kažeš "drugi sprat, levo od stepeništa" (koordinatni sistem zgrade). Kad opisuješ poziciju zgrade, koristiš ulicu i broj (koordinatni sistem grada). Svaki nivo ima svoj koordinatni sistem jer je tako najlakše raditi na tom nivou.

U renderovanju, imamo sličnu hijerarhiju prostora, i svaki postoji iz dobrog razloga:

  1. Object Space (lokalni prostor) — za definisanje geometrije objekta
  2. World Space (svetski prostor) — za pozicioniranje u sceni
  3. View/Camera Space (prostor kamere) — za perspektivu posmatrača
  4. Clip Space (prostor odsecanja) — za eliminisanje nevidljive geometrije
  5. NDC (Normalized Device Coordinates) — za normalizaciju na standardni opseg
  6. Screen Space (prostor ekrana) — za konačne piksele

Vertex prolazi kroz sve ove prostore u jednom frejmu, transformisan matricama na svakom koraku. Hajde da ih prođemo redom.


Object Space (Local Space, Model Space)

Šta je

Object space je koordinatni sistem u kom je 3D model originalno kreiran. Kad modelar pravi stolicu u Blender-u, verteksi stolice su definisani relativno na neko ishodište — obično centar ili baza objekta.

Na primer, stolica može da ima vertex na poziciji (0.5, 0.0, 0.8) u object space-u — to znači 0.5 jedinice udesno od centra stolice, na podu (Y=0), i 0.8 jedinica naviše. Ove koordinate nemaju nikakve veze sa tim gde je stolica u sceni — opisuju samo oblik stolice.

Zašto postoji

Razlog je praktičan: hoćeš da model stolice bude nezavisan od scene. Ista stolica može da se stavi u kuhinju, spavaću sobu, ili na Mesec — njen oblik se ne menja. Menjaju se samo pozicija, rotacija i veličina u sceni — a to je posao transformacija, ne geometrije.

Object space omogućava i instancing — korišćenje istog mesh-a na više mesta. Sto stolica u sceni koristi istih 5.000 verteksa u object space-u, samo sa različitim transformacijama. Bez object space-a, morali bismo da čuvamo 500.000 verteksa (100 kopija × 5.000).

Konvencija ishodišta

Gde je ishodište object space-a? Konvencija zavisi od konteksta:

Pozicija ishodišta utiče na to kako se objekat rotira (rotira se oko ishodišta) i skalira (skalira se od ishodišta). Pogrešno postavljeno ishodište je čest izvor frustracije — objekat se rotira oko pogrešne tačke.

U UE5, ishodište object space-a je pivot point mesh-a. Može se promeniti u DCC alatu pre eksporta.


World Space

Šta je

World space je zajednički koordinatni sistem cele scene. Svaki objekat u sceni ima svoju poziciju, rotaciju i skaliranje u world space-u. Kad kažeš "stol je na poziciji (500, 200, 0) u svetu", to je world space.

Transformacija: Object → World

Da bi došao od object space-a do world space-a, koristiš Model matricu (u UE5 terminologiji: Local to World transform).

Model matrica je 4×4 matrica koja kombinuje:

Za stolicu koja je na poziciji (500, 200, 0), rotirana 45° oko Z ose, i skalirana za faktor 1.5:

WorldPosition = ModelMatrix × ObjectPosition

Svaki vertex stolice se transformiše ovom matricom da se dobije njegova pozicija u svetu.

World space upotrebe

World space je prostor u kom se dešava većina "logike":

Problem velikih svetova

World space ima praktičan problem: preciznost floating-point brojeva (poglavlje 2). Što su koordinate veće (dalje od ishodišta sveta), to je manja preciznost. Na poziciji (0, 0, 0), float ima preciznost od ~0.0000001 metra. Na poziciji (100000, 0, 0) — 100 km od ishodišta — preciznost je oko 0.008 metra (8 mm). Na 1000 km, preciznost je 8 cm.

Za male scene, ovo nije problem. Ali za open-world igre sa svetovima od stotina kilometara, floating-point preciznost postaje ozbiljan izazov. Objekti daleko od ishodišta počinju da "tresu" (jittering), fizika postaje nestabilna, i renderovanje dobija artefakte.

Rešenja:


View Space (Camera Space, Eye Space)

Šta je

View space je koordinatni sistem definisan kamerom. Kamera je u ishodištu (0, 0, 0), gleda duž jedne ose (obično -Z ili +Z, zavisi od konvencije), i "gore" je duž Y ose.

Zašto postoji

View space postoji zato što za rendering ne zanima nas gde je kamera u svetu — zanima nas gde su objekti relativno na kameru. Iz perspektive kamere, kamera je uvek "tu" a svet se kreće oko nje.

Ovo značajno pojednostavljuje dalje transformacije (projekciju) jer projekcija pretpostavlja da kamera gleda iz ishodišta duž jedne ose.

Transformacija: World → View

View matrica transformiše iz world space-a u view space. View matrica je inverz transformacije kamere.

Ako je kamera na poziciji (10, 5, 3) i rotirana za 30° oko Y ose, view matrica "poništava" tu transformaciju — pomera sve za (-10, -5, -3) i rotira za -30°. Rezultat: kamera je na (0, 0, 0) i gleda "pravo napred".

ViewPosition = ViewMatrix × WorldPosition

Look-at matrica

Čest način konstruisanja view matrice je look-at funkcija:

lookAt(eye, target, up)

gde je:

Iz ova tri parametra, funkcija konstruiše view matricu. Interno:

  1. Forward vektor: normalize(target - eye)
  2. Right vektor: normalize(cross(forward, up))
  3. Up vektor: cross(right, forward) (korigovan)
  4. Ovi vektori formiraju rotacioni deo matrice
  5. Negirana pozicija kamere je translacioni deo

Clip Space

Šta je

Clip space je prostor nakon primene projekcione matrice. Ovo je prostor u kom se vrši clipping — eliminisanje geometrije koja je van vidljivog prostora kamere (frustuma).

Projekciona matrica

Projekciona matrica transformiše iz view space-a u clip space. Postoje dva tipa projekcije:

Perspektivna projekcija — simulira ljudski vid: bliži objekti izgledaju veće, dalji manji. Paralelne linije konvergiraju ka tački nedogleda. Ovo je standard za igre i većinu 3D aplikacija.

Ortografska projekcija — nema perspektivu: objekat izgleda isto bez obzira na udaljenost od kamere. Paralelne linije ostaju paralelne. Koristi se za 2D igre, izometrijske prikaze, tehničke crteže, i UI.

Perspektivna projekcija detaljno

Frustum (vidljivi prostor kamere) je zarubljena piramida:

Perspektivna projekciona matrica (za DirectX / UE5 konvenciju):

| f/aspect  0      0              0        |
|    0      f      0              0        |
|    0      0   far/(far-near)    1        |
|    0      0   -far*near/(far-near)  0    |

gde je f = 1/tan(fov/2)

Ovo izgleda zastrašujuće, ali hajde da razumemo šta radi:

Šta se dešava sa W

U view space-u, W svakog verteksa je 1 (jer su homogene koordinate tačaka). Ali nakon množenja projekcionom matricom, W postaje Z vrednost verteksa u view space-u (udaljenost od kamere). Ovo je ključno za perspektivni efekat.

Clipping

U clip space-u, vertex je vidljiv ako su njegove koordinate unutar:

-W ≤ X ≤ W -W ≤ Y ≤ W 0 ≤ Z ≤ W (DirectX konvencija) ili -W ≤ Z ≤ W (OpenGL)

Trouglovi koji su potpuno van ovih granica se odbacuju (culled). Trouglovi koji su delimično unutar se odsecaju (clipped) — deo trougla van granica se odseče i zameni novim, manjim trouglovima.

Ovo je razlog zašto se ovaj prostor zove "clip space" — tu se dešava clipping.


Normalized Device Coordinates (NDC)

Perspektivno deljenje

Posle clippinga, vrši se perspektivno deljenje — svaka koordinata se deli sa W:

NDC_X = Clip_X / Clip_W
NDC_Y = Clip_Y / Clip_W
NDC_Z = Clip_Z / Clip_W

Pošto je W = Z (udaljenost od kamere), deljenje sa W čini da dalji objekti imaju manje X i Y koordinate — oni "šrinkaju" sa udaljenošću. Ovo je perspektivni efekat — osnova svakog realističnog 3D prikaza.

NDC opseg

Nakon perspektivnog deljenja, koordinate su u Normalized Device Coordinates:

NDC je "normalizovan" — iste koordinate bez obzira na rezoluciju ekrana, aspect ratio, ili FOV. (0, 0) je centar ekrana, (-1, -1) je donji levi ugao, (1, 1) je gornji desni.


Screen Space (Viewport Transform)

Transformacija: NDC → pikseli

Konačno, NDC koordinate se transformišu u screen space — konkretne piksel koordinate na ekranu:

Screen_X = (NDC_X + 1) / 2 × ScreenWidth
Screen_Y = (1 - NDC_Y) / 2 × ScreenHeight  (Y se invertuje!)

Na Full HD ekranu (1920×1080):

Z koordinata se čuva za depth buffer (Z-buffer) — koristi se za određivanje koji objekat je ispred kog.

Viewport

Viewport definiše koji deo ekrana koristi za renderovanje. Obično pokriva ceo ekran, ali može da bude i manji — na primer, za split-screen multiplayer, svaki igrač ima svoj viewport koji pokriva polovinu ekrana.


MVP matrica — sve u jednom

Pošto su sve transformacije matrice, mogu se kombinovati u jednu:

MVP = Projection × View × Model

Ova jedna matrica transformiše vertex direktno iz object space-a u clip space:

ClipPosition = MVP × ObjectPosition

GPU ovo radi u vertex shaderu — za svaki vertex, pomnoži ga MVP matricom. Rezultat je pozicija u clip space-u, odakle hardware nastavlja sa clippingom, perspektivnim deljenjem, i rasterizacijom.

Zašto je MVP efikasan

Umesto tri odvojene transformacije (3 × matrica-vektor množenja po verteksu), kombinujemo matrice unapred (matrica-matrica množenje, jednom po objektu) i primenjujemo jednu kombinovanu matricu na svaki vertex.

Za objekat sa 10.000 verteksa:

Skoro 3× manje posla. A Model matrica se računla jednom po objektu (ne po vertexu), View i Projection jednom po frejmu (ne po objektu). Engine obično prosleđuje Model, View, i Projection odvojeno u shader, a shader ih kombinuje ili koristi zasebno zavisno od potrebe.

Zašto shader ponekad treba odvojene matrice?

Vertex shader obično računa i druge stvari osim pozicije:

Zato shader obično prima odvojene matrice i koristi ih kako treba za svaku namenu.


Specijalni prostori

Pored glavnih prostora u pipeline-u, postoje i specijalizovani prostori koji se koriste u specifičnim situacijama:

Tangent Space

Tangent space je lokalni koordinatni sistem definisan na površini mesh-a, u svakom verteksu:

Tangent space se koristi za normal mapping — normal mapa čuva perturbacije normala u tangent space-u, jer su tako nezavisne od orijentacije objekta u svetu. Detalji u poglavlju 19.

TBN matrica (Tangent-Bitangent-Normal) je 3×3 matrica koja transformiše iz tangent space-a u world space (ili view space).

Light Space

Light space je koordinatni sistem iz perspektive svetla — koristi se za shadow mapping. Scena se renderuje iz ugla svetla, i rezultat (depth buffer) je shadow map. Detalji u poglavlju 13.

Texture Space

UV prostor — 2D prostor gde su definisane UV koordinate. Transformacije u texture space-u (skaliranje, offset, rotacija UV-a) kontrolišu kako se tekstura prikazuje na površini.


Depth Buffer i Z vrednosti

Šta je depth buffer

Depth buffer (Z-buffer) je tekstura (render target) iste rezolucije kao framebuffer koja čuva dubinu svakog piksela — udaljenost od kamere. Koristi se za rešavanje visibility problem-a — koji objekat je ispred kog.

Kad se novi piksel renderuje, njegova Z vrednost se poredi sa vrednošću u depth bufferu:

Nelinearnost depth buffer-a

Depth buffer ne čuva linearnu udaljenost od kamere. Zbog perspektivne projekcije, Z vrednosti su nelinearne — mnogo više preciznosti je koncentrisano blizu near plane-a, i sve manje prema far plane-u.

Za tipičan setup (near=0.1, far=10000):

Ovo znači da se Z-fighting (vizuelni artefakt gde se dva bliska objekta "bore" za isti piksel) dešava mnogo češće na velikim udaljenostima.

Reverse-Z

Reverse-Z je tehnika gde se depth buffer obrne:

Ovo koristi činjenicu da floating-point brojevi imaju veću preciznost blizu 0 nego blizu 1. Sa reverse-Z:

Rezultat: mnogo ravnomernija distribucija preciznosti i dramatično manje Z-fighting-a na velikim udaljenostima.

UE5 koristi reverse-Z sa infinite far plane — far plane je efektivno na beskonačnoj udaljenosti, a preciznost je i dalje dovoljna zahvaljujući reverse-Z.


Praktične implikacije za razvoj

Near plane i problemi

Near plane (najbliža ravan klipinga) je delikatan parametar:

UE5 default near plane je 10 cm (0.1 metra), što je dobar balans za većinu scenarija.

FOV i percepcija

Field of View (FOV) dramatično utiče na percepciju prostora:

VR zahteva FOV blizu prirodnog ljudskog vida (~110°) da bi bio uverljiv.

Aspect ratio

Aspect ratio (odnos širine i visine) utiče na projekcionu matricu:

Engine obično automatski prilagođava horizontalni ili vertikalni FOV na osnovu aspect ratio-a. Tipičan pristup: fiksiraj vertikalni FOV, prilagodi horizontalni po aspect ratio-u (tako da širi monitori vide više sveta levo-desno, ali istu visinu).


Rezime transformacije jednog verteksa

Hajde da pratimo jedan vertex kroz ceo pipeline:

1. Object Space: Vertex stolice: (0.5, 0.8, 0.0, 1.0)

2. Object → World (Model matrica): Stolica je na poziciji (500, 200, 0), rotirana 45° oko Z ose. WorldPos = ModelMatrix × (0.5, 0.8, 0.0, 1.0) = (500.14, 200.92, 0.0, 1.0)

3. World → View (View matrica): Kamera je na (510, 195, 1.7), gleda ka stolici. ViewPos = ViewMatrix × WorldPos = (-3.2, 0.5, -12.4, 1.0) (vertex je 12.4 jedinica ispred kamere, malo levo i gore)

4. View → Clip (Projection matrica): Perspektivna projekcija, FOV=90°, aspect=16:9. ClipPos = ProjMatrix × ViewPos = (-4.6, 0.9, 11.8, 12.4) (W = 12.4, što je originalna Z udaljenost)

5. Perspektivno deljenje (Clip → NDC): NDC = ClipPos / W = (-0.37, 0.07, 0.95) (malo levo od centra, malo gore, blizu far plane-a)

6. NDC → Screen (Viewport transform): Ekran 1920×1080. ScreenX = (-0.37 + 1) / 2 × 1920 = 604 piksela ScreenY = (1 - 0.07) / 2 × 1080 = 502 piksela ScreenZ = 0.95 (za depth buffer)

Vertex stolice se prikazuje na pikselu (604, 502), sa dubinom 0.95.


Rezime ključnih pojmova

Pojam Značenje
Object Space Lokalni koordinatni sistem objekta
World Space Zajednički koordinatni sistem scene
View Space Koordinatni sistem kamere
Clip Space Prostor nakon projekcije, pre perspektivnog deljenja
NDC Normalized Device Coordinates — normalizovane koordinate [-1,1]
Screen Space Koordinate piksela na ekranu
Model matrica Object → World transformacija
View matrica World → View transformacija (inverz kamere)
Projection matrica View → Clip transformacija (perspektiva ili ortografska)
MVP matrica Kombinovana Projection × View × Model
Frustum Vidljivi prostor kamere (zarubljena piramida)
Clipping Eliminisanje/odsecanje geometrije van frustuma
Perspektivno deljenje Deljenje sa W — daje perspektivni efekat
Near/Far plane Najbliža/najdalja ravan vidljivosti kamere
FOV Field of View — ugao otvaranja kamere
Depth buffer Tekstura koja čuva dubinu svakog piksela
Reverse-Z Obrnuti depth buffer za bolju preciznost na daljini
Tangent space Lokalni prostor površine (N, T, B) za normal mapping

Sledeće poglavlje daje pregled celog render pipeline-a — od vertex shadera do finalnog piksela. Sad kad razumeš prostore i transformacije, vreme je da vidiš kako GPU obrađuje geometriju korak po korak.

📖 Dalje čitanje: