Table of Contents
Θεμελιώσεις: Αντιπροσωπεύοντας τον Τριψήφιο Χώρο
Πριν από ένα μόνο εικονοστοιχείο είναι σχεδιασμένο, ένας 3D κινητήρας πρέπει να έχει μια μαθηματική γλώσσα για να περιγράψει αντικείμενα στο χώρο. Στον πυρήνα είναι vectors (τρεις συστατικές τουπλ που αντιπροσωπεύουν θέση, κατεύθυνση, ή χρώμα) και matrices[[LFT:3]] (4×4 συστοιχίες που κωδικοποιούν μετασχηματισμούς). Σε C, αυτές ορίζονται συνήθως ως απλές δομές:
- για σημεία και διανύσματα.
- για τις μήτρες μετατροπής που αποθηκεύονται με κύρια σειρά στηλών.
Κάθε αντικείμενο αποτελείται από τρίγωνα. Ένα τρίγωνο ορίζεται από τρεις κορυφές, το καθένα με μια θέση, και προαιρετικά ένα κανονικό και χρώμα. Αποθήκευση αυτών ως συνεχόμενες συστοιχίες (π.χ., για έναν κύβο) βελτιώνει την απόδοση cache ⁇ ένα κρίσιμο θέμα όταν επεξεργάζεται αργότερα χιλιάδες πρόσωπα ανά πλαίσιο.
Ο αγωγός γραφικών: Από τις Vertices στα εικονοστοιχεία
Ένας αγωγός γραφικών είναι μια ακολουθία σταδίων που μετατρέπει τα δεδομένα τρισδιάστατης σκηνής σε μια 2D εικόνα. Σε μια βασική μηχανή με λογισμικό, υλοποιείτε χειροκίνητα κάθε στάδιο. Οι κύριες φάσεις είναι:
- Επεξεργασία Vertex ⁇ εφαρμογή μοντέλου, προβολής και προβολής μετασχηματίζεται.
- ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇ ⁇
- Σκίαση ⁇ υπολογιστικό το χρώμα κάθε θραύσματος με βάση το φωτισμό και το υλικό.
- Συγχώνευση εξόδου ⁇ ανάμειξη θραυσμάτων με τον ρυθμιστή πλαισίου, συμπεριλαμβανομένης της δοκιμής βάθους.
Οι επιταχυνόμενοι με υλικό κινητήρες (με χρήση OpenGL, Vulkan, ή DirectX) εκτελούν τα περισσότερα από αυτά τα βήματα στο GPU, αλλά η κατανόηση της διαδρομής του λογισμικού σας δίνει βαθιά εικόνα για το πώς λειτουργεί το GPU κάτω από την κουκούλα.
Επεξεργασία και μετασχηματισμοί Vertex
Κάθε κορυφή ξεκινά από χώρο μοντέλου (τοπικές συντεταγμένες σε σχέση με το αντικείμενο). Για να το τοποθετήσετε στον κόσμο, εφαρμόζετε μήτρα μοντέλου που κωδικοποιεί τη μετάφραση, την περιστροφή και την κλιμάκωση. Στη συνέχεια, ο μήτρα προβολής μετατρέπει τις παγκόσμιες συντεταγμένες σε συντεταγμένες κάμερας (θέση προβολής). Τέλος, η μήτρα προβολής[ χάρτης βλέπει το χώρο σε ένα ομαλοποιημένο σύστημα συντεταγμένων () κενό clip] όπου η διατομή προοπτική και η χαρτογράφηση προβολών του λιμένα παράγουν συντεταγμένες οθόνης.
Σε C, οι λειτουργίες μετασχηματισμού μοιάζουν με:
- ⁇ επιστρέφει μια μήτρα ταυτότητας.
- ⁇ κατασκευάζει μια μήτρα μετάφρασης.
- ⁇ περιστροφή γύρω από τον άξονα Χ.
- ⁇ πολλαπλασιάζει μια μήτρα 4×4 με ένα διανύσμα 4 στοιχείων (ομογενείς συντεταγμένες).
Ο vertex shader ισοδύναμος στο λογισμικό επαναλαμβάνει σε όλες τις κορυφές, πολλαπλασιάζεται το καθένα από το συνδυασμένο [[LFT:7] μήτρα, και αποθηκεύει το αποτέλεσμα σε μια μετασχηματισμένη ενδιάμεση μνήμη vertex.
Προβολή: Προοπτικές έναντι Ορθογραφικής
Η προβολή ελέγχει πώς το βάθος αναπαρίσταται στην οθόνη. Προοπτική προβολή[[LPT:1]] κάνει τα μακρινά αντικείμενα να εμφανίζονται μικρότερα, δημιουργώντας ρεαλισμό. Η μήτρα του είναι χτισμένη από το οπτικό πεδίο, την αναλογία διαστάσεων, κοντά και μακριά επίπεδα κοπής. Η κλασική φόρμουλα περιλαμβάνει διαίρεση των στοιχείων x και y με z (μετά τον πολλαπλασιασμό μήτρας).
- ⁇ επιστρέφει ένα πρότυπο πίνακα προοπτικής.
Η ορθογραφική προβολή διατηρεί παράλληλες γραμμές και είναι απλούστερη, χρησιμοποιείται για εργαλεία UI ή CAD.
Ραστεροποίηση: Γεμίζοντας Τρίγωνα
Μετά την προβολή, έχετε 2D συντεταγμένες οθόνης (όπως θέσεις εικονοστοιχείων) και μια τιμή βάθους (z). Η δρομοποίηση σπάει κάθε τρίγωνο σε θραύσματα που καλύπτουν ακέραιες συντεταγμένες εικονοστοιχείων. Ο κλασικός αλγόριθμος είναι μετατροπή σάρωσης:
- Ταξινόμηση των τριών κορυφών του τριγώνου με y-συντονισμό.
- Περπατήστε κάτω από τις αριστερές και τις δεξιές άκρες, υπολογιστικά όρια x για κάθε γραμμή σάρωσης.
- Για κάθε εικονοστοιχείο στην οριζόντια κλίμακα, υπολογίστε το βάθος του θραύσματος παρεμβάλλοντας σε όλο το τρίγωνο.
- Εκτελέστε βαθυστόχαστη δοκιμή: συγκρίνετε το z του θραύσματος με την τιμή που ήδη υπάρχει στον ρυθμιστή βάθους. Αν είναι πιο κοντά, ενημερώστε τον ρυθμιστή βάθους και υπολογίστε το χρώμα του θραύσματος.
Η εφαρμογή του αλγόριθμου edge-walking αποτελεσματικά σε C απαιτεί σφιχτούς βρόχους και προσεκτική χρήση της αριθμητικής σταθερού σημείου για να αποφευχθεί το πλωτό σημείο πάνω από το κεφάλι. Πολλοί hobiist κινητήρες ξεκινούν με μια προσέγγιση ωμής δύναμης (ελέγχω κάθε pixel στο πλαίσιο που οριοθετεί) και αργότερα βελτιστοποιούν με εξισώσεις άκρων.
Σκίαση και Φωτισμός
Ένας απλός κινητήρας με επίπεδη όψη χρησιμοποιεί ένα ενιαίο χρώμα ανά τρίγωνο, υπολογισμένος από το πρόσωπο κανονικά και μια ενιαία φωτεινή πηγή. Το Λαμπερτιανικό μοντέλο δίνει διάχυτη ένταση: . Στο C, υπολογίζετε το φυσιολογικό ως το προϊόν σταυροειδούς των δύο τριγώνων ακμών (μετά τη μετατροπή κορυφών σε παγκόσμιο χώρο), στη συνέχεια πολλαπλασιάστε την ένταση φωτός με το βασικό χρώμα του τριγώνου.
Για να προσθέσετε βάθος, εφαρμόστε Σκίαση Gouraud[] (ομαλό vertex, παρεμβαλλόμενο σε θραύσματα) ή Σκίαση Phong (ανά ρόδινο pixel).Το τελευταίο απαιτεί παρεμβολή των παγκόσμιων θέσεων και των κανονικών, κατόπιν υπολογιστικό φωτισμό ανά θραύσμα ⁇ πιο ακριβά αλλά δραματικά καλύτερα αποτελέσματα.
Κατασκευή του κινητήρα σε Γ: Πρακτικά βήματα
Ο στόχος είναι να αποδώσουμε έναν περιστρεφόμενο κύβο με ατμοσφαιρικό και διάχυτο φωτισμό σε ένα παράθυρο εικονοστοιχείων 640×480.
Βήμα 1 ⁇ ⁇ ενός ρυθμιστή εικονοστοιχείων
Καθορίστε μια μνήμη ρυθμιστή για το πλαίσιο και το βάθος: και . Καθαρίστε το πλαίσιο του ρυθμιστή σε μαύρο και το βάθος ρυθμιστικό σε 1,0 (φάρδος) κάθε πλαίσιο.
Βήμα 2 ⁇ Καθορίστε τα δεδομένα σκηνής
Για έναν κύβο, έξι πρόσωπα (12 τρίγωνα) απαιτούν 12×3 = 36 κορυφές. Αποθήκευση τους σε μια σειρά από δομές με θέση (3 πλωτήρες) και χρώμα (3 πλωτήρες για RGB). Προκαθορισμός των 8 μοναδικών γωνιών κύβου και έξι χρώματα προσώπου. Χρησιμοποιήστε ένα δείκτη ρυθμιστή για να αποφύγετε την αναπαραγωγή κορυφές.
Βήμα 3 ⁇ Σωλήνας μετασχηματισμού
Κάθε πλαίσιο, υπολογίστε τη μήτρα μοντέλου από μια γωνία (π.χ., περιστροφήY(χρόνος)), τη μήτρα προβολής από μια σταθερή κάμερα που κοιτάζει την προέλευση, και τη μήτρα προβολής. Συνδυάστε τα σε μια ενιαία μήτρα MVP: . Μεταμορφώστε κάθε κορυφή πολλαπλασιάζοντας με [[LFT:13]]]. Στη συνέχεια εκτελέστε το διαχωρισμό προοπτικής (διάκριση x,y,z με w) για να πάρετε τις συντεταγμένες της συσκευής ( ⁇ 1 έως +1). Χάρτης σε συντεταγμένες οθόνης: , (αναστραμμένο).
Βήμα 4 ⁇ Ραστερίστε και Σκίαση
Για κάθε τρίγωνο, χρησιμοποιήστε τη μέθοδο σάρωσης. Ενώ περπατάτε pixels, παρεμβάλετε το βάθος και επίσης παρεμβάλτε ένα Per-vertex χαρακτηριστικό όπως η θέση του κόσμου-χώρου (για Phong) ή η κορυφή κανονική (για Gouraud). Εφαρμόστε την Lambertian διάχυτη εξίσωση. Γράψτε το τελικό χρώμα στο framebuffer αν η δοκιμή βάθους περάσει.
Βήμα 5 ⁇ Εμφάνιση
Χρησιμοποιήστε SDL (Απλή DirectMedia Layer) ή μια παρόμοια βιβλιοθήκη για να δημιουργήσετε ένα παράθυρο και να blit το framebuffer. Για παράδειγμα, με SDL2: , , ] σε ], τότε ] και κάθε πλαίσιο.
Αυτή η διαδρομή λογισμικού τρέχει στην CPU, έτσι η απόδοση περιορίζεται σε μερικές χιλιάδες τρίγωνα ανά πλαίσιο. Μόλις είναι άνετο, μπορείτε να αντικαταστήσετε το στρώμα rasterization με OpenGL, εκφορτώνοντας το βαρύ έργο στο GPU, διατηρώντας παράλληλα τη λογική μεταμόρφωσης και σκηνής σας σε C.
Βελτιστοποίηση της Μηχανής σας
Μια βασική μηχανή είναι αργή. Αρκετές βελτιστοποιήσεις είναι απαραίτητες για την απόδοση σε πραγματικό χρόνο:
- Πλάγιος-πρόσωπος που σφάζει: Παράκαμψη τριγώνων των οποίων τα φυσιολογικά δείχνουν μακριά από την κάμερα. Υπολογίστε την υπογεγραμμένη περιοχή του προβαλλόμενου τριγώνου (σε 2D) ή ελέγξτε το προϊόν τελείας του προσώπου κανονικά με την κατεύθυνση της προβολής.
- Φρούστομ έσφαγμα: Δοκιμάστε το πλαίσιο σύνδεσης ενός αντικειμένου κατά των έξι επιπέδων της θέας φρούστουμ. Αν εντελώς έξω, παραλείψτε ολόκληρο το αντικείμενο.
- Αριθμική Fixed-point:[[LFT:1]] Αντικατάσταση λειτουργιών κινητής υποδιαστολής με ακέραια μαθηματικά σε σφιχτούς βρόχους rasterization. Πολλοί κατασκευαστές μηχανών χρησιμοποιούν 16.16 σταθερό σημείο για παρεμβολή σκαναλιών.
- Προμετασχηματισμένη λανθάνουσα μνήμη: Αποφύγετε να μετασχηματίσετε την ίδια κορυφή πολλές φορές μεταμορφώνοντας όλες τις κορυφές ενός πλέγματος μία φορά, στη συνέχεια χρησιμοποιώντας δείκτες.
- Ο ρυθμιστής πλαισίου με μπλοκαρισμένα γράφει: Γράψτε εικονοστοιχεία στη σειρά μνήμης (αριστερά προς δεξιά, πάνω προς τα κάτω) για να μεγιστοποιήσετε τα χτυπήματα cache.
Αυτές οι τεχνικές μπορούν να ωθήσουν έναν αποθέτη λογισμικού από 3 ⁇ 5 fps σε 60 fps για σκηνές μέτριας πολυπλοκότητας (π.χ., μερικές εκατοντάδες τρίγωνα).
Επέκταση της μηχανής
Μόλις υπάρχει ένα στερεό θεμέλιο, μπορείτε να προσθέσετε χαρακτηριστικά σταδιακά:
- Χαρτογράφηση κειμένου: Αποθήκευση 2D εικόνων και παρεμβολή συντεταγμένων UV σε τρίγωνα. Εφαρμογή διγραμμικού φιλτραρίσματος για ομαλά αποτελέσματα.
- Προηγμένη σκίαση: Προσθέστε specular highlights (Blinn-Phong), ambient αποφρακτική, ή ακόμα και σκιώδεις χάρτες.
- Διαχείριση σκηνών: Χρησιμοποιήστε ένα δέντρο οκτρίου ή BSP για να καθορίσετε γρήγορα ποια αντικείμενα είναι ορατά.
- Αλληλεπιδράσεις χρήστη: Χειρισμός πληκτρολογίου και εισόδου ποντικιού για να περιστραφούν στην κάμερα ή να διαλέξουν αντικείμενα.
- Αφαιρέσεις πιπελίνων: Σχεδιάστε ένα σύστημα σκιαστών: ορίστε τις λειτουργίες vertex και θραύσμα ως δείκτες συνάρτησης, επιτρέποντας την ευέλικτη απόδοση χωρίς επαναπλήρωση.
Πόροι και περαιτέρω ανάγνωση
Για να εμβαθύνετε την κατανόησή σας, εξερευνήστε τα κλασικά κείμενα και τα online tutorials που ενέπνευσε αυτή τη μηχανή:
- Scracsapixel ⁇ Σε βάθος εξηγήσεις για τον εντοπισμό, την ρατσιστική και μαθηματική ανάλυση των ακτίνων.
- LearnOpenGL ⁇ Σύγχρονα μαθήματα OpenGL; ξεκινήστε με το κεφάλαιο “Hello Triangle”.
- Γουικιπεδιά: 3D Προβολή[ ⁇ Τα τυπικά μαθηματικά πίσω από την προοπτική και τις ορθογραφικές μήτρες.
Η κατασκευή ενός 3D κινητήρα σε C είναι μια τελετουργία διέλευσης για προγραμματιστές γραφικών. Σας διδάσκει όχι μόνο πώς να γράψετε αποτελεσματικό κώδικα, αλλά και πώς να σκεφτείτε σε τρεις διαστάσεις και να συνθέσετε τα κρίσιμα συστήματα απόδοσης. Ξεκινήστε με ένα ενιαίο περιστρεφόμενο κύβο, στη συνέχεια προσθέστε περισσότερα τρίγωνα, υφές, και τέλος να το παραδώσετε στο GPU. Το ταξίδι από το ακατέργαστο C σε ένα πλήρως λειτουργικό κινητήρα αποκαλύπτει τη μαγεία πίσω από κάθε pixel στην οθόνη.