How do I create a viewing frustum?

Proiecția în Perspectivă: Crearea Frustumului de Vizualizare

24/01/2024

Rating: 4.65 (8362 votes)

În lumea fascinantă a graficii pe calculator, capacitatea de a transforma o scenă tridimensională într-o imagine bidimensională pe ecran este fundamentală. Una dintre cele mai comune și impresionante metode de a realiza acest lucru este prin utilizarea proiecției în perspectivă. Aceasta imită modul în care ochiul uman sau o cameră reală percepe lumea, făcând obiectele mai îndepărtate să pară mai mici și liniile paralele să conveargă spre puncte de fugă. Este tehnica preferată în jocuri, efecte speciale cinematografice și vizualizări ale lumilor virtuale, oferind un realism vizual de neegalat.

How far should a frustum be from a camera?

La baza oricărei proiecții în perspectivă stă conceptul de frustum de vizualizare. Acesta este o zonă 3D care se proiectează de la locația camerei de-a lungul a patru raze de delimitare, formând o piramidă trunchiată. Orice model sau obiect aflat în interiorul acestui frustum va fi randat, în timp ce tot ce se află în afara lui va fi tăiat (clipped) și nu va fi afișat. Înțelegerea modului în care este definit și manipulat acest frustum este crucială pentru oricine dorește să aprofundeze grafica pe calculator.

Cuprins

Ce Definește un Frustum de Vizualizare?

Un frustum de vizualizare este delimitat de două planuri de tăiere (clipping planes) paralele cu planul X-Y: un plan „near” (aproape) și un plan „far” (îndepărtat). Aceste planuri, împreună cu cele patru raze laterale care pornesc din „apexul” frustumului (locația camerei), definesc volumul exact care va fi vizibil. Camera este, de fapt, apexul acestei piramide trunchiate.

Patru parametri principali definesc un frustum de vizualizare:

  • fovy: Acesta reprezintă „field of view y-axis” și este unghiul vertical al lentilei camerei. Valorile comune pentru fovy variază între 30 și 60 de grade. O valoare mai mare va cuprinde o zonă mai largă, dar cu distorsiuni mai pronunțate la margini.
  • aspect ratio: Este raportul dintre lățimea și înălțimea ferestrei de randare (canvas window). De exemplu, pentru un ecran 16:9, aspect ratio va fi 16/9. Este vital pentru a evita alungirea sau aplatizarea imaginii.
  • near: Distanța până la planul de tăiere din față. Aceasta este orice număr pozitiv, dar trebuie să fie întotdeauna mai mică decât „far”.
  • far: Distanța până la planul de tăiere din spate. De asemenea, orice număr pozitiv, dar mai mare decât „near”.

Este esențial să menținem distanța dintre planurile „near” și „far” cât mai mică posibil. Deși valorile tipice pot fi de la 0.1 la 100.0, o diferență prea mare poate duce la probleme de precizie (cunoscut sub numele de „z-fighting” sau „artefacte de adâncime”), deoarece frustumul este mapat într-un volum de tăiere de doar 2 unități adâncime. În general, se recomandă ca „near” să fie cât mai departe de cameră, iar „far” cât mai aproape, în limita necesităților scenei, pentru a maximiza precizia în intervalul relevant.

Punctele 3D (left, bottom, near) și (right, top, near) definesc colțurile inferioare stânga și superioare dreapta ale ferestrei de vizualizare. Dacă calculați centrul ferestrei de vizualizare și proiectați acest punct înapoi pe planul X-Y, obțineți apexul frustumului. Razele proiectate de la apex prin cele patru puncte ale ferestrei de vizualizare formează frustumul.

Matricea de Proiecție în Perspectivă: O Calatorie Matematică

O matrice de proiecție are rolul de a transforma vârfurile unei scene într-un volum de tăiere standardizat, care este un cub cu lățimea de 2 unități, centrat pe origine. Realizarea acestui lucru pentru o proiecție în perspectivă este mai complexă decât pentru o proiecție ortografică, deoarece necesită manipulări mai substanțiale ale vârfurilor. Matematica implicată este elegantă, dar necesită câteva „trucuri” pentru a integra calculele într-o matrice de transformare 4x4. Procesul implică următorii pași:

  1. Traducerea apexului frustumului la origine.
  2. Efectuarea calculului de perspectivă.
  3. Scalarea valorilor 2D (x’,y’) din fereastra de vizualizare la un pătrat de 2x2 unități: de la (-1,-1) la (+1,+1).
  4. Scalarea valorilor de adâncime (z) într-un interval normalizat (-1,+1).
  5. Inversarea orientării axei z pentru a se potrivi cu orientarea volumului de tăiere.

1. Mutarea Apexului Frustumului la Origine

Un frustum de perspectivă poate fi decalată de la originea globală de-a lungul axelor X sau Y. Pentru ca calculele de perspectivă să funcționeze corect, trebuie să plasăm apexul frustumului la originea globală. Apexul este situat în centrul ferestrei de vizualizare în planul XY. Prin urmare, calculăm punctul central al ferestrei de vizualizare și îl translatăm la origine. Valoarea z rămâne neschimbată.

mid_x = (left + right) * 0.5;
mid_y = (bottom + top) * 0.5;

Matricea de transformare corespunzătoare este:

| 1 0 0 0 | | 0 1 0 0 | | 0 0 1 0 | | -mid_x -mid_y 0 1 | 

2. Calculul de Perspectivă

Trebuie să proiectăm fiecare vârf din scena noastră în locația sa corectă în fereastra de vizualizare 2D, care este planul „near” al frustumului. Un vârf (x,y,z) este proiectat pe fereastra de vizualizare prin proiectarea unei raze către cameră. Locația de randare pentru vârf este (x',y',near).

Din diagramele geometrice, se observă că valorile y și y' sunt legate prin triunghiuri dreptunghice proporționale. Raportul lungimilor laturilor acestor două triunghiuri trebuie să fie egal. Astfel, y'/near trebuie să fie egal cu y/z. Rezolvând pentru y' obținem (y/z)*near, sau y' = (y*near)/z. Similar, x' = (x*near)/z.

Pentru a fi preciși, deoarece toate valorile z pentru vârfurile din fața camerei sunt negative (în multe sisteme de coordonate, camera privește de-a lungul axei Z negative), iar valoarea lui z este tratată ca o distanță, trebuie să negăm valoarea lui z:

x' = (x * near) / (-z)
y' = (y * near) / (-z)

Aceasta introduce o problemă: o matrice de transformare 4x4 este o combinație liniară de termeni (a*x + b*y + c*z + d), dar nu poate efectua operații de tipul a*x/z. Soluția constă în utilizarea coordonatelor omogene. Un vârf definit ca (x,y,z,w) definește o locație în spațiul 3D la punctul (x/w, y/w, z/w). În mod normal, componenta w este 1, iar (x,y,z) sunt coordonatele reale. Dar pentru a implementa diviziunea de perspectivă, putem seta valoarea w la divizorul nostru, (-z). Aceasta împarte calculele în două părți: o transformare matricială efectuează înmulțirea, iar un pas de post-procesare (după înmulțirea matricială) efectuează diviziunea omogenă.

Matricea care efectuează calculul de perspectivă și pregătește valoarea w pentru diviziune este:

| near 0 0 0 | | 0 near 0 0 | | 0 0 1 -1 | | 0 0 0 0 | 

Pipeline-ul grafic este conceput să aștepte divizorul de perspectivă în componenta w și va calcula automat (x/w, y/w, z/w) înainte de a transmite valorile vârfului către etapele următoare.

3. Scalarea Ferestrei de Vizualizare la Domeniul Normalizat (-1,+1)

Etapele ulterioare din pipeline-ul grafic necesită ca fereastra de vizualizare 2D să fie normalizată la valori între (-1,-1) și (+1,+1). Scalăm valorile x și y la un pătrat de 2x2 unități. Acest lucru se realizează ușor cu un factor de scalare bazat pe un raport simplu: 2/dimensiuneaCurentă. Ecuațiile și matricea de transformare rezultată sunt:

scale_x = 2.0 / (right - left);
scale_y = 2.0 / (top - bottom);

| scale_x 0 0 0 | | 0 scale_y 0 0 | | 0 0 1 0 | | 0 0 0 1 | 

4. Maparea Adâncimii (Valorilor Z) la Domeniul Normalizat (-1,+1)

Am calculat locația corectă pentru un vârf în fereastra de vizualizare 2D, dar nu am modificat componenta z. Nu putem ignora valoarea z; aceasta ne indică distanța dintre un vârf și cameră, permițându-ne să determinăm care obiecte sunt în fața altor obiecte (testul de adâncime). Am putea face o mapare liniară între intervalul (-near,-far) și (-1,+1), dar numerele în virgulă mobilă suferă de erori de rotunjire. În aplicațiile grafice, uneori o diferență minusculă poate avea un impact vizual. Dorim să folosim mai multă precizie pentru valorile apropiate de cameră și mai puțină precizie pentru vârfurile mai îndepărtate. Aceasta înseamnă că dorim o mapare non-liniară între (-near,-far) și (-1,+1).

Ecuația non-liniară utilizată pentru mapare este c1/-z + c2, unde c1 și c2 sunt constante calculate pe baza intervalului (-near,-far). Când z = -near, ecuația trebuie să calculeze -1. Când z = -far, ecuația trebuie să calculeze +1. Aceasta ne oferă două ecuații pentru a rezolva pentru c1 și c2:

c1 = 2 * far * near / (near - far)
c2 = (far + near) / (far - near)

Să luăm un exemplu. Să presupunem near = 2.0 și far = 40. Aceasta înseamnă că vârfurile cu o valoare a componentei z între -2 și -40 vor fi incluse în volumul de tăiere. Observați cum valorile z între -2 și -3.8 utilizează jumătate din valorile volumului de tăiere (-1.0, 0.0)! Aceasta este cu siguranță o mapare non-liniară, care oferă o precizie superioară pentru obiectele apropiate.

Z VârfZ în Volumul de Tăiere (near=2, far=40)
-2.0-1.0000
-3.0-0.2982
-4.00.0526
-5.00.2632
-6.00.4035
-8.00.5789
-10.00.6842
-12.00.7544
-14.00.8045
-16.00.8421
-18.00.8713
-20.00.8947
-25.00.9368
-30.00.9649
-35.00.9850
-40.01.0000

La fel ca și în cazul calculului de perspectivă, nu putem introduce o expresie de tipul c1/-z + c2 direct într-o matrice de transformare. Așadar, folosim același „truc” al diviziunii omogene: amânăm diviziunea până la pasul de diviziune omogenă, după transformare. Ecuația de mapare poate fi scrisă ca (c1 + c2*(-z))/(-z), sau rearanjată (-c2*z + c1)/(-z). Partea superioară a acestei ecuații este introdusă în matricea noastră de transformare, iar diviziunea omogenă se va ocupa de împărțire ulterior. Este important ca această transformare să fie aplicată în timp ce w este încă 1.0.

| 1 0 0 0 | | 0 1 0 0 | | 0 0 -c2 -1 | | 0 0 c1 0 | 

5. Inversarea Orientării Axelor

Ultimul pas ar fi inversarea direcției axei z pentru a se potrivi cu orientarea volumului de tăiere. Totuși, acest lucru nu este necesar deoarece, atunci când am mapat valorile z la un interval non-liniar, noul interval a fost de la -1 la +1, ceea ce a inversat efectiv direcția axei z.

Întrebări Frecvente (FAQ)

Ce este diferența dintre proiecția ortografică și cea în perspectivă?

Proiecția ortografică nu simulează adâncimea; obiectele își păstrează dimensiunea indiferent de distanța lor față de cameră și liniile paralele rămân paralele. Este adesea folosită în aplicații de inginerie sau desene tehnice unde precizia dimensiunilor este crucială. Proiecția în perspectivă, pe de altă parte, imită viziunea umană, făcând obiectele mai îndepărtate să pară mai mici și liniile paralele să conveargă, creând un sentiment de adâncime și realism.

De ce este important să menținem distanța dintre 'near' și 'far' cât mai mică?

Menținerea unei distanțe mici între planurile „near” și „far” este crucială pentru a minimiza erorile de precizie ale numerelor în virgulă mobilă în buffer-ul de adâncime (Z-buffer). Un interval prea mare poate duce la „z-fighting” – artefacte vizuale unde obiectele care ar trebui să fie în spatele altora apar intermitent în fața lor, din cauza lipsei de precizie în reprezentarea adâncimii. Prin reducerea intervalului, se alocă mai multă precizie valorilor de adâncime din zona relevantă a scenei.

Cum afectează 'fovy' și 'aspect ratio' frustumul de vizualizare?

„fovy” (field of view y-axis) controlează unghiul vertical al vederii camerei. O valoare mai mare a „fovy” extinde frustumul pe verticală, incluzând mai mult din scenă, dar poate introduce distorsiuni „fish-eye”. O valoare mai mică restrânge vederea, similar cu un teleobiectiv. „Aspect ratio” (raportul de aspect) influențează lățimea frustumului în raport cu înălțimea, asigurând că imaginea randată nu este întinsă sau comprimată necorespunzător pe ecran, menținând proporțiile corecte ale obiectelor.

Concluzie

Crearea unei proiecții în perspectivă și definirea corectă a frustumului de vizualizare sunt pași fundamentali în construirea oricărei scene 3D realiste. Deși matematica din spatele matricei de transformare 4x4 poate părea complexă la prima vedere, înțelegerea fiecărui pas – de la translația apexului la origină, la calculul de perspectivă cu ajutorul coordonatelor omogene și maparea non-liniară a adâncimii – este esențială. Această cunoaștere nu doar demistifică procesul de randare, ci și oferă instrumentele necesare pentru a optimiza performanța și calitatea vizuală a aplicațiilor grafice. Prin stăpânirea acestor concepte, veți putea manipula cu precizie modul în care lumea virtuală este adusă la viață pe ecran.

Dacă vrei să descoperi și alte articole similare cu Proiecția în Perspectivă: Crearea Frustumului de Vizualizare, poți vizita categoria Fitness.

Go up