Steps3d - tutoriale - redare la tamponul vertex în opengl

După cum știți, transferul datelor de la CPU la unitatea de procesare grafică este o operație destul de costisitoare și, prin urmare, este de dorit să se minimizeze numărul acestor transmisii.

Cu toate acestea, în multe cazuri, este nevoie de un transfer constant al unor magistrale de vârfuri mari ale GPU-urilor. Această situație apare atunci când există o lege prea complicat de conversie a datelor în noduri (care sau chiar nu poate fi realizată printr-un vertex shader sau este foarte scump în termeni de viteză), sau atunci când există o schimbare în topologia obiectului (modificarea numărului de noduri, organizarea lor în primitivele și altele asemenea).







În astfel de cazuri, ar fi extrem de convenabil să puteți construi astfel de matrice de vârfuri direct pe GPU. Apoi, nu ar fi nevoie de transfer de date costisitoare de la CPU la GPU și toate operațiile cu vârfurile vor fi efectuate în întregime pe GPU și pe GPU.

Din păcate, GPU (nu vom considera SM4) poate construi numai texturi - este suficient să folosim extensia EXT_framebuffer_object. permițându-vă să faceți direct în textură. Ca rezultat, putem construi o textura direct pe GPU-urile de orice dimensiune si format (desigur, suportate de acest GPU).

Cu toate acestea, dacă te uiți atent, devine evident faptul că textura diferă de matrice vârf singura modalitate de a utiliza - și textura și vârful matrice este o matrice de vectori (1-4-dimensionale) ale unui anumit tip (inclusiv float).

Deci, avem exact ceea ce avem nevoie, dacă adăugăm capacitatea de a copia pur și simplu textura (sau o porțiune a acestuia) în matrice vertex (si va fi copiat în memoria GPU, care are loc la viteze foarte mari).

Această posibilitate este oferită de extensiile EXT_pixel_buffer_object și ARB_pixel_buffer_object.

Ca rezultat construcția poate fi realizată cu un fragment shader textură specială (textură prin redare, este de dorit, în acest caz, pentru a folosi textura componente montaj în virgulă mobilă), iar apoi datele rezultate sunt pur și simplu copiate direct în matrice vertex.

O tehnică similară se numește redare la matricea vârfurilor (render-to-vertex-buffer).

Construirea unui peisaj pe o hartă înălțime

Ca un prim exemplu, ia în considerare transformarea texturii care cuprinde o hartă înălțime, într-o serie de vârfuri, în care fiecare textură texel va corespunde unui nod, z coordonate care este proporțională cu luminozitatea pixelilor.

În acest caz, textura fragment Shader în construcție va conține o serie de vârfuri ale peisajului definit de hartă înălțimea inițială. Pentru construirea acestui peisaj, trebuie să copiați datele din textura matrice nod corespunzător și punerea în aplicare a acestuia de redare.

Ca rezultat, direct pe GPU, o matrice de 256 2 vârfuri este construită pe fiecare cadru și fără a lăsa limitele GPU această matrice de vârfuri este imediat ieșită.

Mai jos este un fragment al codului care construiește matricea de vârfuri și redarea ulterioară a acesteia (codul complet este disponibil la sfârșitul articolului).

Pentru confortul muncii, pe lângă clasele FrameBuffer și GlslProgram, clasa VertexBuffer este de asemenea utilizată aici. descrierea și implementarea cărora sunt prezentate mai jos.

Următoarea figură prezintă un exemplu al imaginii rezultate (culoarea utilizată pentru a indica înălțimea punctului pentru a face relieful mai vizibil).

Steps3d - tutoriale - redare la tamponul vertex în opengl

Figura 1. Peisaj, construit pe o hartă de înălțimi.

Mai jos sunt shadere fragment pentru randare textura si redare matrice vertex rezultat.

Realizarea unei suprafețe animate de apă







Ca următorul exemplu de a folosi randarea în textură, să analizăm randarea apei animate. În loc de utilizarea tradițională a cartografierii ciocnirilor, vom construi vertexul animat și matricele normale în mișcare, folosind turbulența ca o funcție de animație.

Este foarte convenabil să ia posibilitatea de a face o dată la două texturi (MRT, Multiple Render Ținte) - într-o singură coordonate de textură ale nodurilor sunt afișate, și într-un alt - vectorul normal de la aceste noduri.

Plus utilizarea de redare tampon la vârf, în acest caz, este posibilitatea de a lucra cu texturi în calculul nodurilor (nu tot sprijinul recursul la vârf textura GPU, și chiar dacă suportul său este, de obicei, modurile de filtrare normale nu sunt disponibile).

Următoarea listă arată fragmentul de shader utilizat pentru a construi nodurile și normalele în ele.

Pentru a face suprafața apei, utilizați următorul shader de fragmente.

Mai jos este un fragment de cod utilizat pentru a construi vertex și matrice normale și pentru a scoate suprafața de apă rezultată.

Figura următoare prezintă imaginea rezultată a apei.

Steps3d - tutoriale - redare la tamponul vertex în opengl

Fig. 2. Suprafața apei.

Animație scheletară

Ca un exemplu următor, luați în considerare implementarea modelelor de animație scheletică din jocul DooM III prin redare la tamponul de vertex.

Deși în cele mai simple cazuri, animația scheletului poate fi implementată cu programe de vârf, o astfel de implementare este eficientă doar cu un număr foarte mic de oase (articulații) în partea de sus (1-2).

Acest lucru se datorează faptului că pentru fiecare os trebuie să transmită o cantitate destul de mare de date. În timp ce toate aceste date sunt plasate în atributele vertex standard ale OpenGL, totul este bine.

Cu toate acestea, atunci când cantitatea de os la partea superioară a 5 sau mai mult (și în modelele DooM III este utilizat în top 10 al osului) transmise pentru fiecare date nod nu este plasat în atributele standard, OpenGL, și trebuie să utilizeze formularul atributele vertex generale (glVertexAttrib *).

Numărul acestora este de asemenea limitată și, mai important, de obicei funcționează cu vârf OpenGL atribute standard mai eficient (a se vedea articolul de pe site-ul pseudoinstancing developer.nvidia.com în OpenGL).

Cu un număr mare de vârfuri, folosirea unui program de vertex pentru animația scheletului are ca rezultat o sarcină grea pe procesoarele de vertex, în timp ce procesoarele de fragmente sunt de obicei mai optimizate (și există mai multe).

Prin urmare, utilizarea în redarea tamponul vârf poate fi mult mai convenabil - toate datele Vertex pot fi plasate în texturi, pentru a calcula pozițiile nodurilor utilizate de către procesoarele de fragmente și numărul de noduri în modelul nu mai are prea multă influență asupra performanței (în termeni desigur animație scheletic).

În primul rând, vom analiza exact ce texturi avem nevoie și ce date vor fi plasate în ele.

Mai întâi, avem nevoie de texturi care vor stoca informații despre toate oasele scheletului (joinsMap). Pentru fiecare os al scheletului, trebuie să ne amintim orientarea (quaternion, adică vectorul tridimensional), poziția (vector tridimensional) și indicele (numărul) osului părinte.

Este ușor de observat că, atunci când se utilizează texturi RGBA cu componente cu virgulă mobilă, avem nevoie de două texele per os.

Deoarece oasele din scheletul este, de obicei, un pic, este mai ușor de utilizat de tip GL_TEXTURE_RECTANGLE_ARB textura (precum și pentru toate celelalte texturi utilizate pentru calcularea animației scheletic) Dimensiunea 2 * numJoints 1 texel.

Conținutul acestei texturi se va schimba pentru fiecare cadru al animației.

De asemenea, avem nevoie de două texturi pentru a lucra cu vârfurile. Primul dintre ele (weightsMap) va păstra pentru fiecare greutate deplasarea (pos), contribuția greutății date și indicele osului corespunzător (jointIndex).

Aici avem nevoie de două texele (în format RGBA) pentru o greutate:

Deoarece dimensiunea textura este, de asemenea, convenabil de a folosi GL_TEXTURE_RECTANGLE_ARB, dar din moment ce numărul de greutăți poate fi destul de mare, este mai bine să se stabilească o suficient de mare lățime de valoare textura (de exemplu, 512), și se calculează înălțimea de textura pe zbor, în funcție de numărul total de ponderi ale modelului.

În cele din urmă, avem nevoie de o textura (vertexWeightsMap), care, pentru fiecare nod va stoca două valori - numărul primei greutate (weightIndex) și numărul de greutăți consecutive (weightCount).

Apoi avem nevoie de un singur texel în partea de sus.

Rețineți că majoritatea modelelor Doom III constau de fapt din mai multe submodule (de obicei datorită necesității de a folosi diferite shadere pentru diferite părți ale modelului).

Pentru implementarea noastră va fi foarte convenabil pentru toate submodelele să construiască un set comun de date (de ex. Texturi), și într-o singură trecere să animeze toate submodelele dintr-o dată. În principiu, o astfel de abordare poate fi dezvoltată în continuare, animând într-o singură trecere un grup mare de modele simultan.

Următorul este un fragment de shader care efectuează animații scheletice. Deoarece GLSL nu are suport încorporat pentru quaternioane, două operații de bază pe ele - înmulțirea a două quaternioane și rotirea unui vector cu ajutorul unui quaternion - se fac în funcții separate.

Tot codul sursă poate fi descărcat de pe acest link. De asemenea, puteți descărca versiunile compilate pentru M $ Windows. Linux și Mac OS X.







Trimiteți-le prietenilor: