Unitatea centrală de procesare (CPU) și unitatea de procesare grafică (GPU) ale computerului dvs. 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 cum funcționează împreună.
Fotografie de sskennel .
Sesiunea de Întrebări și Răspunsuri de astăzi ne vine prin amabilitatea SuperUser - o subdiviziune a Stack Exchange, un grup comunitar de site-uri de întrebări și răspunsuri.
Intrebarea
Cititorul SuperUser 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 API-ul OpenGL.
Desigur, un exemplu foarte de bază, dar cred că este aplicabil și altor operații cu plăci grafice.
Am fost curios și am vrut să știu întregul proces de la dublu clic pe Triangle.exe sub Windows XP până când pot vedea triunghiul rotindu-se pe monitor. Ce se întâmplă, cum interacționează CPU (care se ocupă mai întâi de .exe) și GPU (care scoate în cele din urmă triunghiul de pe ecran)?
Cred că implicat în afișarea acestui triunghi rotativ este în primul rând următorul hardware / software, printre altele:
Hardware
- HDD
- Memorie de sistem (RAM)
- Procesor
- Memorie video
- GPU
- Ecran LCD
Software
- Sistem de operare
- API DirectX / OpenGL
- Driver Nvidia
Poate cineva să explice procesul, poate cu un fel de diagramă pentru ilustrare?
Nu ar trebui să fie o explicație complexă care să acopere fiecare pas (presupun că ar depăși domeniul de aplicare), ci o explicație pe care o poate urma un tip IT intermediar.
Sunt destul de sigur că o mulțime de oameni care și-ar spune chiar profesioniști IT nu ar putea descrie corect acest proces.
Răspunsul
Deși mai mulți membri ai comunității au răspuns la întrebare, Oliver Salzburg a făcut un efort suplimentar și a răspuns nu doar cu un răspuns detaliat, ci și cu o grafică excelentă.
Imagine de JasonC, disponibil ca tapet aici .
El scrie:
Am decis să scriu puțin despre aspectul programării și despre modul în care componentele vorbesc între ele. Poate că va arunca o lumină în anumite zone.
Prezentarea
Ce este nevoie pentru ca imaginea singură pe care ați postat-o în întrebarea dvs. să fie desenată pe ecran?
Există multe modalități de a desena un triunghi pe ecran. Pentru simplitate, să presupunem că nu au fost utilizate tampoane de vârf. (A tampon de vârf este o zonă a memoriei în care stocați coordonatele.) Să presupunem că programul a spus pur și simplu conductei de procesare grafică despre fiecare vârf (un vârf este doar o coordonată în spațiu) la rând.
Dar , înainte de a putea desena ceva, trebuie mai întâi să rulăm niște schele. Vom vedea De ce mai tarziu:
// Ștergeți ecranul și tamponul de adâncime glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Resetați Matricea actuală Modelview glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Desenarea folosind triunghiuri glBegin (GL_TRIANGLES); // Roșu glColor3f (1,0f, 0,0f, 0,0f); // Partea de sus a triunghiului (față) glVertex3f (0,0f, 1,0f, 0,0f); // Verde glColor3f (0,0f, 1,0f, 0,0f); // Stânga triunghiului (față) glVertex3f (-1.0f, -1.0f, 1.0f); // Albastru glColor3f (0,0f, 0,0f, 1,0f); // Dreapta triunghiului (față) glVertex3f (1.0f, -1.0f, 1.0f); // Desen finalizat glEnd ();
Deci, ce a făcut asta?
Când scrieți un program care dorește să utilizeze placa grafică, de obicei veți alege un fel de interfață pentru driver. Unele interfețe bine cunoscute pentru driver sunt:
- OpenGL
- Direct3D
- MINUNI
Pentru acest exemplu, vom rămâne cu OpenGL. Acum, a ta interfață cu driverul este ceea ce vă oferă toate instrumentele de care aveți nevoie pentru a vă crea programul vorbi la placa grafică (sau la driver, care apoi vorbește la card).
Această interfață vă va oferi siguranță instrumente . Aceste instrumente iau forma unui FOC pe care le puteți apela din programul dvs.
Acest API este ceea ce vedem că este folosit în exemplul de mai sus. Să aruncăm o privire mai atentă.
Schela
Înainte de a putea face cu adevărat orice desen efectiv, va trebui să efectuați un înființat . Trebuie să vă definiți fereastra de vizualizare (zona care va fi de fapt redată), perspectiva dvs. ( camera în lumea ta), ce anti-aliasing vei folosi (pentru a netezi marginile triunghiului tău) ...
Dar nu vom analiza nimic din toate acestea. Vom arunca o privire asupra lucrurilor pe care va trebui să le faceți fiecare cadru . Ca:
Ștergerea ecranului
Conducta grafică nu va șterge ecranul pentru fiecare cadru. Va trebui să-i spuneți. De ce? De-aceea:
Dacă nu ștergeți ecranul, pur și simplu
trage peste
fiecare cadru. De aceea apelăm
glClear
cu
GL_COLOR_BUFFER_BIT
a stabilit. Celălalt bit (
GL_DEPTH_BUFFER_BIT
) îi spune OpenGL să șteargă
adâncime
tampon. Acest tampon este utilizat pentru a determina ce pixeli sunt în fața (sau în spatele) altor pixeli.
Transformare
Transformarea este partea în care luăm toate coordonatele de intrare (vârfurile triunghiului nostru) și aplicăm matricea ModelView. Aceasta este matricea care explică cum model (vârfurile) sunt rotite, scalate și traduse (mutate).
Apoi, aplicăm matricea noastră de proiecție. Aceasta mișcă toate coordonatele, astfel încât să fie orientate corect către camera noastră.
Acum ne transformăm încă o dată, cu matricea Viewport. Facem acest lucru pentru a-l scala model la dimensiunea monitorului nostru. Acum avem un set de vârfuri care sunt gata să fie redate!
Vom reveni la transformare puțin mai târziu.
Desen
Pentru a desena un triunghi, putem spune pur și simplu OpenGL să înceapă un nou
lista triunghiurilor
sunând
glBegin
cu
GL_TRIANGLES
constant.
Există, de asemenea, alte forme pe care le puteți desena. Ca o
bandă triunghiulară
sau a
ventilator triunghi
. Acestea sunt în primul rând optimizări, deoarece necesită mai puțină comunicare între CPU și GPU pentru a desena aceeași cantitate de triunghiuri.
După aceea, putem furniza o listă de seturi de 3 vârfuri care ar trebui să alcătuiască fiecare triunghi. Fiecare triunghi folosește 3 coordonate (așa cum suntem în spațiul 3D). În plus, ofer și un
culoare
pentru fiecare vârf, apelând
glColor3f
inainte de
chemând
glVertex3f
.
Umbra dintre cele 3 vârfuri (cele 3 colțuri ale triunghiului) este calculată de OpenGL automat . Acesta va interpola culoarea pe întreaga față a poligonului.
Interacţiune
Acum, când faceți clic pe fereastră. Aplicația trebuie doar să capteze fișierul mesaj fereastra care semnalizează clicul. Apoi, puteți rula orice acțiune din programul dorit.
Aceasta devine o lot mai dificil odată ce doriți să începeți să interacționați cu scena dvs. 3D.
Mai întâi trebuie să știți clar la ce pixel a făcut clic utilizatorul pe fereastră. Apoi, luând-o perspectivă ținând cont, puteți calcula direcția unei raze, din punctul clicului mouse-ului în scena dvs. Apoi puteți calcula dacă vreun obiect din scena dvs. se intersectează cu raza aceea . Acum știți dacă utilizatorul a dat clic pe un obiect.
Deci, cum o faci să se rotească?
Transformare
Sunt conștient de două tipuri de transformări care se aplică în general:
- Transformare bazată pe matrice
- Transformarea bazată pe oase
Diferența este că oase afectează singur vârfuri . Matricele afectează întotdeauna toate vârfurile trasate în același mod. Să vedem un exemplu.
Exemplu
Anterior, ne-am încărcat matrice de identitate înainte de a ne desena triunghiul. Matricea de identitate este una care oferă pur și simplu nici o transformare deloc. Deci, orice desenez, este afectat doar de perspectiva mea. Deci, triunghiul nu va fi rotit deloc.
Dacă vreau să-l rotesc acum, aș putea să fac calculele singur (pe CPU) și să sun simplu
glVertex3f
cu
alte
coordonate (care sunt rotite). Sau aș putea lăsa GPU să facă toată treaba, apelând
glRotatef
înainte de a desena:
// Rotiți triunghiul pe axa Y glRotatef (cantitate, 0,0f, 1,0f, 0,0f);
Cantitate
este, desigur, doar o valoare fixă. Dacă dorești
animate
, va trebui să țineți evidența
Cantitate
și mărește-l la fiecare cadru.
Deci, așteaptă, ce s-a întâmplat cu toate discuțiile matrice mai devreme?
În acest exemplu simplu, nu trebuie să ne pese de matrice. Pur și simplu sunăm
glRotatef
și are grijă de toate acestea pentru noi.
glRotateproduce o rotație deunghigrade în jurul vectorului x y z. Matricea curentă (vezi glMatrixMode ) este înmulțită cu o matrice de rotație, produsul înlocuind matricea curentă, ca și cum glMultMatrix au fost chemate cu următoarea matrice ca argument:x 2 1 - c + cx y 1 - c - z sx z 1 - c + y s 0 y x 1 - c + z sy 2 1 - c + cy z 1 - c - x s 0 x z 1 - c - y sy z 1 - c + x sz 2 1 - c + c 0 0 0 0 1
Ei bine, mulțumesc pentru asta!
Concluzie
Ceea ce devine evident este că se vorbește mult la OpenGL. Dar nu este grăitor ne orice. Unde este comunicarea?
Singurul lucru pe care ni-l spune OpenGL în acest exemplu este cand e gata . Fiecare operație 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 va fi atât de rapid, nici nu aș ști cum să-l exprim. Trimiterea a mii de vârfuri de la CPU la GPU, fiecare cadru unic, este, cel mai probabil, nicio problemă.
Ștergerea ecranului poate dura o milisecundă sau mai rău (rețineți, de obicei aveți doar aproximativ 16 milisecunde de timp pentru a desena fiecare cadru), în funcție de cât de mare este ecranul dvs. Pentru a-l șterge, OpenGL trebuie să atragă fiecare pixel în culoarea pe care doriți să o ștergeți, care ar putea fi milioane de pixeli.
În afară de asta, putem întreba OpenGL doar despre capacitățile adaptorului nostru grafic (rezoluție maximă, anti-aliasing maxim, adâncime maximă de culoare ...).
Dar putem, de asemenea, să umplem o textură cu pixeli care au fiecare o culoare specifică. Fiecare pixel deține astfel o valoare, iar textura este un „fișier” gigant umplut cu date. Putem încărca asta pe placa grafică (prin crearea unui tampon de textură), apoi încărcăm un umbra , spuneți acel shader să folosească textura noastră ca intrare și să execute niște calcule extrem de grele pe „fișierul” nostru.
Putem apoi „reda” rezultatul calculului nostru (sub formă de culori noi) într-o nouă textură.
Așa puteți face ca GPU să funcționeze pentru dvs. în alte moduri. Presupun că CUDA are o performanță similară cu acel aspect, dar nu am avut niciodată ocazia să lucrez cu acesta.
Într-adevăr am atins ușor tot subiectul. Programarea grafică 3D este o fiară.
Aveți ceva de adăugat la explicație? Sună în comentarii. Doriți să citiți mai multe răspunsuri de la alți utilizatori ai Stack Exchange? Consultați aici firul complet de discuție .