Η κεντρική μονάδα επεξεργασίας (CPU) και η μονάδα επεξεργασίας γραφικών (GPU) του υπολογιστή σας αλληλεπιδρούν κάθε στιγμή που χρησιμοποιείτε τον υπολογιστή σας για να σας προσφέρει μια ευκρινή και ευέλικτη οπτική διεπαφή. Διαβάστε παρακάτω για να κατανοήσετε καλύτερα πώς συνεργάζονται.
Φωτογραφία από sskennel .
Η σημερινή συνεδρία Ερωτήσεων & Απαντήσεων μας προσφέρει ευγενική προσφορά του SuperUser - μιας υποδιαίρεσης του Stack Exchange, μιας κοινότητας ομαδοποίησης ιστότοπων Q&A.
Το ερώτημα
Ο αναγνώστης SuperUser Sathya έθεσε την ερώτηση:
Εδώ μπορείτε να δείτε ένα στιγμιότυπο οθόνης ενός μικρού προγράμματος C ++ που ονομάζεται Triangle.exe με ένα περιστρεφόμενο τρίγωνο που βασίζεται στο OpenGL API.
Βεβαίως ένα πολύ βασικό παράδειγμα, αλλά πιστεύω ότι ισχύει για άλλες λειτουργίες καρτών γραφικών.
Ήμουν απλώς περίεργος και ήθελα να μάθω όλη τη διαδικασία κάνοντας διπλό κλικ στο Triangle.exe στα Windows XP μέχρι να δω το τρίγωνο να περιστρέφεται στην οθόνη. Τι συμβαίνει, πώς αλληλεπιδρούν η CPU (που χειρίζεται πρώτα το .exe) και η GPU (η οποία εξάγει τελικά το τρίγωνο στην οθόνη);
Υποθέτω ότι εμπλέκεται στην εμφάνιση αυτού του περιστρεφόμενου τριγώνου είναι κυρίως το ακόλουθο υλικό / λογισμικό μεταξύ άλλων:
Σκεύη, εξαρτήματα
- HDD
- Μνήμη συστήματος (RAM)
- ΕΠΕΞΕΡΓΑΣΤΗΣ
- Μνήμη βίντεο
- GPU
- οθόνη LCD
Λογισμικό
- Λειτουργικό σύστημα
- API DirectX / OpenGL
- Πρόγραμμα οδήγησης Nvidia
Μπορεί κανείς να εξηγήσει τη διαδικασία, ίσως με κάποιο διάγραμμα ροής για απεικόνιση;
Δεν πρέπει να είναι μια περίπλοκη εξήγηση που καλύπτει κάθε βήμα (μαντέψτε ότι θα ξεπερνούσε το πεδίο εφαρμογής), αλλά μια εξήγηση που μπορεί να ακολουθήσει ένας ενδιάμεσος τύπος πληροφορικής.
Είμαι σίγουρος ότι πολλοί άνθρωποι που θα μπορούσαν να αποκαλούν τους εαυτούς τους επαγγελματίες πληροφορικής δεν θα μπορούσαν να περιγράψουν σωστά αυτήν τη διαδικασία.
Η απάντηση
Αν και πολλά μέλη της κοινότητας απάντησαν στην ερώτηση, ο Όλιβερ Σάλτσμπουργκ προσπάθησε πολύ και απάντησε όχι μόνο με μια λεπτομερή απάντηση, αλλά και εξαιρετικά συνοδευτικά γραφικά.
Εικόνα από τον JasonC, διαθέσιμο ως ταπετσαρία εδώ .
Αυτός γράφει:
Αποφάσισα να γράψω λίγο για την πτυχή του προγραμματισμού και τον τρόπο με τον οποίο τα στοιχεία μιλούν μεταξύ τους. Ίσως θα ρίξει φως σε ορισμένες περιοχές.
Η παρουσίαση
Τι χρειάζεται για να έχει κανείς αυτήν την ενιαία εικόνα, την οποία δημοσιεύσατε στην ερώτησή σας, στην οθόνη;
Υπάρχουν πολλοί τρόποι για να σχεδιάσετε ένα τρίγωνο στην οθόνη. Για απλότητα, ας υποθέσουμε ότι δεν χρησιμοποιήθηκαν buffers κορυφής (ΕΝΑ buffer κορυφής είναι μια περιοχή μνήμης όπου αποθηκεύετε συντεταγμένες.) Ας υποθέσουμε ότι το πρόγραμμα απλώς είπε στον αγωγό επεξεργασίας γραφικών για κάθε μεμονωμένη κορυφή (μια κορυφή είναι απλώς μια συντεταγμένη στο διάστημα) στη σειρά.
Αλλά , πριν μπορέσουμε να σχεδιάσουμε οτιδήποτε, πρέπει πρώτα να κάνουμε κάποια σκαλωσιές Θα δούμε Γιατί αργότερα:
// Διαγράψτε την οθόνη και το ρυθμιστικό βάθους glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Επαναφορά του τρέχοντος μοντέλου Modelview glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Σχέδιο με χρήση τριγώνων glBegin (GL_TRIANGLES); // Το κόκκινο glColor3f (1.0f, 0.0f, 0.0f); // Κορυφή του τριγώνου (εμπρός) glVertex3f (0,0f, 1,0f, 0,0f); // Πράσινο glColor3f (0,0f, 1,0f, 0,0f); // Αριστερά τρίγωνο (εμπρός) glVertex3f (-1.0f, -1.0f, 1.0f); // Μπλε glColor3f (0,0f, 0,0f, 1,0f); // Δεξιά Τριγώνου (Μπροστά) glVertex3f (1.0f, -1.0f, 1.0f); // Έγινε σχέδιο glEnd ();
Τι έκανε λοιπόν;
Όταν γράφετε ένα πρόγραμμα που θέλει να χρησιμοποιήσει την κάρτα γραφικών, συνήθως θα επιλέξετε κάποιο είδος διεπαφής στο πρόγραμμα οδήγησης. Μερικές γνωστές διεπαφές με το πρόγραμμα οδήγησης είναι:
- OpenGL
- Direct3D
- ΜΑΡΑΚΛΙΑ
Για αυτό το παράδειγμα θα διατηρήσουμε το OpenGL. Τώρα, το δικό σας διεπαφή με το πρόγραμμα οδήγησης είναι αυτό που σας δίνει όλα τα εργαλεία που χρειάζεστε για να δημιουργήσετε το πρόγραμμά σας ΜΙΛΑ ρε στην κάρτα γραφικών (ή στο πρόγραμμα οδήγησης, το οποίο στη συνέχεια συνομιλίες στην κάρτα).
Αυτή η διεπαφή θα σας δώσει σίγουρη εργαλεία . Αυτά τα εργαλεία έχουν τη μορφή ενός ΦΩΤΙΑ που μπορείτε να καλέσετε από το πρόγραμμά σας.
Αυτό το API είναι αυτό που βλέπουμε να χρησιμοποιείται στο παραπάνω παράδειγμα. Ας ρίξουμε μια πιο προσεκτική ματιά.
Τα ικριώματα
Για να μπορέσετε πραγματικά να κάνετε οποιοδήποτε πραγματικό σχέδιο, θα πρέπει να εκτελέσετε ένα εγκατάσταση . Πρέπει να ορίσετε τη θύρα προβολής σας (την περιοχή που θα αποδοθεί), την προοπτική σας ( ΦΩΤΟΓΡΑΦΙΚΗ ΜΗΧΑΝΗ στον κόσμο σας), τι αντι-ψευδώνυμο θα χρησιμοποιείτε (για να εξομαλύνετε τις άκρες του τριγώνου σας)…
Αλλά δεν θα εξετάσουμε κανένα από αυτά. Θα ρίξουμε μια ματιά στα πράγματα που πρέπει να κάνετε κάθε πλαίσιο . Σαν:
Εκκαθάριση της οθόνης
Ο αγωγός γραφικών δεν πρόκειται να καθαρίσει την οθόνη για κάθε καρέ. Θα πρέπει να το πεις. Γιατί; Αυτός είναι ο λόγος:
Εάν δεν εκκαθαρίσετε την οθόνη, απλά
πλησιάζω
κάθε πλαίσιο. Γι 'αυτό καλούμε
glClear
με την
GL_COLOR_BUFFER_BIT
σειρά. Το άλλο κομμάτι (
GL_DEPTH_BUFFER_BIT
) λέει στο OpenGL να διαγράψει το
βάθος
ρυθμιστής. Αυτό το buffer χρησιμοποιείται για να προσδιορίσει ποια pixel βρίσκονται μπροστά (ή πίσω) από άλλα pixel.
Μεταμόρφωση
Ο μετασχηματισμός είναι το μέρος όπου παίρνουμε όλες τις συντεταγμένες εισόδου (τις κορυφές του τριγώνου μας) και εφαρμόζουμε τη μήτρα ModelView. Αυτή είναι η μήτρα που εξηγεί πώς μας μοντέλο (οι κορυφές) περιστρέφονται, κλιμακώνονται και μεταφράζονται (μετακινούνται).
Στη συνέχεια, εφαρμόζουμε τον πίνακα προβολών. Αυτό μετακινεί όλες τις συντεταγμένες έτσι ώστε να βλέπουν σωστά την κάμερά μας.
Τώρα μεταμορφώνουμε για άλλη μια φορά, με τον πίνακα Viewport Το κάνουμε αυτό για να κλιμακώσουμε το δικό μας μοντέλο στο μέγεθος της οθόνης μας. Τώρα έχουμε ένα σύνολο κορυφών που είναι έτοιμα για απόδοση!
Θα επιστρέψουμε στον μετασχηματισμό λίγο αργότερα.
Σχέδιο
Για να σχεδιάσουμε ένα τρίγωνο, μπορούμε απλά να πούμε στο OpenGL να ξεκινήσει ένα νέο
λίστα των τριγώνων
τηλεφωνώντας
glBegin
με την
GL_TRIANGLES
συνεχής.
Υπάρχουν επίσης άλλες φόρμες που μπορείτε να σχεδιάσετε. Σαν ένα
τριγωνική λωρίδα
ή α
ανεμιστήρας τριγώνου
. Αυτές είναι κυρίως βελτιστοποιήσεις, καθώς απαιτούν λιγότερη επικοινωνία μεταξύ της CPU και της GPU για να σχεδιάσουν το ίδιο ποσό τριγώνων.
Μετά από αυτό, μπορούμε να παρέχουμε μια λίστα με σύνολα 3 κορυφών που θα πρέπει να αποτελούν κάθε τρίγωνο. Κάθε τρίγωνο χρησιμοποιεί 3 συντεταγμένες (όπως βρισκόμαστε σε 3D-space). Επιπλέον, παρέχω επίσης ένα
χρώμα
για κάθε κορυφή, καλώντας
glColor3f
πριν
κλήση
glVertex3f
.
Η απόχρωση μεταξύ των 3 κορυφών (οι 3 γωνίες του τριγώνου) υπολογίζεται από το OpenGL αυτομάτως . Θα παρεμβάλλει το χρώμα σε ολόκληρη την όψη του πολυγώνου.
ΑΛΛΗΛΕΠΙΔΡΑΣΗ
Τώρα, όταν κάνετε κλικ στο παράθυρο. Η εφαρμογή πρέπει να καταγράψει μόνο το μήνυμα παραθύρου που σηματοδοτεί το κλικ. Στη συνέχεια, μπορείτε να εκτελέσετε οποιαδήποτε ενέργεια στο πρόγραμμά σας που θέλετε.
Αυτό παίρνει ένα παρτίδα πιο δύσκολο όταν θέλετε να αρχίσετε να αλληλεπιδράτε με την τρισδιάστατη σκηνή σας.
Πρέπει πρώτα να ξέρετε με σαφήνεια σε ποιο pixel ο χρήστης έκανε κλικ στο παράθυρο. Τότε, παίρνοντας το δικό σας προοπτική υπόψη, μπορείτε να υπολογίσετε την κατεύθυνση μιας ακτίνας, από το σημείο του κλικ του ποντικιού στη σκηνή σας. Στη συνέχεια, μπορείτε να υπολογίσετε εάν υπάρχει κάποιο αντικείμενο στη σκηνή σας τέμνει με αυτήν την ακτίνα . Τώρα ξέρετε αν ο χρήστης έκανε κλικ σε ένα αντικείμενο.
Λοιπόν, πώς το κάνετε να περιστρέφεται;
Μεταμόρφωση
Γνωρίζω δύο τύπους μετασχηματισμών που εφαρμόζονται γενικά:
- Μετασχηματισμός με βάση το Matrix
- Μετασχηματισμός με βάση τα οστά
Η διαφορά είναι ότι οστά επηρεάζουν μόνο κορυφές . Οι πίνακες επηρεάζουν πάντα όλες τις ζωγραφισμένες κορυφές με τον ίδιο τρόπο. Ας δούμε ένα παράδειγμα.
Παράδειγμα
Νωρίτερα, φορτώσαμε το μήτρα ταυτότητας πριν σχεδιάσουμε το τρίγωνό μας. Ο πίνακας ταυτότητας είναι αυτός που παρέχει απλά χωρίς μετασχηματισμό καθόλου. Έτσι, ό, τι σχεδιάζω, επηρεάζεται μόνο από την προοπτική μου. Έτσι, το τρίγωνο δεν θα περιστραφεί καθόλου.
Εάν θέλω να το περιστρέψω τώρα, θα μπορούσα είτε να κάνω τα μαθηματικά ο ίδιος (στη CPU) και απλά να τηλεφωνήσω
glVertex3f
με
άλλα
συντεταγμένες (που περιστρέφονται) Ή θα μπορούσα να αφήσω την GPU να κάνει όλη τη δουλειά, τηλεφωνώντας
glRotatef
πριν σχεδιάσετε:
// Περιστρέψτε το τρίγωνο στον άξονα Υ glRotatef (ποσό, 0,0f, 1,0f, 0,0f);
ποσό
είναι, φυσικά, μια σταθερή τιμή. Αν θέλεις
κινούμενα
, θα πρέπει να παρακολουθείτε
ποσό
και αυξήστε το κάθε καρέ.
Λοιπόν, περιμένετε, τι συνέβη σε όλες τις συνομιλίες του πίνακα;
Σε αυτό το απλό παράδειγμα, δεν χρειάζεται να ενδιαφερόμαστε για τους πίνακες. Απλώς καλούμε
glRotatef
και τα φροντίζει όλα αυτά για εμάς.
glRotateπαράγει μια περιστροφή τουγωνίαμοίρες γύρω από το διάνυσμα x y z. Ο τρέχων πίνακας (βλ glMatrixMode ) πολλαπλασιάζεται με έναν πίνακα περιστροφής με το προϊόν που αντικαθιστά τον τρέχοντα πίνακα, σαν glMultMatrix κλήθηκαν με τον ακόλουθο πίνακα ως επιχείρημά του: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
Λοιπόν, ευχαριστώ για αυτό!
συμπέρασμα
Αυτό που γίνεται προφανές είναι ότι υπάρχει πολλή συζήτηση το OpenGL. Αλλά δεν λέει μας Οτιδήποτε. Πού είναι η επικοινωνία;
Το μόνο πράγμα που μας λέει το OpenGL σε αυτό το παράδειγμα είναι όταν τελειώσει . Κάθε λειτουργία θα διαρκέσει ορισμένο χρόνο. Κάποια λειτουργία διαρκεί απίστευτα πολύ, άλλες είναι εξαιρετικά γρήγορες.
Αποστολή κορυφής στην GPU θα είναι τόσο γρήγορη, δεν θα ξέρω καν πώς να το εκφράσω Η αποστολή χιλιάδων κορυφών από την CPU στην GPU, κάθε μεμονωμένο πλαίσιο, είναι, πιθανότατα, κανένα ζήτημα.
Εκκαθάριση της οθόνης μπορεί να πάρει ένα χιλιοστό του δευτερολέπτου ή χειρότερο (λάβετε υπόψη ότι συνήθως έχετε περίπου 16 χιλιοστά του δευτερολέπτου χρόνου για να σχεδιάσετε κάθε πλαίσιο), ανάλογα με το πόσο μεγάλο είναι το σημείο προβολής σας. Για να το καθαρίσετε, το OpenGL πρέπει να σχεδιάσει κάθε εικονοστοιχείο στο χρώμα στο οποίο θέλετε να διαγράψετε, που θα μπορούσε να είναι εκατομμύρια pixel.
Εκτός από αυτό, μπορούμε να ρωτήσουμε το OpenGL μόνο για τις δυνατότητες του προσαρμογέα γραφικών μας (μέγιστη ανάλυση, μέγιστο anti-aliasing, μέγιστο βάθος χρώματος,…).
Αλλά μπορούμε επίσης να γεμίσουμε μια υφή με pixel που το καθένα έχει ένα συγκεκριμένο χρώμα. Κάθε εικονοστοιχείο διατηρεί έτσι μια τιμή και η υφή είναι ένα τεράστιο «αρχείο» γεμάτο με δεδομένα. Μπορούμε να το φορτώσουμε στην κάρτα γραφικών (δημιουργώντας ένα buffer υφής) και στη συνέχεια να φορτώσουμε ένα shader , πείτε στον shader να χρησιμοποιήσει την υφή μας ως είσοδο και να εκτελέσετε μερικούς εξαιρετικά βαρύς υπολογισμούς στο "αρχείο" μας.
Στη συνέχεια, μπορούμε να «αποδώσουμε» το αποτέλεσμα του υπολογισμού μας (με τη μορφή νέων χρωμάτων) σε μια νέα υφή.
Έτσι μπορείτε να κάνετε τη GPU να λειτουργεί για εσάς με άλλους τρόπους. Υποθέτω ότι το CUDA έχει παρόμοια απόδοση, αλλά δεν είχα ποτέ την ευκαιρία να συνεργαστώ με αυτό.
Στην πραγματικότητα αγγίξαμε ελαφρώς ολόκληρο το θέμα. Ο τρισδιάστατος προγραμματισμός γραφικών είναι μια κόλαση ενός θηρίου.
Έχετε κάτι να προσθέσετε στην εξήγηση; Ακούστε στα σχόλια. Θέλετε να διαβάσετε περισσότερες απαντήσεις από άλλους χρήστες τεχνολογίας Stack Exchange; Δείτε ολόκληρο το νήμα συζήτησης εδώ .