De centrale verwerkingseenheid (CPU) en de grafische verwerkingseenheid (GPU) van uw computer werken samen op elk moment dat u uw computer gebruikt om u een scherpe en responsieve visuele interface te bieden. Lees verder om beter te begrijpen hoe ze samenwerken.
foto door sskennel .
De vraag- en antwoordsessie van vandaag komt tot ons dankzij SuperUser - een onderdeel van Stack Exchange, een community-drive groep van Q & A-websites.
De vraag
SuperUser-lezer Sathya stelde de vraag:
Hier zie je een screenshot van een klein C ++ programma genaamd Triangle.exe met een roterende driehoek gebaseerd op de OpenGL API.
Toegegeven, een heel eenvoudig voorbeeld, maar ik denk dat het van toepassing is op andere grafische kaartbewerkingen.
Ik was gewoon nieuwsgierig en wilde het hele proces weten van dubbelklikken op Triangle.exe onder Windows XP totdat ik de driehoek op de monitor kan zien draaien. Wat gebeurt er, hoe werken de CPU (die eerst de .exe afhandelt) en de GPU (die uiteindelijk de driehoek op het scherm uitvoert) op elkaar in?
Ik vermoed dat bij het weergeven van deze roterende driehoek voornamelijk de volgende hardware / software betrokken is:
Hardware
- HDD
- Systeemgeheugen (RAM)
- CPU
- Video geheugen
- GPU
- LCD display
Software
- Besturingssysteem
- DirectX / OpenGL API
- Nvidia-stuurprogramma
Kan iemand het proces uitleggen, misschien met een soort stroomschema ter illustratie?
Het zou geen complexe uitleg moeten zijn die elke stap omvat (denk dat dat buiten de scope zou vallen), maar een uitleg die een gemiddeld IT-man kan volgen.
Ik ben er vrij zeker van dat veel mensen die zichzelf IT-professionals zouden noemen, dit proces niet correct zouden kunnen beschrijven.
Het antwoord
Hoewel meerdere communityleden de vraag beantwoordden, deed Oliver Salzburg een stap verder en beantwoordde het niet alleen met een gedetailleerd antwoord, maar ook met uitstekende begeleidende graphics.
Afbeelding door JasonC, hier als behang verkrijgbaar .
Hij schrijft:
Ik besloot wat te schrijven over het programmeeraspect en hoe componenten met elkaar praten. Misschien werpt het wat licht op bepaalde gebieden.
De presentatie
Wat is er nodig om zelfs maar die ene afbeelding, die je in je vraag hebt gepost, op het scherm te laten tekenen?
Er zijn veel manieren om een driehoek op het scherm te tekenen. Laten we voor de eenvoud aannemen dat er geen hoekpuntbuffers zijn gebruikt. (EEN vertex buffer is een geheugengebied waar je coördinaten opslaat.) Laten we aannemen dat het programma de grafische verwerkingspijplijn simpelweg vertelde over elk hoekpunt (een hoekpunt is slechts een coördinaat in de ruimte) op een rij.
Maar , voordat we iets kunnen tekenen, moeten we eerst een steiger rennen. We zullen zien waarom later:
// Wis het scherm en de dieptebuffer glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset de huidige modelview-matrix glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Tekenen met driehoeken glBegin (GL_TRIANGLES); // Rood glColor3f (1.0f, 0.0f, 0.0f); // Top Of Triangle (voorkant) glVertex3f (0.0f, 1.0f, 0.0f); // Groen glColor3f (0,0f, 1,0f, 0,0f); // Links van driehoek (voorkant) glVertex3f (-1.0f, -1.0f, 1.0f); // Blauw glColor3f (0,0f, 0,0f, 1,0f); // Recht van driehoek (voorzijde) glVertex3f (1.0f, -1.0f, 1.0f); // Klaar met tekenen glEnd ();
Dus wat deed dat?
Als je een programma schrijft dat de grafische kaart wil gebruiken, kies je meestal een soort interface voor de driver. Enkele bekende interfaces met de driver zijn:
- OpenGL
- Direct3D
- WONDEREN
Voor dit voorbeeld blijven we bij OpenGL. Nu jij interface met de bestuurder is wat je alle tools geeft die je nodig hebt om je programma te maken praten naar de grafische kaart (of de driver, die dan praat op de kaart).
Deze interface geeft u zeker zekerheid gereedschap . Deze tools hebben de vorm van een BRAND die u vanuit uw programma kunt bellen.
Die API is wat we zien in het bovenstaande voorbeeld. Laten we dat van dichterbij bekijken.
De steiger
Voordat je echt een tekening kunt maken, moet je een opstelling . U moet uw viewport (het gebied dat daadwerkelijk wordt weergegeven), uw perspectief (het camera in uw wereld), welke anti-aliasing u gaat gebruiken (om de randen van uw driehoek glad te strijken) ...
Maar daar kijken we niet naar. We zullen gewoon een kijkje nemen naar de dingen die u moet doen elk frame . Leuk vinden:
Het scherm wissen
De grafische pijplijn zal niet elk frame het scherm voor je wissen. U zult het moeten vertellen. Waarom? Dit is waarom:
Als je het scherm niet leegmaakt, doe je dat gewoon
tekenen over
het elk frame. Daarom bellen we
glClear
met de
GL_COLOR_BUFFER_BIT
set. Het andere stukje (
GL_DEPTH_BUFFER_BIT
) vertelt OpenGL om het
diepte
buffer. Deze buffer wordt gebruikt om te bepalen welke pixels voor (of achter) andere pixels staan.
Transformatie
Transformatie is het deel waar we alle invoercoördinaten (de hoekpunten van onze driehoek) nemen en onze ModelView-matrix toepassen. Dit is de matrix die legt uit hoe onze model (de hoekpunten) worden geroteerd, geschaald en vertaald (verplaatst).
Vervolgens passen we onze projectiematrix toe. Dit verplaatst alle coördinaten zodat ze correct naar onze camera zijn gericht.
Nu transformeren we opnieuw met onze Viewport-matrix. We doen dit om onze model naar de grootte van onze monitor. Nu hebben we een reeks hoekpunten die klaar zijn om te worden weergegeven!
We komen later terug op de transformatie.
Tekening
Om een driehoek te tekenen, kunnen we OpenGL eenvoudig vertellen om een nieuwe te starten
lijst met driehoeken
door te bellen
glBegin
met de
GL_TRIANGLES
constante.
Er zijn ook andere vormen die u kunt tekenen. Zoals een
driehoek strip
of een
driehoek ventilator
. Dit zijn voornamelijk optimalisaties, omdat ze minder communicatie tussen de CPU en de GPU vereisen om hetzelfde aantal driehoeken te tekenen.
Daarna kunnen we een lijst met sets van 3 hoekpunten geven die elke driehoek moeten vormen. Elke driehoek gebruikt 3 coördinaten (aangezien we in 3D-ruimte zijn). Daarnaast bied ik ook een
kleur
voor elk hoekpunt, door aan te roepen
glColor3f
voordat
roeping
glVertex3f
.
De schaduw tussen de 3 hoekpunten (de 3 hoeken van de driehoek) wordt berekend door OpenGL automatisch . Het interpoleert de kleur over het hele vlak van de veelhoek.
Interactie
Nu, wanneer u op het venster klikt. De applicatie hoeft alleen het venster bericht dat de klik aangeeft. Vervolgens kunt u elke gewenste actie in uw programma uitvoeren.
Dit krijgt een veel moeilijker als je eenmaal wilt beginnen met interactie met je 3D-scène.
U moet eerst duidelijk weten op welke pixel de gebruiker op het venster heeft geklikt. Vervolgens neemt u uw perspectief Houd er rekening mee dat u de richting van een straal kunt berekenen vanaf het punt van de muisklik in uw scène. U kunt vervolgens berekenen of er een object in uw scène is snijdt met die straal . Nu weet je of de gebruiker op een object heeft geklikt.
Dus, hoe laat je het draaien?
Transformatie
Ik ken twee soorten transformaties die algemeen worden toegepast:
- Matrix-gebaseerde transformatie
- Op bot gebaseerde transformatie
Het verschil is dat botten invloed op single hoekpunten . Matrices beïnvloeden altijd alle getekende hoekpunten op dezelfde manier. Laten we naar een voorbeeld kijken.
Voorbeeld
Eerder hebben we onze identiteitsmatrix voordat we onze driehoek tekenen. De identiteitsmatrix is er een die eenvoudigweg voorziet geen transformatie helemaal. Dus wat ik ook teken, wordt alleen beïnvloed door mijn perspectief. De driehoek wordt dus helemaal niet gedraaid.
Als ik het nu wil draaien, kan ik ofwel de wiskunde zelf doen (op de CPU) en gewoon bellen
glVertex3f
met
andere
coördinaten (die worden geroteerd). Of ik kan de GPU al het werk laten doen, door te bellen
glRotatef
voor het tekenen:
// Draai de driehoek op de Y-as glRotatef (hoeveelheid, 0.0f, 1.0f, 0.0f);
bedrag
is natuurlijk slechts een vaste waarde. Als je wilt
geanimeerd
, moet u bijhouden
bedrag
en vergroot het elk frame.
Dus wacht, wat is er met al het matrixgesprek eerder gebeurd?
In dit eenvoudige voorbeeld hoeven we ons geen zorgen te maken over matrices. We bellen gewoon
glRotatef
en het regelt dat allemaal voor ons.
glRotateproduceert een rotatie vanhoekgraden rond de vector x y z. De huidige matrix (zie glMatrixMode ) wordt vermenigvuldigd met een rotatiematrix waarbij het product de huidige matrix vervangt, alsof glMultMatrix werden aangeroepen met de volgende matrix als 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
Bedankt daarvoor!
Gevolgtrekking
Wat duidelijk wordt, is dat er veel wordt gepraat naar OpenGL. Maar het zegt niets ons iets. Waar is de communicatie?
Het enige dat OpenGL ons in dit voorbeeld vertelt, is wanneer het klaar is . Elke operatie duurt een bepaalde tijd. Sommige operaties duren ongelooflijk lang, andere zijn ongelooflijk snel.
Een hoekpunt verzenden naar de GPU zal zo snel zijn dat ik niet eens zou weten hoe ik het moet uitdrukken. Het verzenden van duizenden hoekpunten van de CPU naar de GPU, elk afzonderlijk frame, is hoogstwaarschijnlijk helemaal geen probleem.
Het scherm wissen kan een milliseconde of erger duren (houd er rekening mee dat u gewoonlijk slechts ongeveer 16 milliseconden tijd heeft om elk frame te tekenen), afhankelijk van hoe groot uw viewport is. Om het te wissen, moet OpenGL elke afzonderlijke pixel tekenen in de kleur waarnaar u wilt wissen, dat kunnen miljoenen pixels zijn.
Verder kunnen we OpenGL vrijwel alleen vragen naar de mogelijkheden van onze grafische adapter (max. Resolutie, max. Anti-aliasing, max. Kleurdiepte,…).
Maar we kunnen een textuur ook vullen met pixels die elk een specifieke kleur hebben. Elke pixel heeft dus een waarde en de textuur is een gigantisch "bestand" gevuld met gegevens. We kunnen dat in de grafische kaart laden (door een textuurbuffer te maken) en vervolgens een shader , vertel die arcering om onze textuur als invoer te gebruiken en voer enkele extreem zware berekeningen uit op ons "bestand".
We kunnen dan het resultaat van onze berekening (in de vorm van nieuwe kleuren) 'renderen' in een nieuwe textuur.
Zo kunt u de GPU op andere manieren voor u laten werken. Ik neem aan dat CUDA hetzelfde presteert als dat aspect, maar ik heb nooit de kans gehad om ermee te werken.
We hebben het hele onderwerp eigenlijk maar een klein beetje aangeraakt. 3D grafische programmering is een verdomd beest.
Iets toe te voegen aan de uitleg? Geluid uit in de reacties. Wilt u meer antwoorden lezen van andere technisch onderlegde Stack Exchange-gebruikers? Bekijk hier de volledige discussiethread .