OpenGL is een krachtige 3D-programmeertool die wordt gebruikt om complexe driedimensionale scènes van eenvoudige primitieven te tekenen. Dit artikel leert je hoe je een eenvoudige kubus tekent die je kunt draaien om in drie dimensies te bekijken!
Voor dit project heb je een code-editor en enige kennis van C-programmering nodig.
Stappen
Deel 1 van 3: Eerste installatie
Stap 1. Installeer OpenGL Volg deze stappen om OpenGL op uw systeem te installeren om te beginnen
Als u al OpenGL en een compatibele C-compiler hebt geïnstalleerd, kunt u deze stap overslaan en naar de volgende gaan.
Stap 2. Maak het document aan
Maak een nieuw bestand in je favoriete code-editor en sla het op als mycube.c
Stap 3. Voeg #includes toe
Dit zijn de basisonderdelen die je nodig hebt voor je programma. Het is belangrijk om te beseffen dat er eigenlijk verschillende omvat nodig zijn voor de verschillende besturingssystemen. Zorg ervoor dat u deze allemaal opneemt om ervoor te zorgen dat uw programma veelzijdig is en voor elke gebruiker kan worden uitgevoerd.
// Inclusief #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif
Stap 4. Functie-prototypes en globale variabelen toevoegen
Uw volgende stap is het declareren van enkele functie-prototypes.
// Functie Prototypes void display(); ongeldig specialeKeys(); // Globale variabelen dubbel roteren_y=0; dubbel roteren_x=0;
Stap 5. Stel de functie main() in
int main(int argc, char* argv){ // Initialiseer GLUT en verwerk gebruikersparameters glutInit(&argc, argv); // Verzoek dubbel gebufferd True Color-venster met Z-buffer glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
Stap 6. Maak het venster
De volgende stap is om maak het venster waarbinnen je de kubus gaat tekenen. In deze tutorial heet het venster "Awesome Cube".
// Maak een venster glutCreateWindow ("Awesome Cube");
Stap 7. Schakel dieptetest in
OpenGL is een strikte taal omdat het niet veronderstelt dat speciale functies zijn ingeschakeld. Om uw programma correct in 3 dimensies weer te geven met behulp van de Z-buffer die u eerder hebt bekeken, moet u: dieptetest inschakelen. Terwijl je OpenGL blijft verkennen, zul je veel functies ontdekken die je moet inschakelen, waaronder verlichting, texturen, cull-facing en nog veel meer.
// Schakel Z-bufferdieptetest glEnable in (GL_DEPTH_TEST);
Stap 8. Terugbelfuncties toevoegen
Dit zijn de callback-functies waarvoor u eerder de prototypes hebt geschreven. Elke keer dat de hoofdlus wordt doorlopen, worden deze functies aangeroepen. De weergavefunctie tekent de scène opnieuw op basis van eventuele wijzigingen in variabelen die zijn aangebracht sinds de vorige oproep. De specialeKeys-functie stelt ons in staat om met het programma te communiceren.
// Terugbelfuncties glutDisplayFunc (display); glutSpecialFunc (speciale sleutels);
Stap 9. Start de MainLoop
Hierdoor wordt de hoofdfunctie opgeroepen totdat u het programma sluit om animaties en gebruikersinteractie mogelijk te maken.
// Geef de controle door aan GLUT voor evenementen glutMainLoop(); // Keer terug naar OS retour 0; }
Deel 2 van 3: De display()-functie
Stap 1. Begrijp het doel van deze functie
Al het werk van het tekenen van uw kubus zal in deze functie worden gedaan. Het algemene idee achter je kubus is om alle zes zijden afzonderlijk te tekenen en ze in de juiste positie te plaatsen.
Conceptueel wordt elke zijde getekend door de vier hoeken te definiëren en OpenGL de lijnen te laten verbinden en deze in te vullen met een kleur die u definieert. Hieronder staan de stappen om dit te doen
Stap 2. Voeg glClear() toe
De eerste stap die u in deze functie moet nemen, is: wis de kleur en Z-buffer. Zonder deze stappen kunnen de oude tekeningen nog steeds zichtbaar zijn onder de nieuwe tekeningen en zouden de getekende objecten niet op de juiste plaats op het scherm staan.
void display () {// Clear screen en Z-buffer glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
Stap 3. Voeg glBegin() en glEnd() toe
OpenGL definieert objecten als combinaties van verschillende polygonen. De … gebruiken glBegin() commando, leg je effectief een potlood neer dat een vorm zal tekenen. Om het potlood op te tillen en een nieuwe vorm te beginnen, moet je de glEnd() opdracht. In deze zelfstudie gebruik je GL_POLYGON om elke zijde van de kubus te tekenen, maar het is mogelijk om andere parameteropties zoals GL_LINE, GL_QUAD of GL_TRIANGLE te gebruiken om andere vormen te maken.
- Hier begin je met de voorkant van je kubus. Later voeg je kleur toe aan alle 6 zijden.
// Veelkleurige zijkant - FRONT glBegin (GL_POLYGON); // Vertices worden toegevoegd in de volgende stap glEnd();
Stap 4. Voeg glVertex3f() toe
Nadat u hebt aangegeven dat u met uw polygoon wilt beginnen, moet u: definieer de hoekpunten van het voorwerp. glVertex heeft meerdere vormen, afhankelijk van wat u met uw object wilt doen.
- De eerste is in hoeveel dimensies u werkt. De 3 hierboven in glVertex3f zegt dat u in 3 dimensies tekent. Het is ook mogelijk om in 2 of 4 dimensies te werken. De f hierboven in glVertex3f zegt dat je met getallen met drijvende komma werkt. Je kunt ook shorts, integers of doubles gebruiken.
- Merk op dat deze punten zijn gedefinieerd in a tegen de klok in manier. Dit is op dit moment niet erg belangrijk, maar wanneer je begint te werken met verlichting, texturen en cull-facing, zal dit ongelooflijk belangrijk worden, dus maak er een gewoonte van om je punten nu tegen de klok in te definiëren.
- Voeg de hoekpunten toe tussen de regels glBegin() en glEnd().
// Veelkleurige zijkant - FRONT glBegin (GL_POLYGON); glVertex3f(-0,5, -0,5, -0,5); // P1 glVertex3f(-0,5, 0,5, -0,5); // P2 glVertex3f (0,5, 0,5, -0,5); // P3 glVertex3f (0,5, -0,5, -0,5); // P4 glEnd();
Stap 5. Voeg glColor3f() toe
glColor werkt op dezelfde manier als glVertex. U kunt punten definiëren als shorts, integers, doubles of floats. Elke kleur heeft een waarde van 0 tot 1. Alle nullen maken het punt zwart en alle enen maken het punt wit. De 3 in glColor3f() verwijst naar het RGB-kleursysteem zonder alfakanaal. De alfa van een kleur bepaalt de transparantie. Gebruik glColor4f() om het alfaniveau te wijzigen, waarbij de laatste parameter een waarde van 0 tot 1 is voor dekkend tot transparant.
- Als je glColor3f() aanroept, zal elk hoekpunt dat vanaf dat punt wordt getekend, die kleur hebben. Daarom, als u wilt dat alle vier de hoekpunten rood zijn, stelt u de kleur één keer in op elk moment voor de glVertex3f()-opdrachten en alle hoekpunten zullen rood zijn.
- De hieronder gedefinieerde voorkant laat zien hoe u een nieuwe kleur voor elk hoekpunt definieert. Wanneer u dit doet, ziet u een interessante eigenschap van de OpenGL-kleuren. Aangezien elk hoekpunt van de polygoon zijn eigen kleur heeft, zal OpenGL automatisch de kleuren mengen! De volgende stap laat zien hoe u vier hoekpunten met dezelfde kleur toewijst.
// Veelkleurige zijkant - FRONT glBegin (GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); // P1 is rood glColor3f(0.0, 1.0, 0.0); glVertex3f(0,5, 0,5, -0,5); // P2 is groen glColor3f (0.0, 0.0, 1.0); glVertex3f(-0,5, 0,5, -0,5); // P3 is blauw glColor3f (1.0, 0.0, 1.0); glVertex3f(-0,5, -0,5, -0,5); // P4 is paars glEnd();
Stap 6. Behandel de andere kanten
Bereken wat de locatie van elk hoekpunt zal zijn voor de andere vijf zijden van de kubus, maar voor de eenvoud zijn deze voor u berekend en zijn opgenomen in de laatste weergave() functie onderstaand.
// Witte kant - BACK glBegin (GL_POLYGON); glColor3f(1.0, 1.0, 1.0); glVertex3f(0,5, -0,5, 0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); glEnd(); // Paarse kant - RECHTS glBegin (GL_POLYGON); glColor3f(1.0, 0.0, 1.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, -0,5, 0,5); glEnd(); // Groene kant - LINKS glBegin (GL_POLYGON); glColor3f(0.0, 1.0, 0.0); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, -0,5, -0,5); glEnd(); // Blauwe kant - TOP glBegin (GL_POLYGON); glColor3f(0.0, 0.0, 1.0); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, 0,5); glEnd(); // Rode kant - BODEM glBegin (GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, -0,5); glEnd(); glFlush(); glutSwapBuffers(); }
We willen ook twee laatste regels code toevoegen voor deze functie. Dit zijn glFlush();
en glutSwapBuffers();
die ons het dubbele buffereffect geven waar u eerder over hoorde.
Deel 3 van 3: Gebruikersinteractiviteit
Stap 1. Voeg speciale sleutels() toe
Je bent bijna klaar, maar op dit moment kun je een kubus tekenen, maar je kunt hem niet draaien. Om dit te doen, zul je maak een speciale sleutels() functie waarmee we op de pijltjestoetsen kunnen drukken en de kubus kunnen draaien!
- Deze functie is de reden waarom je de globale variabelen roteren_x en roteren_y hebt gedeclareerd. Wanneer u op de rechter- en linkerpijltoetsen drukt, wordt roteren_y met 5 graden verhoogd of verlaagd. Evenzo, wanneer u op de pijltoetsen omhoog en omlaag drukt, zal roteren_x overeenkomstig veranderen.
void specialKeys (int-toets, int x, int y) { // Pijl naar rechts - verhoog de rotatie met 5 graden als (toets == GLUT_KEY_RIGHT) roterende_y += 5; // Pijl naar links - verlaag de rotatie met 5 graden anders als (toets == GLUT_KEY_LEFT) roteren_y -= 5; anders if (toets == GLUT_KEY_UP) roteren_x += 5; anders als (toets == GLUT_KEY_DOWN) roteren_x -= 5; // Verzoek weergave-update glutPostRedisplay(); }
Stap 2. Voeg glRotate() toe
Uw laatste verklaring is om de verklaring toe te voegen die uw object zal draaien. Ga terug naar de display()-functie en voeg voor de FRONT-kant deze regels toe:
// Reset transformaties glLoadIdentity(); // Roteren wanneer de gebruiker roteert_x en roteert_y glRotatef (rotate_x, 1.0, 0.0, 0.0); glRotatef(rotatie_y, 0.0, 1.0, 0.0); // Veelkleurige zijkant - FRONT ….
Stap 3. Voeg de volgende opdrachten toe om de kubus te schalen met 2 langs de x-as, 2 langs de y-as, draai de kubus 180 graden om de y-as en vertaal de kubus met 0,1 langs de x-as
Zorg ervoor dat u deze en de vorige glRotate()-opdrachten in de juiste volgorde rangschikt, zoals hierboven beschreven. (Als je het niet zeker weet, doe je dit in de definitieve code aan het einde van de tutorial.)
// Andere transformaties glTranslatef(0.1, 0.0, 0.0); gl Rotatef(180, 0.0, 1.0, 0.0); glScalef(2.0, 2.0, 0.0);
Stap 4. Compileer en voer uw code uit
Ervan uitgaande dat u gcc als uw compiler gebruikt, voert u deze opdrachten uit vanaf uw terminal om uw programma te compileren en te testen.
Op Linux: gcc cube.c -o cube -lglut -lGL./ mycube Op Mac: gcc -o foo foo.c -framework GLUT -framework OpenGL./ mycube Op Windows: gcc -Wall -ofoo foo.c -lglut32cu - lglu32 -lopengl32./ mycube
Stap 5. Controleer uw volledige code
Het zou zo moeten zijn:
// // Bestand: mycube.c // Auteur: Matt Daisley // Gemaakt: 25-4-2012 // Project: Broncode voor Make a Cube in OpenGL // Beschrijving: Maakt een OpenGL-venster en tekent een 3D-kubus / / Dat de gebruiker kan draaien met de pijltjestoetsen // // Bediening: Pijl naar links - Links draaien // Pijl naar rechts - Rechts draaien // Pijl omhoog - Omhoog draaien // Pijl omlaag - Omlaag draaien // ------ -------------------------------------------------- -- // Inclusief // ------------------------------------------- --------------- #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif // ------------- --------------------------------------------- // Functie Prototypes / / ------------------------------------------------- --------- ongeldige weergave(); ongeldig specialeKeys(); // ------------------------------------------------ ---------- // Globale variabelen // ---------------------------------- ------------------------ dubbel roteren_y=0; dubbel roteren_x=0; // ------------------------------------------------ ---------- // display() Terugbelfunctie // ------------------------------- --------------------------- void display () {// Scherm wissen en Z-buffer glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Reset transformaties glLoadIdentity(); // Andere transformaties // glTranslatef(0.1, 0.0, 0.0); // Niet inbegrepen // glRotatef(180, 0.0, 1.0, 0.0); // Niet inbegrepen // Roteren wanneer de gebruiker roteert_x en roteert_y glRotatef(rotate_x, 1.0, 0.0, 0.0); glRotatef(rotatie_y, 0.0, 1.0, 0.0); // Andere transformaties // glScalef(2.0, 2.0, 0.0); // Niet inbegrepen // Veelkleurige zijkant - FRONT glBegin (GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); // P1 is rood glColor3f(0.0, 1.0, 0.0); glVertex3f(0,5, 0,5, -0,5); // P2 is groen glColor3f (0.0, 0.0, 1.0); glVertex3f(-0,5, 0,5, -0,5); // P3 is blauw glColor3f (1.0, 0.0, 1.0); glVertex3f(-0,5, -0,5, -0,5); // P4 is paars glEnd(); // Witte kant - BACK glBegin (GL_POLYGON); glColor3f(1.0, 1.0, 1.0); glVertex3f(0,5, -0,5, 0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); glEnd(); // Paarse kant - RECHTS glBegin (GL_POLYGON); glColor3f(1.0, 0.0, 1.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, -0,5, 0,5); glEnd(); // Groene kant - LINKS glBegin (GL_POLYGON); glColor3f(0.0, 1.0, 0.0); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, 0,5, 0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, -0,5, -0,5); glEnd(); // Blauwe kant - TOP glBegin (GL_POLYGON); glColor3f(0.0, 0.0, 1.0); glVertex3f(0,5, 0,5, 0,5); glVertex3f(0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, -0,5); glVertex3f(-0,5, 0,5, 0,5); glEnd(); // Rode kant - BODEM glBegin (GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f(0,5, -0,5, -0,5); glVertex3f(0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, 0,5); glVertex3f(-0,5, -0,5, -0,5); glEnd(); glFlush(); glutSwapBuffers(); } // ----------------------------------------------- ----------- // specialKeys() Terugbelfunctie // ------------------------------ ---------------------------- void specialKeys (int key, int x, int y) { // Pijl naar rechts - verhoog de rotatie met 5 mate als (toets == GLUT_KEY_RIGHT) roteren_y += 5; // Pijl naar links - verlaag de rotatie met 5 graden anders als (toets == GLUT_KEY_LEFT) roteren_y -= 5; anders if (toets == GLUT_KEY_UP) roteren_x += 5; anders if (toets == GLUT_KEY_DOWN) roteren_x -= 5; // Verzoek weergave-update glutPostRedisplay(); } // ----------------------------------------------- ----------- // hoofdfunctie // ------------------------------- --------------------------- int main(int argc, char* argv){ // Initialiseer GLUT en verwerk gebruikersparameters glutInit(&argc,argv); // Verzoek dubbel gebufferd True Color-venster met Z-buffer glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Maak een venster glutCreateWindow ("Awesome Cube"); // Schakel Z-bufferdieptetest glEnable in (GL_DEPTH_TEST); // Terugbelfuncties glutDisplayFunc (display); glutSpecialFunc (speciale sleutels); // Geef de controle door aan GLUT voor evenementen glutMainLoop(); // Keer terug naar OS retour 0; }