Pagina principala » HOWTO » Cum procesează GPU-ul și GPU-ul pentru a desena grafica computerelor?

    Cum procesează GPU-ul și GPU-ul pentru a desena grafica computerelor?

    Unitatea centrală de procesare (CPU) și unitatea de procesare grafică (GPU) a computerului interacționează în fiecare moment în care utilizați computerul pentru a vă oferi o interfață vizuală clară și receptivă. Citiți mai departe pentru a înțelege mai bine modul în care acestea lucrează împreună.

    Fotografie de sskennel.

    Sesiunea de întrebări și răspunsuri din ziua de azi vine de la amabilitatea programului SuperUser - o subdiviziune a Stack Exchange, o grupare de comunicații pe site-uri web Q & A.

    Intrebarea

    Cititorul super-utilizator Sathya a pus întrebarea:

    Aici puteți vedea o captură de ecran a unui mic program C ++ numit Triangle.exe cu un triunghi rotativ bazat pe OpenGL API.

    Desigur, un exemplu foarte simplu, dar cred că este aplicabil și altor operațiuni cu carduri grafice.

    Am fost curios și am vrut să cunosc întregul proces făcând clic dublu pe Triangle.exe sub Windows XP până când văd triunghiul rotindu-se pe monitor. Ce se întâmplă, cum interacționează CPU (care manipulează mai întâi .exe) și GPU (care trimit în cele din urmă triunghiul pe ecran)?

    Cred că implicat în afișarea acestui triunghi rotativ este în primul rând următoarele hardware / software, printre altele:

    Hardware

    • HDD
    • Memoria sistemului (RAM)
    • Procesor
    • Memorie video
    • GPU
    • Ecran LCD

    Software-ul

    • Sistem de operare
    • DirectX / OpenGL API
    • Nvidia Driver

    Poate cineva să explice procesul, poate cu un fel de grafic pentru ilustrare?

    Aceasta nu ar trebui să fie o explicație complexă care să acopere fiecare pas (presupune că ar depăși domeniul de aplicare), dar o explicație pe care un tip IT intermediar poate să o urmeze.

    Sunt sigur că o mulțime de oameni care chiar s-ar numi profesioniști IT nu au putut descrie corect acest proces.

    Răspunsul

    Deși mai mulți membri ai comunității au răspuns la întrebare, Oliver Salzburg a mers extra mile și a răspuns nu doar cu un răspuns detaliat, ci și cu o excelentă grafică însoțitoare.

    Imagine de JasonC, disponibilă ca tapet aici.

    El scrie:

    Am decis să scriu un pic despre aspectul de programare și modul în care componentele vorbesc unul cu celălalt. Poate că va lumina anumite zone.

    Prezentarea

    Ce este necesar pentru a avea chiar acea singură imagine pe care ați postat-o ​​în întrebarea dvs., desenată pe ecran?

    Există multe modalități de a desena un triunghi pe ecran. Pentru simplificare, să presupunem că nu s-au folosit tampoane de vertex. (A vertex tamponeste o zonă de memorie în care stocați coordonatele.) Să presupunem că programul a spus pur și simplu conductei de procesare grafică despre fiecare vertex (un vertex este doar o coordonată în spațiu) într-un rând.

    Dar, înainte de a putea trage ceva, mai întâi trebuie să executăm niște schele. Vom vedea De ce mai tarziu:

    // Ștergeți ecranul și bufferul de adâncime glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Resetați Matricea curentă de vizualizare a modelului glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Desenarea cu ajutorul glangelor triunghiulare (GL_TRIANGLES); // Red glColor3f (1.0f, 0.0f, 0.0f); // Topul triunghiului (Frontul) glVertex3f (0.0f, 1.0f, 0.0f); // verde glColor3f (0.0f, 1.0f, 0.0f); // Stânga triunghiului (Front) glVertex3f (-1.0f, -1.0f, 1.0f); // Blue glColor3f (0.0f, 0.0f, 1.0f); // Dreptul triunghiului (Frontul) glVertex3f (1.0f, -1.0f, 1.0f); // Terminat desenul glEND ();

    Deci, ce a făcut asta?

    Când scrieți un program care dorește să utilizeze placa grafică, veți alege, de obicei, un tip de interfață pentru driver. Unele interfețe bine cunoscute conducătorului auto sunt:

    • OpenGL
    • Direct3D
    • CUDA

    Pentru acest exemplu vom rămâne cu OpenGL. Acum, tu interfață cu șoferul este ceea ce vă oferă toate instrumentele de care aveți nevoie pentru a vă face programul vorbi pe placa grafică (sau pe conducătorul auto, care apoi tratative la card).

    Această interfață este obligată să vă ofere anumite informații unelte. Aceste instrumente au forma unui API pe care îl puteți apela din programul dvs..

    API-ul este ceea ce vedem utilizându-se în exemplul de mai sus. Să aruncăm o privire mai atentă.

    Schela

    Înainte de a putea face cu adevărat orice desen real, va trebui să efectuați un a înființat. Trebuie să definiți portul de vizualizare (zona care va fi realmente redată), perspectiva dvs. ( aparat foto în lumea voastră), ce anti-aliasing veți folosi (pentru a netezi marginea triunghiului) ...

    Dar nu ne vom uita la asta. Vom arunca o privire asupra lucrurilor pe care trebuie să le faceți fiecare cadru. Ca:

    Ștergerea ecranului

    Conducta grafică nu va șterge ecranul pentru fiecare cadru. Va trebui să-i spui. De ce? De-aceea:

    Dacă nu ștergeți ecranul, pur și simplu trageți fiecare cadru. De aceea sunăm glClear cuGL_COLOR_BUFFER_BIT a stabilit. Celălalt bit (GL_DEPTH_BUFFER_BIT) spune OpenGL pentru a șterge adâncimetampon. Acest tampon este utilizat pentru a determina ce pixeli sunt în fața (sau în spatele) altor pixeli.

    Transformare


    Sursă de imagini

    Transformarea este partea în care luăm toate coordonatele de intrare (vârfurile triunghiului nostru) și aplicăm matricea noastră ModelView. Aceasta este matricea asta explică cum ne model (vârfurile) sunt rotite, scalate și traduse (mutate).

    Apoi, aplicăm matricea de proiecție. Aceasta mișcă toate coordonatele, astfel încât să se confrunte cu camera noastră corect.

    Acum ne transformăm încă o dată, cu matricea Viewport. Facem asta pentru a ne scala model la dimensiunea monitorului nostru. Acum avem un set de vârfuri care sunt pregătite pentru a fi redate!

    Vom reveni la transformare un pic mai târziu.

    Desen

    Pentru a desena un triunghi, putem spune pur și simplu OpenGL să înceapă un nou lista de triunghiuri sunând glBegin cu GL_TRIANGLES constant.
    Există și alte forme pe care le puteți desena. Ca o bandă triunghiulară sau un ventilator triunghiular. Acestea sunt în primul rând optimizări, deoarece necesită o mai mică comunicare între CPU și GPU pentru a trage aceeași cantitate de triunghiuri.

    După aceasta, putem furniza o listă de seturi de 3 noduri care ar trebui să alcătuiască fiecare triunghi. Fiecare triunghi foloseste 3 coordonate (asa cum suntem in spatiul 3D). În plus, ofer o a culoare pentru fiecare vârf, prin apelareglColor3f inainte de apel glVertex3f.

    Umbra dintre cele trei noduri (cele 3 colțuri ale triunghiului) este calculată de OpenGLautomat. Aceasta va interpola culoarea pe toată fața poligonului.

    Interacţiune

    Acum, când faceți clic pe fereastră. Aplicația trebuie doar să capteze mesajul de fereastră care semnalizează clicul. Apoi, puteți executa orice acțiune în programul pe care îl doriți.

    Acest lucru devine a mult mai dificilă odată ce doriți să începeți să interacționați cu scena dvs. 3D.

    Mai întâi trebuie să știți în mod clar la ce pixel utilizatorul a făcut clic pe fereastră. Apoi, luați-vă perspectivăluați în considerare, puteți calcula direcția unei raze, din punctul de acces al mouse-ului în scenă. Puteți calcula apoi dacă există vreun obiect în scenă intersecteaza cu acea rază. Acum știi dacă utilizatorul a făcut clic pe un obiect.

    Deci, cum o faceți să se rotească?

    Transformare

    Sunt conștient de două tipuri de transformări care sunt în general aplicate:

    • Matricea bazată pe transformare
    • Transformarea pe bază de oase

    Diferența este aceea oase afecta singur noduri. Matricile afectează întotdeauna toate vârfurile trase în același mod. Să ne uităm la un exemplu.

    Exemplu

    Anterior, ne-am încărcat matrice de identitate înainte de a desena triunghiul nostru. Matricea de identitate este una care oferă pur și simplu nici o transformare deloc. Deci, orice am desenat, este afectat numai de perspectiva mea. Deci, triunghiul nu va fi rotit deloc.

    Dacă vreau să o rotesc acum, aș putea să fac eu însumi matematica (pe CPU) și pur și simplu să sun glVertex3f cualte coordonate (care sunt rotite). Sau aș putea lăsa GPU-ul să facă toată munca, sunând glRotatefînainte de desen:

    // Rotiți triunghiul pe axa Y glRotatef (suma, 0.0f, 1.0f, 0.0f); 

    Cantitate este, desigur, doar o valoare fixă. Dacă dorești anima, va trebui să urmăriți Cantitateși să crească în fiecare cadru.

    Așteaptă, ce sa întâmplat cu toată discuția despre matrice mai devreme?

    În acest exemplu simplu, nu trebuie să ne pasă de matrice. Pur și simplu sunăm glRotatef și are grijă de toate acestea pentru noi.

    glRotate produce o rotație a unghi grade în jurul vectorului x y z. Matricea curentă (seeglMatrixMode) este înmulțită cu o matrice de rotație cu produsul care înlocuiește matricea curentă, deoarece ifglMultMatrix au fost numiți cu matricea următoare ca argument:

    x 2 ⁡ 1 - c + cx ı y ⁡ 1 - c - zxx z ⁡ 1 - c + y s y y ⁡ 1 - c + z sy 2 ⁡ 1 - c + c z z ⁡ 1 - c - x s 0 x z z ⁡ 1 - c - y syz z ⁡ 1 - c + x sz 2 ⁡ 1 - c + c 0 0 0 0 1

    Mulțumesc pentru asta!

    Concluzie

    Ceea ce devine evident este că vorbim mult la OpenGL. Dar nu spune ne orice. Unde este comunicarea?

    Singurul lucru pe care ni-l spune OpenGL în acest exemplu este cand e gata. Fiecare operațiune va dura o anumită perioadă de timp. Unele operații durează incredibil de mult, altele sunt incredibil de rapide.

    Trimiterea unui vârf la GPU-ul va fi atât de rapid, nici măcar nu aș ști cum să-l exprim. Trimiterea a mii de noduri de la CPU la unitatea de procesare grafică, fiecare cadru, nu este deloc o problemă.

    Ștergerea ecranului poate dura o milisecundă sau mai rău (rețineți că, de obicei, aveți doar 16 milisecunde de timp pentru a desena fiecare cadru), în funcție de cât de mare este fereastra de vizualizare. Pentru ao șterge, OpenGL trebuie să deseneze fiecare pixel în culoarea pe care doriți să o eliminați, care ar putea fi milioane de pixeli.

    În afară de asta, putem doar să cerem OpenGL doar despre capacitățile adaptorului nostru grafic (rezoluție maximă, max anti-aliasing, adâncime de culoare max., ...).

    Dar putem de asemenea să umplem o textura cu pixeli, fiecare având o anumită culoare. Fiecare pixel păstrează astfel o valoare și textura este un "fișier" uriaș umplut cu date. Putem încărca acest lucru în placa grafică (prin crearea unui tampon de textură), apoi încărcați un shader, spuneți că shaderul să folosească textura noastră ca intrare și să execute niște calcule extrem de grele în "fișierul".

    Putem apoi "render" rezultatul calculului nostru (sub forma de noi culori) într-o nouă textura.

    Acesta este modul în care puteți face GPU să lucreze pentru dvs. în alte moduri. Presupun că CUDA se comportă similar cu acest aspect, dar nu am avut ocazia să lucrez cu el.

    Chiar am atins doar puțin subiectul întreg. Programarea grafică 3D este o iad de o fiară.


    Sursa de imagini


    Aveți ceva de adăugat la explicație? Sunați în comentariile. Doriți să citiți mai multe răspunsuri de la alți utilizatori de tehnologie Stack Exchange? Check out discuția completă aici.