Merge pull request #393 from nikos-maximus/master

Greek translation, Chapters 0 - 4
pull/395/head
Patricio Gonzalez Vivo 1 year ago committed by GitHub
commit 99c66e4cd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,47 @@
# Εισαγωγή
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
Οι παραπάνω εικόνες φτιάχτηκαν με διαφορετικούς τρόπους. Η πρώτη φτιάχτηκε από το χέρι του Van Gogh, προσθέτοντας στρώματα χρώματος, το ένα πάνω στο άλλο. Του χρειάστηκαν ώρες. Η δεύτερη δημιουργήθηκε σε δευτερόλεπτα από τον συνδυασμό τεσσάρων πινάκων από pixels: έναν για το κυανό (cyan), έναν για το πορφυρό (magenta), έναν για το κίτρινο και έναν για το μαύρο. Η βασική διαφορά είναι πως η δεύτερη εικόνα δημιουργήθηκε με μη-σειριακό τρόπο (δηλαδή, όχι ένα-ένα βήμα, αλλά ολόκληρη την ίδια στιγμή)
Αυτό το βιβλίο πραγματεύεται την επαναστατική υπολογιστική τεχνική, *fragment shaders* (φωτοσκιαστές τεμαχίων), η οποία ανεβάζει τις ψηφιακά παραγόμενες εικόνες σε επόμενο επίπεδο. Σκεφτείτε το σαν το αντίστοιχο του πιεστηρίου του Γουτεμβέργιου για τα graphics.
![Τυπογραφείο του Γουτεμβέργιου](gutenpress.jpg)
Οι fragment shaders μας δίνουν πλήρη έλεγχο πάνω στα pixels που ζωγραφίζονται στην οθόνη, σε υπερυψηλές ταχύτητες. Γι' αυτό το λόγο χρησιμοποιούνται σε όλων των ειδών τις περιπτώσεις, από φίλτρα βίντεο σε κινητά τηλέφωνα μέχρι απίστευτα 3D βιντεοπαιχνίδια.
![Journey απο That Game Company](journey.jpg)
Στα επόμενα κεφάλαια θα ανακαλύψετε πόσο απίστευτα γρήγορη και ισχυρή είναι αυτή η τεχνική και πως να τη χρησιμοποιήσετε στην επαγγελματική και προσωπική σας δουλειά.
## Σε ποιούς απευθύνεται αυτό το βιβλίο;
Αυτό το βιβλίο γράφτηκε για δημιουργικούς coders, game developers και μηχανικούς με εμπειρία στο coding, βασικές γνώσεις γραμμικής άλγεβρας και τριγωνομετρίας, που θέλουν να ανεβάσουν τη δουλειά τους σε ένα συναρπαστικό νέο επίπεδο ποιότητας γραφικών. (Αν θέλετε να μάθετε πως να γράφετε κώδικα, προτείνω ιδιαίτερα να ξεκινήσετε με την [Processing](https://processing.org/) και να επιστρέψετε όταν έχετε αποκτήσει μια σχετική άνεση με αυτή.)
Αυτό το βιβλίο θα σας δείξει πως να χρησιμοποιείτε και να ενσωματώνετε shaders στα δικά σας έργα, βελτιώνοντας την απόδοση και την οπτική τους ποιότητα. Επειδή οι shaders που είναι γραμμένοι σε GLSL (η γλώσσα για περιγραφή shaders που ορίζει η OpenGL) μεταγλωττίζονται και τρέχουν σε μια πληθώρα από περιβάλλοντα, θα μπορείτε να εφαρμόσετε ο,τι μάθετε εδώ σε οποιοδήποτε περιβάλλον χρησιμοποιεί OpenGL, OpenGL ES ή WebGL. Με άλλα λόγια, θα μπορείτε να εφαρμόσετε και να χρησιμοποιήσετε τις γνώσεις σας με αρχεία [Processing](https://processing.org/), εφαρμογές [openFrameworks](http://openframeworks.cc/), διαδραστικά περιβάλλοντα [Cinder](http://libcinder.org/), ιστοσελίδες [Three.js](http://threejs.org/) ή παιχνίδια σε iOS/Android.
## Τι καλύπτει αυτό το βιβλίο;
Αυτό το βιβλίο εστιάζει στη χρήση pixel shaders σε GLSL. Πρώτα θα ορίσουμε τι είναι οι shaders, στη συνέχεια θα μάθουμε πως να φτιάχνουμε διαδικάστικά (procedural) σχήματα, μοτίβα, υφές (textures) και animations (κίνηση) με αυτούς. Θα μάθετε τις αρχές της γλώσσας περιγραφής shaders και θα την χρησιμοποιήσετε σε πιο χρηστικά σενάρια όπως: επεξεργασία εικόνας (χειρισμούς εικόνας, συγκερασμούς (convolution) πινάκων, θόλωμα (blur), φίλτρα χρώματος, πίνακες αναζήτησης (lookup tables) και άλλα εφέ) και προσομοιώσεις (Conway's game of life, Gray-Scott's reaction-diffusion, κυματισμούς νερού, εφέ νερομπογιάς, στοιχεία Voronoi, κτλ.). Προς το τέλος του βιβλίου θα δούμε ένα σύνολο απο προχωρημένες τεχνικές βασισμένες σε Ray Marching (βηματισμό ακτίνων).
*Υπάρχουν διαδραστικά παραδείγματα με τα οποία μπορείτε να παίξετε σε κάθε κεφάλαιο* Όταν αλλάζετε τον κώδικα, θα μπορείτε να βλέπετε τις αλλαγές άμεσα. Οι έννοιες μπορεί να είναι αφηρημένες και περίπλοκες, οπότε τα διαδραστικά παραδείγματα είναι απαραίτητα ώστε να σας βοηθήσουν να μάθετε το υλικό. Όσο πιο σύντομα βάλετε σε "κίνηση" τις έννοιες, τόσο ευκολότερη θα γίνει η διαδικασία της αφομοίωσης.
Τι δεν καλύπτει αυτό το βιβλίο:
* Αυτό *δεν είναι* ενα βιβλίο για την OpenGL ή τη webGL. Η OpenGL/webGL είναι ένα αντικέιμενο μεγαλύτερο από την GLSL και τους fragment shaders. Για να μάθετε περισσότερα σχετικά με OpenGL/webGL, προτείνω να ρίξετε μια ματιά σε: [OpenGL Introduction](https://open.gl/introduction), [8η έκδοση του βιβλίου OpenGL Programming Guide](http://www.amazon.com/OpenGL-Programming-Guide-Official-Learning/dp/0321773039/ref=sr_1_1?s=books&ie=UTF8&qid=1424007417&sr=1-1&keywords=open+gl+programming+guide) (γνωστό επίσης ως "το κόκκινο βιβλίο") ή [WebGL: Up and Running](http://www.amazon.com/WebGL-Up-Running-Tony-Parisi/dp/144932357X/ref=sr_1_4?s=books&ie=UTF8&qid=1425147254&sr=1-4&keywords=webgl)
* Αυτό *δεν είναι* ένα βιβλίο μαθηματικών. Αν και θα καλύψουμε ένα σύνολο απο αλγορίθμους και τεχνικές που βασίζονται στην κατανόηση άλγεβρας και τριγωνομετρίας, δε θα τις εξηγήσουμε με λεπτομέρεια. Για απορίες σχετικές με τα μαθηματικά προτείνω να έχετε πρόχειρο ένα από τα ακόλουθα βιβλία: [3η Έκδοση του Mathematics for 3D Game Programming and computer Graphics](http://www.amazon.com/Mathematics-Programming-Computer-Graphics-Third/dp/1435458869/ref=sr_1_1?ie=UTF8&qid=1424007839&sr=8-1&keywords=mathematics+for+games) ή [2η Έκδοση του Essential Mathematics for Games and Interactive Applications](http://www.amazon.com/Essential-Mathematics-Games-Interactive-Applications/dp/0123742978/ref=sr_1_1?ie=UTF8&qid=1424007889&sr=8-1&keywords=essentials+mathematics+for+developers).
## Τι χρειάζεται για να ξεκινήσετε;
Όχι πολλά! Αν έχετε ένα σύγχρονο browser που υποστηρίζει WebGL (όπως οι Chrome, Firefox, Safari) και μια σύνδεση στο internet, πατήστε "Next" (επόμενο κεφάλαιο) στο τέλος αυτής της σελίδας για να ξεκινήσετε.
Εναλλακτικά, ανάλογα με τι έχετε ή τι χρειάζεστε από αυτό το βιβλίο μπορείτε:
- [Να φτιάξετε μια off-line εκδοχή του βιβλίου](https://thebookofshaders.com/appendix/00/)
- [Να τρέξετε τα παραδείγματα σε ενα Raspberry Pi χωρίς browser](https://thebookofshaders.com/appendix/01/)
- [να φτιάξετε ενα PDF του βιβλίου για εκτύπωση](https://thebookofshaders.com/appendix/02/)
- Συμβουλευτείτε το [αποθετήριο GitHub (repository)](https://github.com/patriciogonzalezvivo/thebookofshaders) του βιβλίου για επίλυση προβλημάτων και για να μοιραστείτε κώδικα.

@ -0,0 +1 @@
# Εισαγωγή

@ -0,0 +1,48 @@
# Ξεκινώντας
## Τι είναι ένας fragment shader;
Στο προηγούμενο κεφάλαιο περιγράψαμε τους shaders σαν το αντίστοιχο του πιεστηρίου του Γουτεμβέργιου για τα γραφικά. Γιατί; Και πιό σημαντικό: τι είναι ενας shader?
![Από έναν-ένα χαρακτήρα/γράμμα, Δεξιά: William Blades (1891). Στο μια-μια Σελίδα, Αριστερά: Rolt-Wheeler (1920).](print.png)
Αν έχετε ήδη εμπειρία στο να δημιουργείτε ζωγραφιές με υπολογιστές, ξέρετε πως μέρος της διαδικασίας είναι να ζωγραφίσετε έναν κύκλο, μετά ένα τετράγωνο, μια γραμμή, μερικά τρίγωνα μέχρι να συνθέσετε την εικόνα που θέλετε. Αυτή η διαδικασία είναι πολύ παρόμοια με το να γράφετε ένα γράμμα ή ένα βιβλίο με το χέρι - είναι ένα σύνολο από οδηγίες που πραγματοποιούν μια εργασία μετά την άλλη.
Οι shaders είναι επίσης ένα σύνολο απο οδηγίες, αλλά οι οδηγίες εκτελούνται όλες ταυτόχρονα για κάθε ένα pixel στην οθόνη. Αυτό σημαίνει πως ο κώδικας που γράφετε πρέπει να συμπεριφερθεί διαφορετικά ανάλογα με τη θέση του pixel στην οθόνη. Ανάλογα με ένα πιεστήριο τυπογραφείου, το πρόγραμμα θα συμπεριφερθεί σα μια συνάρτηση που παίρνει στην είσοδο μια θέση και επιστρέφει στην έξοδο ένα χρώμα, και που αφού μεταγλωττιστεί θα εκτελεστεί εκπληκτικά γρήγορα.
![Κινητοί Κινέζικοι χαρακτήρες](typepress.jpg)
## Γιατί είναι γρήγοροι οι shaders;
Για να το απαντήσουμε αυτό, σας παρουσιάζω το θαύμα της *παράλληλης επεξεργασίας*.
Φανταστείτε την CPU (επεξεργαστή) του υπολογιστή σας σαν έναν μεγάλο βιομηχανικό σωλήνα, και κάθε εργασία (task) σαν κάτι που περνάει μέσα απο αυτόν - σαν εργοστασιακή γραμμή παραγωγής. Κάποιες εργασίες είναι μεγαλύτερες από άλλες, που σημαίνει πως απαιτούν περισσότερο χρόνο και ενέργεια. Λέμε πως απαιτούν μεγαλύτερη υπολογιστική ισχύ. Λόγω της αρχιτεκτονικής των υπολογιστών οι εργασίες πρέπει να τρέχουν σε σειρά: κάθε εργασία πρέπει να τελειώνει μία τη φορά. Οι σύγχρονοι υπολογιστές συνήθως έχουν ομάδες τεσσάρων επεξεργαστών που λειτουργούν όπως αυτοί οι σωλήνες, ολοκληρώνοντας εργασίες τη μια μετά την άλλη ώστε τα πράγματα να συνεχίσουν να λειτουργούν ομαλά. Κάθε σωλήνας είναι επίσης γνωστός και σαν *thread (νήμα)*.
![CPU (επεξεργαστής)](00.jpeg)
Τα video games και άλλες εφαργμογές με γραφικά απαιτούν πολύ περισσότερη επεξεργαστική ισχύ από άλλα προγράμματα. Εξ' αιτίας του οπτικού τους περιεχομένου χρειάζεται να πραγματοποιούν πολύ μεγάλο αριθμό από λειτουργίες pixel προς pixel. Κάθε ένα pixel στην οθόνη χρειάζεται να υπολογιστεί, και σε 3D παιχνίδια, η γεωμετρία και η προοπτική πρέπει επίσης να υπολογιστούν.
Ας πάμε πίσω στην αναλογία με τους σωλήνες και τις εργασίες. Κάθε pixel στην οθόνη αντιπροσωπέυει μια μικρή εργασία. Από μόνη της, μια εργασία για ένα pixel δεν είναι τίποτα σπουδαίο για την CPU, αλλά (και εδώ είναι το πρόβλημα), η μικροσκοπική εργασία πρέπει να γίνει για κάθε pixel στην οθόνη! Αυτό σημαίνει πως σε μια παλιά οθόνη (με ανάλυση) 800x600, πρέπει σε κάθε frame (καρέ) να επεξεργαστούμε 480.000 pixels που σημαίνει 14.400.000 υπολογισμούς το δευτερόλεπτο! Ναι! Αυτό είναι ένα πρόβλημα αρκετά μεγάλο ώστε να καταβάλλει έναν επεξεργαστή. Σε μια σύγχρονη οθόνη retina 2880x1800 που ανανεώνεται στα 60 frames το δευτερόλεπτο, αυτός ο υπολογισμός καταλήγει σε 311.040.000 υπολογισμούς το δευτερόλεπτο. Πως λύνουν αυτό το πρόβλημα οι μηχανικοί των γραφικών?
![](03.jpeg)
Εδώ είναι που η παράλληλη επεξεργασία δίνει μια καλή λύση. Αντί να έχουμε λίγους μεγάλους και δυνατούς επεξεργαστές, η *σωλήνες*, είναι αποδοτικότερο να έχουμε πολλούς μικροσκοπικούς επεξεργαστές που λειτουργούν παράλληλα και ταυτόχρονα. Αυτό είναι μια Graphics Processing Unit (GPU) - (μονάδα επεξεργασίας γραφικών)
![GPU](04.jpeg)
Φανταστείτε τους μικρούς επεξεργαστές σαν ένα τραπέζει από σωλήνες, και τα δεδομένα για κάθε pixel σαν ένα μπαλάκι του πινγκ πονγκ. 14.400.000 μπάλες του πινγκ πονγκ το δευτερόλεπτο μπορούν να φράξουν λίγο - πολύ οποιοδήποτε σωλήνα. Αλλά ένα τραπέζι από 800x600 μικρούς σωλήνες από τους οποίους περνάνε 30 κύματα των 480.000 pixels το δευτερόλεπτο είναι κάτι που μπορούμε να διαχειριστούμε με άνεση. Αυτό δουλεύει με τον ίδιο τρόπο σε υψηλότερες αναλύσεις - όσο περισσότερο παράλληλο hardware (υλικό) διαθέτουμε, τόσο μεγαλύτερη η ροή που μπορεί να διαχειριστεί.
Άλλη μια "σούπερ δύναμη" των GPU είναι πως επιταχύνουν μέσω hardware ειδικές μαθηματικές συναρτήσεις, ώστε περίπλοκες μαθηματικές πράξεις επιλύονται κατευθείαν στο microchip, αντί για το software (λογισμικό). Αυτό σημαίνει εξαιρετικά γρήγορες πράξεις τριγωνομετρίας και άλγεβρας πινάκων - σε ταχύτητες που περιορίζονται μόνο από την ταχύτητα του ηλεκτρισμού.
## Τι είναι η GLSL;
GLSL σημαίνει OpenGL Shading Language (γλώσσα περιγραφής shaders της OpenGL), η οποία είναι το συγκεκριμένο πρότυπο για προγράμματα shaders που θα δείτε στα επόμενα κεφάλαια. Υπάρχουν και άλλοι τύποι shaders ανάλογα με το hardware και το Λειτουργικό Σύστημα. Εδώ θα δουλέψουμε με το πρότυπο OpenGL όπως το ορίζει το [Khronos Group](https://www.khronos.org/opengl/). Κάποια γνώση της ιστορίας της OpenGL μπορεί να φανέι χρήσιμη στο να καταλάβουμε αρκετές από τις περίεργες συμβάσεις της, και γι' αυτό προτείνω να ρίξετε μια ματιά στο: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
## Γιατί έχουν οι Shaders τη φήμη πως είναι δύσκολοι;
Όπως είπε και ο Θείος Ben "η μεγάλη δύναμη απαιτεί μεγάλη υπευθυνότητα", και η παράλληλη επεξεργασία ακολουθεί αυτό τον κανόνα. Ο ισχυρός αρχιτεκτονικός σχεδιασμός της GPU φέρνει τους δικούς του περιορισμούς και κανόνες.
Προκειμένου να λειτουργεί παράλληλα, κάθε σωλήνας - ή thread (νήμα) - πρέπει να είναι ανεξάρτητο από κάθε άλλο thread. Λέμε πως τα threads είναι *τυφλά* ως προς το τι κάνουν τα άλλα threads. Αυτός ο περιορισμός υπονοεί πως όλα τα δεδομένα κινούνται προς την ίδια κατεύθυνση. Κατά συνέπεια, είναι αδύνατο να δούμε το αποτέλεσμα ενός άλλου thread, να αλλάξουμε τα δεδομένα εισόδου, ή να οδηγήσουμε το αποτέλεσμα ενός thread σε ένα άλλο thread. Το να επιτρέψουμε επικοινωνία μεταξύ threads, βάζει σε κίνδυνο τη συνέπεια των δεδομένων.
Επίσης, η GPU κρατάει τον παράλληλο επεξεργαστή (τους σωλήνες) διαρκώς απασχολημένο. Μόλις αποδεσμευτούν, παίρνουν καινούριες πληροφορίες για επεξεργασία. Είναι αδύνατο για ένα thread να ξέρει τι έκανε μια στιγμή νωρίτερα. Θα μπορούσε να ζωγραφίζει ένα κουμπί για το UI (διεπαφή χρήστη) του λειτουργικού συστήματος, μετά να ζωγραφίζει ένα τμήμα του ουρανού για κάποιο παιχνίδι, μετά να δείχνει το κείμενο ενός email. Κάθε thread δεν είναι μόνο **τυφλό**, αλλά και **χωρίς μνήμη**. Εκτός από την αφαίρεση που απαιτείται για να γράψουμε (σε κώδικα) μια γενική συνάρτηση που αλλάζει το αποτέλεσμα ενός pixel τη φορά βάσει της θέσης του, οι περιορισμοί "τυφλότητας" και "έλλειψης μνήμης" (του thread) κάνουν τους λιγότερο έμπειρους προγραμματιστές να αποφεύγουν τους shaders.
Μην ανησυχείτε! Στα επόμενα κεφάλαια, θα μάθουμε βήμα - βήμα πως να πάμε από απλούς σε προχωρημένους υπολογισμούς με shaders. Αν διαβάζετε αυτό το κείμενο σε έναν σύγχρονο browser, θα μπορέσετε να παίξετε με τα διαδραστικά παραδείγματα. Ας μην καθυστερούμε άλλο τη διασκέδαση λοιπόν, πατήστε *Next >>* για να κάνουμε βουτιά κατ' ευθείαν στον κώδικα!

@ -0,0 +1,2 @@
# Ξεκινώντας
## Τί είναι ένας fragment shader (φωτοσκιαστής τεμαχίων);

@ -0,0 +1,53 @@
## Hello World
Συνήθως το παράδειγμα "Hello world!" είναι το πρώτο βήμα για να μάθει κανείς μια νέα γλώσσα. Είναι ένα απλό πρόγραμμα της μιας γραμμής που τυπώνει ένα ενθουσιώδες καλοσώρισμα και αναγέλλει τις δυνατότητες που μας περιμένουν.
Στη χώρα της GPU, ο σχεδιασμός χαρακτήρων είναι μια υπερβολικά περίπλοκη εργασία για πρώτο βήμα, οπότε θα προτιμήσουμε ένα φωτεινό φιλόξενο χρώμα για να διακυρήξουμε τον ενθουσιασμό μας!
<div class="codeAndCanvas" data="hello_world.frag"></div>
Αμ διαβάζετε αυτό το κείμενο σε browser, το προηγούμενο τμήμα κώδικα είναι διαδραστικό. Αυτό σημαίνει πως μπορείτε να κάνετε κλικ και να αλλάξετε όποιο μέρος του κώδικα θέλετε να εξερευνήσετε. Οι αλλαγές θα γίνουν άμεσα ορατές χάρη στην αρχιτεκτονική της GPU που μεταγλωττίζει (compiles) και αντικαθιστά τους shaders "στον αέρα". Κάντε μια δοκιμή να αλλάξετε τις τιμές στη γραμμή 8.
Αν και αυτές οι απλές γραμμές κώδικα δε δείχνουν τίποτα σπουδαίο, μπορούμε να εξάγουμε σημαντικές γνώσεις από αυτές:
1. Η γλώσσα των shaders έχει μια μοναδική συνάρτηση `main` που επιστρέφει ένα χρώμα στο τέλος, παρόμοια με τη C.
2. Το τελικό χρώμα του pixel ανατίθεται (γράφεται) στην δεσμευμένη (reserved) καθολική μεταβλητή `gl_FragColor`.
3. Αυτή η παρόμοια-με-C γλώσσα έχει ενσωματωμένες *μεταβλητές* (όπως η `gl_FragColor`), *συναρτήσεις* και *τύπους*. Σε αυτό το παράδειγμα συστηθήκαμε μόνο με το `vec4` που αντιπροσωπεύει ένα διάνυσμα 4 διαστάσεων και ακρίβειας τύπου μονής κινητής υποδιαστολής (float). Αργότερα θα δούμε και άλλους τύπους όπως `vec3` και `vec2` όπως και τους γνωστούς: `float`, `int` και `bool`.
4. Αν παρατηρήσουμε τον τύπο `vec4` μπορούμε να συμπεράνουμε οτι τα τέσσερα μέρη αντιστοιχούν στα κανάλια χρώματος RED, GREEN, BLUE και ALPHA. Επίσης μπορούμε να δούμε πως οι τιμές τους είναι *κανονικοποιημένες*, που σημαίνει πως το εύρος τους είναι από `0.0` ως `1.0`. Αργότερα θα δούμε πως η κανονικοποίηση των τιμών μας διευκολύνει στο να αντιστοιχίζουμε τιμές ανάμεσα σε μεταβλητές.
5. Άλλο ένα σημαντικό *χαρακτηριστικό σαν της C* που βλέπουμε σε αυτό το παράδειγμα είναι η ύπαρξη preprocessor macros (μακροεντολών προεπεξεργαστή). Οι macros είναι μέρος ενός βήματος προ-μεταγλώττισης. Με αυτές μπορούμε να ορίσουμε (`#define`) καθολικές μεταβλητές και να κάνουμε κάποιες βασικές επιλογές υπό συνθήκη (conditional operations - με `#ifdef` και `#endif`). Όλες οι μακροεντολές ξεκινάνε με ένα hashtag (`#`). Η προ-μεταγλώττιση συμβαίνει ακριβώς πριν τη μεταγλώττιση, και αντιγράφει όλες τις κλήσεις σε `#defines` και ελέγχει τις συνθήκες `#ifdef` (κάτι είναι ορισμένο) και `#ifndef` (κάτι δεν είναι ορισμένο). Στο "hello world!" παράδειγμά μας παραπάνω, προσθέσαμε μόνο τη γραμμή 2 (αν έχει οριστεί η `GL_ES`), το οποίο κυρίως συμβαίνει όταν ο κώδικας μεταγλωττίζεται σε φορητές συσκευές και browsers.
6. Οι τύποι κινητής υποδιαστολής είναι απαραίτητοι στους shaders, οπότε και το επίπεδο *ακρίβειας* είναι καίριο. Χαμηλότερη ακρίβεια σημαίνει γρηγορότερη απεικόνιση (rendering), αλλάμ με κόστος σε ποιότητα. Μπορείτε να είστε επιλεκτικοί και να προσδιορίσετε την ακρίβεια σε κάθε μεταβλητή που χρησιμοποιεί κινητή υποδιαστολή. Στη δεύτερη γραμμή (`precision mediump float;`) θέτουμε όλους τους floats σε μέση ακρίβεια. Μπορούμε επίσης να αποφασίσουμε να τους θέσουμε σε χαμηλή (`precision lowp float;`) ή υψηλή (`precision highp float;`).
7. Η τελευταία, και ίσως πιο σημαντική λεπτομέρεια είναι πως το πρότυπο της GLSL δεν εγγυάται πως όλες οι μεταβλητές μετατρέπονται αυτόματα. Τι σημαίνει αυτό; Οι κατασκευαστές έχουν διαφορετικές προσεγγίσεις στο να επιταχύνουν τις διεργασίες των καρτών γραφικών, αλλά είναι υποχρεωμένοι να εγγυηθούν κάποιες ελάχιστες προδιαγραφές. Η αυτόματη μετατροπή δεν είναι μια απο αυτές. Στο “hello world!” παράδειγμά μας, το `vec4` έχει ακρίβεια float (μονής κινητής υποδιαστολής), οπότε περιμένει να του αναθέσουμε `float` τιμές. Αν θέλετε να έχετε καλό και σταθερό κώδικα αντί να ξοδεύετε ώρες προσπαθώντας να διορθώσετε (debug) λευκές οθόνες, συνηθίστε να βάζετε την υποδιαστολή (`.`) στους floats σας. Κώδικας σαν κι αυτόν δε δουλεύει πάντα σωστα:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // ERROR
}
```
Τώρα που περιγράψαμε τα πιο απαραίτητα στοιχεία του "hello world!" προγράμματός μας, ώρα να κάνετε κλικ στο τμήμα κώδικα και να αρχίσετε να δοκιμάζετε όλα όσα μάθαμε. Θα διαπιστώσετε πως σε περίπτωση λαθών το πρόγραμμα δεν θα μεταγλωττιστεί, και θα δείξει μια λευκή οθόνη. Υπάρχουν μερικά πράγματα να δοκιμάσετε, για παράδειγμα:
* Δοκιμάστε να αντικαταστήσετε τους float με integers, η κάρτα γραφικών σας ίσως να μην ανεχτεί αυτή τη συμπεριφορά!
* Δοκιμάστε να βάλετε σε σχόλια τη γραμμή 8 και να μη δώσετε τιμή για το pixel στη συνάρτηση
* Δοκιμάστε να φτιάξετε μια ξεχωριστή συνάρτηση που επιστρέφει ένα συγκεκριμένο χρώμα και να την καλέσετε μέσα στη `main()`. Σα βοήθημα, αυτός είναι ο κώδικας μιας συνάρτησης που επιστρέφει κόκκινο:
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* Υπάρχουν διάφοροι τρόποι για να αρχικοποιήσετε τυπους `vec4`, δοκιμάστε να ανακαλύψετε και άλλους. Ο ακόλουθος είνα ένας από αυτούς:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
Αν και αυτό το παράδειγμα δεν είναι ιδιαίτερα ενδιαφέρον, είναι το πιο βασικό - αλλάζουμε όλα τα pixels μέσα στον καμβά (για την ακρίβεια στο canvas element) στο ίδιο ακριβώς χρώμα. Στο επόμενο κεφάλαιο θα δούμε πως να αλλάζουμε το χρώμα κάθε pixel χρησιμοποιώντας δύο τύπους εισόδου: το χώρο (τη θέση του pixel στην οθόνη) και το χρόνο (τον αριθμό των δευτερολέπτων από τη στιγμή που φορτώθηκε η σελιδα).

@ -0,0 +1,61 @@
## Uniforms
Μέχρι τώρα έχουμε δει πως η GPU διαχειρίζεται μεγάλο πλήθος από παράλληλα threads (νήματα), όπου το καθένα είναι υπεύθυνο να αναθέσει σε κάθε τμήμα της τελικής εικόνας το χρώμα του. Αν και κάθε παράλληλο thread είναι τυφλό προς τα υπόλοιπα, χρειάζεται να μπορούμε να στείλουμε κάποιες εισόδους από τη CPU (ΚΜΕ) σε όλα τα threads. Εξ' αιτίας της αρχιτεκτονικής της κάρτας γραφικών, αυτές οι έισοδοι θα είναι ίδιες (uniform - ομοιόμορφες) για όλα τα threads, και κατ' ανάγκη είναι *μόνο για ανάγνωση (read only)*. Με άλλα λόγια, κάθε thread παίρνει τα ίδια δεδομένα τα οποία μπορεί να διαβάσει αλλά όχι και να αλλάξει.
Αυτές οι είσοδοι λέγονται `uniform` και υπάρχουν για τους περισσότερους από τους υποστηριζόμενους τύπους: `float`, `vec2`, `vec3`, `vec4`, `mat2`, `mat3`, `mat4`, `sampler2D` και `samplerCube`. Τα uniforms ορίζονται μαζί με τον αντίστοιχο τύπο στην κορυφή του shader, αμέσως μετά την ανάθεση της ακρίβειας κινητής υποδιαστολής (default floating point precision).
```glsl
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution; // Μέγεθος καμβά (πλάτος, ύψος)
uniform vec2 u_mouse; // θέση του mouse σε συντεταγμένες οθόνης (σε pixels)
uniform float u_time; // Χρόνος σε δευτερόλεπτα (seconds) από τη φόρτωση της σελίδας
```
Μπορούμε να φανταστούμε τα uniforms σαν μικρές γέφυρες ανάμεσα στην CPU και τη GPU. Τα ομόματα θα διαφέρουν από υλοποίηση σε υλοποίηση, αλλά σε αυτά τα παραδείγματα πάντα τα περνάω σαν: `u_time` (χρόνος σε δευτερόλεπτα από τη στιγμή που ξεκίνησε ο shader), `u_resolution` (μέγεθος του πίνακα όπου ζωγραφίζεται ο shader) και `u_mouse` (θέση του mouse μέσα στον πίνακα σε pixels). Ακολουθώ τη σύμβαση να προσθέτω `u_` πριν από το όνομα του uniform ώστε να είμαι σαφής ως προς τη φύση της μεταβλητής, αλλά θα συναντήσετε όλων των ειδών τα ονόματα για uniforms. Για παράδειγμα, το [ShaderToy.com](https://www.shadertoy.com/) χρησιμοποιεί τα ίδια uniforms αλλά με τα ακόλουθα ονόματα:
```glsl
uniform vec3 iResolution; // ανάλυση του viewport (περιοχή "θέασης") (σε pixels)
uniform vec4 iMouse; // συντεταγμένες του mouse σε pixel. xy: τρέχουσα θέση, zw: θέση click
uniform float iTime; // χρόνος εκτέλεσης (playback) του shader (σε seconds)
```
Αλλά αρκετά με τα λόγια, ας δούμε τα uniforms στην πράξη. Στον ακόλουθο κώδικα χρησιμοποιούμε το `u_time` - τον αριθμό δευτερολέπτων από τη στιγμή που ο shaders άρχισε να εκτελείται - σε συνδυασμό με μια ημιτονοειδή συνάρτηση για να δώσουμε κίνηση στη μεταβολή του κόκκινου στον πίνακα.
<div class="codeAndCanvas" data="time.frag"></div>
Όπως βλέπετε, η GLSL έχει κι άλλες εκπλήξεις. Η GPU υποστηρίζει σε hardware συναρτήσεις γωνίας, τριγωνομετρικές και εκθετικές. Μερικές από αυτές τις συναρτήσεις είναι: [`sin()`](../glossary/?search=sin), [`cos()`](../glossary/?search=cos), [`tan()`](../glossary/?search=tan), [`asin()`](../glossary/?search=asin), [`acos()`](../glossary/?search=acos), [`atan()`](../glossary/?search=atan), [`pow()`](../glossary/?search=pow), [`exp()`](../glossary/?search=exp), [`log()`](../glossary/?search=log), [`sqrt()`](../glossary/?search=sqrt), [`abs()`](../glossary/?search=abs), [`sign()`](../glossary/?search=sign), [`floor()`](../glossary/?search=floor), [`ceil()`](../glossary/?search=ceil), [`fract()`](../glossary/?search=fract), [`mod()`](../glossary/?search=mod), [`min()`](../glossary/?search=min), [`max()`](../glossary/?search=max) και [`clamp()`](../glossary/?search=clamp).
Ώρα να παίξουμε πάλι με τον παραπάνω κώδικα.
* Επιβραδύνετε τη συχνότητα μέχρι η αλλαγή χρώματος σχεδόν να μη γίνεται αντιληπτή.
* Επιταχύνετέ τη μέχρι να βλέπετε ένα ενιαίο χρώμα που δε θα τρεμοσβήνει (flicker).
* Παίξτε με τα τρία κανάλια (RGB) σε διαφορετικές συχνότητες για να πάρετε ενδιαφέροντες συνδυασμούς και συμπεριφορές.
## gl_FragCoord
Κατά τον ίδιο τρόπο που η GLSL μας δίνει μια προκαθορισμένη (default) έξοδο, `vec4 gl_FragColor`, μας δίνει και μια προκαθορισμένη είσοδο, `vec4 gl_FragCoord`, η οποία περιέχει τις συντεταγμένες οθόνης του *pixel* ή *τεμάχιου οθόνης - screen fragment* στο οποίο δουλεύει το ενεργό thread. Με το `vec4 gl_FragCoord`, ξέρουμε που δουλεύει ένα thread μέσα στον πίνακα. Σε αυτή την περίπτωση δεν το ονομάζουμε `uniform` γιατί θα είναι διαφορετικό από το ένα thread στο άλλο, αντίθετα, το `gl_FragCoord` λέγεται *varying*.
<div class="codeAndCanvas" data="space.frag"></div>
Στον παραπάνω κώδικα *κανονικοποιούμε (normalize)* τις συντεταγμένες του fragment (τεμαχίου) διαιρώντας το με τη συνολική ανάλυση του πίνακα. Με αυτό τον τρόπο, οι τιμές θα βρίσκονται μεταξύ `0.0` και `1.0`, κάτι που το κάνει εύκολο να αντιστοιχίσουμε τις τιμές X και Y στα κανάλια RED (κόκκινο) και GREEN (πράσινο).
Στον κόσμο των shaders, δεν έχουμε και πολλές δυνατότητες για debugging (διόρθωση σφαλμάτων) πέρα από το να αναθέτουμε έντονα χρώματα σε μεταβλητές και να προσπαθούμε να βγάλουμε άκρη από αυτά. Θα ανακαλύψετε πως κάποιες φορές το να προγραμματίζετε σε GLSL είναι πολύ παρόμοιο με το να φτιάχνει κανείς καραβάκια μέσα σε μπουκάλια. Είναι εξ' ίσου δύσκολο, όμορφο και ευχάριστο.
![](08.png)
Ώρα να δοκιμάσουμε να τσεκάρουμε πόσο έχουμε κατανοήσει αυτό τον κώδικα.
* Μπορείτε να βρείτε που στον καμβά μας βρίσκονται οι συντεταγμένες `(0.0, 0.0)`;
* Ή οι συντεταγμένες `(1.0, 0.0)`, `(0.0, 1.0)`, `(0.5, 0.5)` και `(1.0, 1.0)`;
* Μπορείτε να βρείτε πως να χρησιμοποιήσετε το `u_mouse` γνωρίζοντας πως οι τιμές είναι σε pixels και ΟΧΙ κανονικοποιημένες; Μπορείτε να το χρησιμοποιήσετε για να κινήστε τα χρώματα;
* Μπορείτε να επινοήσετε έναν ενδιαφέροντα τρόπο να αλλάζετε το χρωματικό συνδυασμό χρησιμοποιώντας τις συντεταγμένες `u_time` και `u_mouse`?
Αφού ολοκληρώσετε αυτές τις ασκήσεις, θα αναρωτηθείτε ίσως πού αλλού μπορείτε να χρησιμοποιήστε τις νέες σας shaderοδυνάμεις. Στο επόμενο κεφάλαιο θα δούμε πως να φτιάξετε τα δικά σας εργαλεία shaders σε three.js, Processing, και openFrameworks.

@ -0,0 +1,233 @@
## Εκτελώντας τον shaders σας
Σαν μέρος της σύνθεσης αυτού του βιβλίου και της εξάσκησής μου στην πράξη, έφτιαξα ένα οικοσύστημα από εργαλεία ώστε που μπορεί κανείς να δημιουργήσει, να εμφανίσει, να μοιραστεί και να επιμεληθεί τους shaders του. Τα εργαλεία αυτά λειτουργούν ομοιόμορφα σε Linux, MacOS, Windows και [Raspberry Pi](https://www.raspberrypi.org/) και browsers (φυλλομετρητές) χωρίς να χρειάζεται να αλλάξετε τον κώδικά σας.
## Εκτελώντας τους shaders σας σε browser
**Εμφάνιση**: όλα τα διαδραστικά παραδείγματα σε αυτό το βιβλίο απεικονίζονται χρησιμοποιώντας [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) το οποίο κάνει τη διαδικασία του να τρέξουμε αυτόνομους shaders εξαιρετικά εύκολη.
```html
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
```
Όπως βλέπετε, χρειάζεται μόνο ένα `canvas` (HTML) element με `class="glslCanvas"` και το url του shader στο `data-fragment-url`. Μάθετε περισσότερα [εδώ](https://github.com/patriciogonzalezvivo/glslCanvas).
Αν είστε σαν εμένα, πιθανόν θα θέλετε να τρέξετε shaders απευθείας από τη γραμμή εντολών, σε αυτή την περίπτωση προτείνω να δείτε το [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Αυτή η εφαρμογή σας επιτρέπει να ενσωματώσετε shaders στα scripts (σενάρια εκτέλεσης) σας φλοιού `bash` ή σε pipelines ("σωληνώσεις" εργαλείων) unix και να τα χρησιμοποιήσετε παρόμοια με το [ImageMagick](http://www.imagemagick.org/script/index.php). Επίσης, το [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) είναι ένας πολύ καλός τρόπος να μεταγλωττίζετε shaders στο [Raspberry Pi](https://www.raspberrypi.org/) σας, ο οποίος είναι και ο λόγος που το [openFrame.io](http://openframe.io/) το χρησιμοποιεί για να εμφανίσει έργα τέχνης με shaders. Βρείτε περισσότερα για αυτή την εφαρμογή [εδώ](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -E screenshot,yourOutputImage.png
```
**Δημιουργία**: προκειμένου να αναδείξω την εμπειρία του να γράφουμε shaders, έφτιαξα ένα online editor (πρόγραμμα επεξεργασίας κειμένου) με όνομα [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Αυτός ο editor είναι ενσωματωμένος στα διαδραστικά παραδείγματα του βιβλίου. Μας δίνει ένα σύνολο από χρήσιμα widgets (εργαλεία διεπαφής) ώστε να κάνει πιο "απτή" την αφηρημένη εμπειρία του να δουλεύουμε με κώδικα glsl. Μπορείτε επίσης να τον τρέξετε σαν αυτόνομη εφαρμογή web από εδώ [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Μάθετε περισσότερα σχετικά [εδώ](https://github.com/patriciogonzalezvivo/glslEditor).
![](glslEditor-01.gif)
Αν προτιμάτε να δουλεύετε offline με το [SublimeText](https://www.sublimetext.com/) μπορείτε να εγκαταστήσετε αυτό το [πακέτο για τον glslViewer](https://packagecontrol.io/packages/glslViewer). Μάθετε περισσότερα [εδώ](https://github.com/patriciogonzalezvivo/sublime-glslViewer).
![](glslViewer.gif)
**Διανομή**: με τον online editor ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) μπορείτε να μοιραστείτε τους shaders σας! Και η online και ενσωματωμένη και η ανεξάρτητη έκδοση έχουν ένα κουμπί export (εξαγωγή) με το οποίο μπορείτε να πάρετε ένα μοναδικό URL για τον shader σας. Επίσης έχει τη δυνατότητα να κάνει export απευθείας σε ένα [openFrame.io](http://openframe.io/).
![](glslEditor-00.gif)
**Επιμέλεια**: Το να μοιραστείτε τον κώδικά σας είναι το πρώτο βήμα προς το να μοιραστείτε τον shader σας σαν έργο τέχνης! Εκτός από την επιλογή να κάνετε export σε [openFrame.io](http://openframe.io/) έφτιαξα ένα εργαλείο με το οποίο μπορείτε να οργανώσετε τους shaders σας σε μια έκθεση που μπορεί να ενσωματωθεί σε οποιοδήποτε site (ιστοχώρο), το όνομά του είναι [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery). Δείτε περισσότερα [εδώ](https://github.com/patriciogonzalezvivo/glslGallery).
![](glslGallery.gif)
## Εκτελώντας τους shaders στο περιβάλλον της προτίμησής σας
Αν έχετε ήδη εμπειρία προγραμματισμού σε κάποιο περιβάλλον όπως: [Processing](https://processing.org/), [Three.js](http://threejs.org/), [OpenFrameworks](http://openframeworks.cc/) ή [SFML](https://www.sfml-dev.org/), θα ανυπομονείτε πιθανόν να δοκιμάσετε shaders στις πλατφόρμες με τις οποίες αισθάνεστε οικεία. Τα παρακάτω είναι παραδείγματα για το πως να ορίσετε shaders σε κάποια γνωστά περιβάλλοντα με τα ίδια uniforms τα οποία θα χρησιμοποιήσουμε σε όλο το βιβλίο. (Στο [GitHub repository αυτού του κεφαλαίου](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), θα βρείτε ολόκληρο τον κώδικα γι' αυτά τα τρία περιβάλλοντα.)
### Σε **Three.js**
Ο ευφυέστατος και πολύ σεμνός Ricardo Cabello (επίσης γνωστός και σαν [MrDoob](https://twitter.com/mrdoob) ) αναπτύσσει ανάμεσα σε άλλους [συνεργάτες](https://github.com/mrdoob/three.js/graphs/contributors) ένα πιθανόν από τα πιο γνωστά περιβάλλοντα για WebGL, που ονομάζεται [Three.js](http://threejs.org/). Θα βρείτε πολλά παραδείγματα, μαθήματα και βιβλία που διδάσκουν πως να χρησιμοποιήσετε αυτή τη βιβλιοθήκη JavaScript για να δημιουργήσετε φοβερά 3D γραφικά.
Ακολουθεί ένα παράδειγμα για τις HTML και JS που που χρειάζεστε για να ξεκινήσετε με shaders σε three.js. Δώστε ιδιαίτερη σημασία στο script `id="fragmentShader"`, εδώ είναι που μπορείτε να αντιγράψετε τους shaders που βρίσκετε σε αυτό το βοβλίο.
```html
<body>
<div id="container"></div>
<script src="js/three.min.js"></script>
<script id="vertexShader" type="x-shader/x-vertex">
void main() {
gl_Position = vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2 u_resolution;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
gl_FragColor=vec4(st.x,st.y,0.0,1.0);
}
</script>
<script>
var container;
var camera, scene, renderer, clock;
var uniforms;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
clock = new THREE.Clock();
var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
uniforms = {
u_time: { type: "f", value: 1.0 },
u_resolution: { type: "v2", value: new THREE.Vector2() },
u_mouse: { type: "v2", value: new THREE.Vector2() }
};
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
container.appendChild( renderer.domElement );
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false );
document.onmousemove = function(e){
uniforms.u_mouse.value.x = e.pageX
uniforms.u_mouse.value.y = e.pageY
}
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
uniforms.u_time.value += clock.getDelta();
renderer.render( scene, camera );
}
</script>
</body>
```
### Σε **Processing**
Η [Processing](https://processing.org/) η οποία πρωτοξεκίνησε από τους [Ben Fry](http://benfry.com/) και [Casey Reas](http://reas.com/) το 2001, είναι ένα εξαιρετικά απλό και ισχυρό περιβάλλον για να κάνετε τα πρώτα σας βήματα σε κώδικα (σίγουρα ήταν για 'μένα). Ο [Andres Colubri](https://codeanticode.wordpress.com/) έχει κάνει σπουδαίες ενημερώσεις για την OpenGL και το video στην Processing, καθιστώντας το εκολότερο από ποτέ να παίξει κανείς με GLSL shaders στο φιλικό αυτό περιβάλλον. Η Processing ψάχνει για τον shader με όνομα `"shader.frag"` στον φάκελο `data` του sketch ("σκίτσο" - το project της Processing). Αντιγράψτε τα παραδείγματα που βρίσκετε εδώ σε αυτό τον φάκελο, και μετονομάστε το αρχείο.
```cpp
PShader shader;
void setup() {
size(640, 360, P2D);
noStroke();
shader = loadShader("shader.frag");
}
void draw() {
shader.set("u_resolution", float(width), float(height));
shader.set("u_mouse", float(mouseX), float(mouseY));
shader.set("u_time", millis() / 1000.0);
shader(shader);
rect(0,0,width,height);
}
```
Προκειμένου να δουλέψει ο shader σε εκδόσεις παλιότερες της 2.1, πρέπει να προσθέσετε την παρακάτω γραμμή στην αρχή του shader: `#define PROCESSING_COLOR_SHADER`, έτσι ώστε να δείχνει ως εξής:
```glsl
#ifdef GL_ES
precision mediump float;
#endif
#define PROCESSING_COLOR_SHADER
uniform vec2 u_resolution;
uniform vec3 u_mouse;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.st/u_resolution;
gl_FragColor = vec4(st.x,st.y,0.0,1.0);
}
```
Για περισσότερες πληροφορίες σχετικά με τους shaders σε Processing, δείτε αυτό το [μάθημα](https://processing.org/tutorials/pshader/).
### Σε **openFrameworks**
Για τον καθένα υπάρχει ένα μέρος όπου νιώθει άνετα, στην περίπτωσή μου, εξακολουθεί να είναι η [κοινότητα openFrameworks](http://openframeworks.cc/). Αυτή η βιβλιοθήκη C++ παρέχει ένα πλαίσιο αφαίρεσης γύρω απο την OpenGL και άλλες βιβλιοθήκες C++ ανοιχτού κώδικα. Κατά πολλές έννοιες είναι παρόμοια με την Processing, αλλά με τις προφανείς επιπλοκές του να δουλεύει κανείς με μεταγλωττιστές C++. Όμοια με την Processing, η openFrameworks αναζητά τα αρχεία shader στο φάκελο data, οπότε μην παραλείψετε να αντιγράψετε τα αρχεία `.frag` που θέλετε να χρησιμοποιήσετε και να αλλάξετε το όνομά τους όταν τα φορτώνετε.
```cpp
void ofApp::draw(){
ofShader shader;
shader.load("","shader.frag");
shader.begin();
shader.setUniform1f("u_time", ofGetElapsedTimef());
shader.setUniform2f("u_resolution", ofGetWidth(), ofGetHeight());
ofRect(0,0,ofGetWidth(), ofGetHeight());
shader.end();
}
```
Αν θέλετε να χρησιμοποιήσετε το πλήρες σύνολο απο uniforms που υπάρχουν στον ορισμό των GlslViewer και GlslCanvas με απλούστερο τρόπο σε OpenFrameworks, συνιστώ το addon (πρόσθετο) [ofxShader](https://github.com/patriciogonzalezvivo/ofxshader) το οποίο επίσης υποστηρίζει πολλαπλούς buffers (μνήμη εικόνας), shaders υλικών, hotreload (άμεση επανεκτέλεση) και αυτόματη μετατροπή σε OpenGL ES για το Raspberry Pi. Και ο κώδικάς σας θα απαιτεί μόνο το παρακάτω:
```cpp
//--------------------------------------------------------------
void ofApp::setup(){
ofDisableArbTex();
sandbox.allocate(ofGetWidth(), ofGetHeight());
sandbox.load("grayscott.frag");
}
//--------------------------------------------------------------
void ofApp::draw(){
sandbox.render();
sandbox.draw(0, 0);
}
```
Για περισσότερες πληροφορίες για τους shaders σε openFrameworks δείτε αυτό το [εξαιρετικό μάθημα](http://openframeworks.cc/ofBook/chapters/shaders.html) από τον [Joshua Noble](http://thefactoryfactory.com/).
### Σε **Blender**
Το [GlslTexture](https://github.com/patriciogonzalezvivo/glslTexture) είναι ένα addon που επιτρέπει να παράξετε textures (υφές) προγραμματιστικά χρησιμοποιώντας GLSL Shaders, και είναι πλήρως συμβατό με τα υπόλοιπα απο τα sandboxes (περιβάλλοντα) αυτού του κεφαλαίου. Να πως λειτουργεί:
1. Αναζήτηση Operator: `F3``SpaceBar (διάστημα)` ανάλογα με τις επιλογές περιβάλλοντος του Blender). Γράψτε `GlslTexture`
![](blender/00.png)
2. Αλλάξτε τα μεγέθη `width` και `height` και το αρχείο `Source` (όπου μπορείτε να βάλετε το path -τοποθεσία- ενός εξωτερικού αρχείου).
![](blender/01.png)
3. Χρησιμοποιήστε την Εικόνα στα υλικά σας. Το όνομα της Εικόνας βασίζεται στο όνομα του αρχείου source (βλ. 2)
![](blender/02.png)
4. Πηγαίνετε στον Text Editor (επεξεργαστή κειμένου - ή έναν εξωτερικό επεξεργαστή κειμένου αν το source αρχείο είναι εξωτερικό) και αλλάξτε τον shader. Οι αλλαγές είναι άμεσα ορατές.
![](blender/03.png)
Loading…
Cancel
Save