Tesselarea dinamică a terenului


Acest articol abordează modalități statice și dinamice de calcul al nivelului de tesselare, modalități de andocare a patch-urilor cu detalii diferite și un algoritm pentru tăierea patch-urilor invizibile. Înainte de a citi acest articol, vă recomandăm să citiți articolul despre cartografiere hardware și deplasare.








Fiecare capitol al articolului utilizează propriile shadere, pentru a comuta între exemple utilizați tastele F1..F6. pentru comutarea modurilor sunt tastele 1..8 sau (și) - comutați la modul precedent și, respectiv, la modul următor. Ca o caracteristică suplimentară, puteți vizualiza normal și nivelul de tessellation utilizat pentru această cheie C. N. T. M - pentru a afișa culoarea textura, normală, nivelul de tessellation și modul mixt: culoarea și nivelul de tessellation. Tasta R este utilizată pentru a reîncărca shaderele curente, P comută între afișarea ochiului și poligon.
În exemplele în care se acceptă schimbarea burghiului, sunt utilizate următoarele chei:
- și + modifică nivelul maxim de tessellation,
<и> modifică nivelul de detaliu,
[și] modifică înălțimea terenului.
Pentru a vă deplasa, utilizați tastele W. S. A. A pentru a vă deplasa vertical - Shift. Spațiu.
Antetul ferestrei afișează partea selectată a exemplului, corespunzătoare părții articolului, numărul de cadre pe secundă, numărul de vârfuri generat și generat.


Aici, ca și în alte exemple, este desenată o rețea cu dimensiunile de 128x128 vârfuri, se utilizează patch-uri triunghiulare sau pătrate (în funcție de exemplu). Pătrările patrate ocupă mai puțin spațiu - 4 plasturi sunt utilizați pentru un plasture față de 6 pentru un plasture triunghiular.
Înainte de a desena grila, dimensiunea patch-ului este setată:

Implicit, dimensiunea patch-urilor este 3. Dacă nu setați dimensiunea corectă a patch-urilor, de exemplu puneți 3, atunci când shader-ul este definit ca 4, atunci nu vor exista erori, dar acestea nu vor fi desenate corect.
Pentru a evita astfel de erori, puteți obține valoarea patch-ului de la shader prin funcția glGetProgramiv cu parametrul GL_TESS_CONTROL_OUTPUT_VERTICES. valoarea specificată în șirul de control din șir va reveni:

Shader de evaluare este citită de pe card și altitudinea normală, poziția este deplasată la înălțimea hărții înălțime, iar normală este trecut la shader fragment, care poate fi folosit pentru a calcula iluminat.

În acest exemplu, se utilizează tessellation uniform de patch-uri pătrate, nivelul de tessellation este fix și egal cu valoarea maximă, ceea ce reduce foarte mult performanța. Următoarele părți vor descrie optimizarea redării cu conservarea calității.


Pentru a păstra calitatea partiției de suprafață, trebuie să utilizați detaliile variabile, dar există o problemă - patch-urile vecine pot avea detalii diferite, ceea ce duce la întreruperi între ele. Prin urmare, parametrul gl_TessLevelOuter este folosit pentru a conecta corecțiile corecte cu detalii diferite.
În exemplul respectiv, pentru fiecare vârf din shaderul de vârf, este dată o valoare aleatoare a nivelului de tessellation,
modurile cu tastele 1 și 2, puteți activa și dezactiva starea corectă de andocare. Rezultatul inecării incorecte:

Tesselarea dinamică a terenului

Imaginea de ecran afișează mai multe lacune între plăcuțele cu detalii diferite.

În shader-ul de control, este setat nivelul de tessellation la limita patch-urilor, pentru o asociere corectă, este necesar ca aceste niveluri să coincidă. Acest lucru se datorează aceleiași performanțe a funcției de calcul al nivelului de tessellation în toate shaderele, în exemple aceasta este funcția max:

Puteți utiliza orice funcție de calcul ale cărei rezultate pentru marginile identice vor coincide.


Plăci triunghiulare.
Pentru patch-urile triunghiulare, se folosesc doar trei valori din gl_TessLevelOuter.
Indicele zero din gl_TessLevelOuter este afectat de vârfurile cu indexul 1 și 2, primul indice este 0 și 2, al doilea indice este 0 și 1.
exemplu:

Patch-uri patrate.
Pentru patch-uri pătrat, toate cele patru valori de la gl_TessLevelOuter sunt utilizate.
La index zero în nodurile gl_TessLevelOuter Viliia cu indexul 0 și 3, la început - 0 și 1, al doilea - 1 și 2, al treilea - 2 și 3.
exemplu:

Valoarea gl_TessLevelInner poate fi oricare - nu afectează în nici un fel corecta andocare,
dar pentru o tessellare uniformă este de dorit să se ia valoarea maximă sau medie a nivelurilor
tessellation de marginile (gl_TessLevelOuter), de exemplu:


Merită menționat faptul că atunci când scrieți zerouri la gl_TessLevelInner și gl_TessLevelOuter, patch-ul nu este creat,
Această proprietate poate fi utilizată pentru a scoate patch-uri, dar merită de asemenea să țineți cont
tăierea nu a fost accidentală, deci exemplul folosește funcția clemei:

UnMaxTessLevel este nivelul maxim de tessellation definit în aplicație.








În acest exemplu, se utilizează o textura pre-generată cu un nivel de detaliere pentru fiecare vârf. Pentru a stoca nivelul de detaliu, este suficient să aveți texturi de format R8 cu o rezoluție de 128x128 (un texel per vârf).

Codul shader de fragmente gen_normal_and_tesslvl.prg constă din două funcții:
ReadHeight - citește textură într-o matrice 4x4, pentru aceasta, sunt utilizate 4 apeluri funcționale de texturăGatherOffsets.
GenTessLevel - generarea niveluri caracteristica de detaliu, calculate elevație între punctele în două treceri pe verticală și pe orizontală, rezultatul este normalizat și stocat în textura.

În shaderul de tip tessellation, se adaugă nivelul de detaliu al shader-ului de vârf.

Tesselarea dinamică a terenului

Așa cum se poate vedea în captura de ecran în care diferența de elevație este mai mare decât nivelul de tessellation (culoarea roșie este nivelul maxim de detaliu), acest lucru a permis reducerea numărului de poligoane cu mai mult de 2 ori. Poligoanele îndepărtate au un nivel de detaliu prea mare pentru a corecta această problemă, se folosește următoarea metodă.


Cel mai mare detaliu este necesar în apropierea camerei, iar mai departe de cameră, cu atât mai puține detalii, în acest exemplu, este utilizată o schimbare liniară a detecției de la distanța până la cameră.
Nivelul de detaliere al vârfului este calculat în shaderul de vârfuri, în acest scop este utilizată funcția Nivel:

unDetailLevel - nivel de detaliu.
dist este distanța de la aparatul de fotografiat la vârf, se calculează după cum urmează:


Pentru a calcula corect distanța, trebuie să mutați vârful la valoarea definită în harta înălțimii de-a lungul normalei la suprafață și să proiectați spațiul de pe ecran. Dupa aceea se calculeaza distanta de sus. Deoarece aparatul foto este mereu în centrul coordonatelor, este suficient să cunoaștem lungimea vectorului.
Acestea sunt toate modificările aduse programului, totul este destul de simplu și numărul de poligoane a scăzut de mai mult de 10 ori.

Tesselarea dinamică a terenului


În exemplul anterior, depozitele de deșeuri îndepărtate pot avea insuficiente detalii, în special vizibile pe intervale mari, nivelul schimbărilor de detaliu în tehnică, în funcție de dimensiunea poligonului remedierile ecran această problemă.
În shaderul vârfului, se adaugă traducerea poziției vertexului în spațiul de pe ecran:


În shaderul de control se calculează nivelul de tessellation pentru fiecare margine:

Funcția Niveluri returnează nivelul de detaliere, în funcție de mărimea marginii:

unDetailLevel - nivelul detaliat definit în aplicație, ca în exemplul anterior. Semnificația ei
este prea mare, deci este folosit un factor de 0,01.


Această abordare are mai multe dezavantaje:
1. În timp ce se mișcă, detalierea tuturor patch-urilor se schimbă imediat - acest lucru cauzează pâlpâirea, parțial
corectată prin utilizarea detaliilor superioare și a unui alt tip de partiționare:


2. Când se întinde un poligon, marginile sale pot varia foarte mult în dimensiune.
Ca urmare, apar zone cu detalii mici.
Pentru a nu provoca probleme la fixarea patch-urilor, nu puteți mări detaliile acestor margini -
în patch-urile vecine nu vor exista informații despre el. Soluția la această problemă poate fi o combinație cu tehnica anterioară.

Tesselarea dinamică a terenului


În acest exemplu, se adaugă tăierea de patch-uri invizibile pentru două metode dinamice de calcul al detaliului. Schimbările în ele vor fi aceleași, astfel încât să se trateze doar un exemplu. Tastele 1 și 2 sunt utilizate pentru a comuta între exemple.
Funcția shader pentru vârfuri a fost adăugată pentru a verifica lovitura de vârfuri de pe ecran:

dimensiune - definește dimensiunea ecranului, nu este destul de constantă - poate lua valori de la 1.0 și mai mult.
Cu cât dimensiunea parametrului este mai mare, cu atât mai multe poligoane în apropierea marginii ecranului vor fi vizibile,
care nu intră exact pe ecran. Valoarea 1.0 oferă o tăiere mai bună și o precizie redusă la margini
deseori taie excesul. O valoare de 1,2 oferă o precizie bună și un nivel minim de operare. Pentru a vedea cum se face patch-ul, puteți seta valoarea dimensiunii la mai puțin de 1, rezultatul pentru valoarea de 0,7 este afișat în captura de ecran:

Tesselarea dinamică a terenului

Rezultatul verificării și coordonatele de ecran ale vârfului sunt transferate la shaderul de control:


Se pare că dacă știți dacă toate vârfurile patch-urilor ajung pe ecran, puteți să le tăiați în siguranță,
dar nu este așa. În multe cazuri, problemele nu vor apărea, dar când toate vârfurile plasturii nu sunt lovite
în zona ecranului și poligonul este încă vizibil, atunci vor fi necesare verificări suplimentare.

Tesselarea dinamică a terenului

Verificarea va fi destul de simplă - verificați intersecția plasturelui cu ecranul în coordonatele ecranului:

Funcția Rect calculează AABB pentru nodurile de patch-uri, mărimea constantă este aceeași ca în funcția InScreen. Aici folosim algoritmul de verificare a dreptunghiului de control al dreptunghiului.

Ei bine, atunci totul este simplu:

Dacă plasturele nu este vizibil, atunci k are valoarea zero și când este înmulțită cu nivelul de tessellation
este, de asemenea, un zero, ca urmare, plasturele este tăiat de către tessellator.

Prin capturi de ecran, puteți compara două metode de calcul al tessellation dinamic este utilizat patch-uri pătrate și începutul patch-uri-sacrificare z, astfel încât să puteți evalua detaliile referitoare la numărul de primitivelor de ieșire:

Tesselarea dinamică a terenului

Tesselarea dinamică a terenului


Pentru diferite cazuri, pot fi adecvate diferite tehnici, dar un amestec de două sau trei tehnici va fi mai eficient. De exemplu, folosind tehnica distanței împreună cu creșterea partiției interioare a patch-urilor (gl_TessLevelInner) în funcție de dimensiunea ecranului.

În concluzie, vreau să mulțumesc lui Kirill Bazhenov (aka bazhenovc) pentru că mi-a ajutat să scriu exemple și articole.







Articole similare

Trimiteți-le prietenilor: