Hoe maak je een kubus in OpenGL (met afbeeldingen)

Inhoudsopgave:

Hoe maak je een kubus in OpenGL (met afbeeldingen)
Hoe maak je een kubus in OpenGL (met afbeeldingen)

Video: Hoe maak je een kubus in OpenGL (met afbeeldingen)

Video: Hoe maak je een kubus in OpenGL (met afbeeldingen)
Video: How To Install Windows XP In Virtual Box - 2023 2024, Mei
Anonim

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

1994315 1 1
1994315 1 1

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.

1994315 2 1
1994315 2 1

Stap 2. Maak het document aan

Maak een nieuw bestand in je favoriete code-editor en sla het op als mycube.c

1994315 3 1
1994315 3 1

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

1994315 4 1
1994315 4 1

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;

1994315 5 1
1994315 5 1

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);

  • Deze verklaring stelt uw omgeving in. Een belangrijk ding om te onthouden bij het schrijven van OpenGL-programma's is dat je om alles moet vragen. Dit vereist dat u een beter begrip heeft van hoe uw programma werkt en wat u moet opnemen om de gewenste functionaliteit te krijgen. In deze regel stelt u het display in met dubbele buffering, RGB-kleur en een Z-buffer.
  • Dubbele buffering is een techniek die in grafische programma's wordt gebruikt om een probleem op te lossen dat ontstaat door de manier waarop afbeeldingen naar het scherm worden getrokken. Elke keer dat u de scène opnieuw tekent, moet eerst de weergave worden gewist en vervolgens wordt de nieuwe informatie getekend. Zonder dubbele buffering zult u een flikkerend effect waarnemen als het scherm herhaaldelijk wordt gewist en opnieuw getekend.
  • Dit probleem wordt verholpen door een tweede buffer toe te voegen om naar te tekenen. Met deze methode wordt een afbeelding naar de eerste buffer getrokken en die buffer wordt aan u getoond. Het volgende frame wordt naar de tweede buffer getrokken en als dat is gebeurd, wisselen de twee buffers van plaats. Je ziet meteen de tweede buffer, maar, voor ons verborgen, wordt de eerste buffer gewist en opnieuw getekend met het derde frame dat wordt ingewisseld als het klaar is.
  • U wilt ook de RGB-kleur systeem in uw raam.
  • Z-buffering is hoe u de 3D-effecten krijgt die u wilt. OpenGL gebruikt een driedimensionaal coördinatensysteem met x-, y- en z-assen. Om het effect te geven dat een object dichter bij u is, wordt de positie op de z-as vergroot, maar om het verder weg te laten lijken, wordt de positie op de z-as verkleind.
1994315 6 1
1994315 6 1

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");

1994315 7 1
1994315 7 1

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);

1994315 8 1
1994315 8 1

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);

1994315 9 1
1994315 9 1

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

1994315 10 1
1994315 10 1

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

1994315 11 1
1994315 11 1

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);

1994315 12 1
1994315 12 1

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();

1994315 13 1
1994315 13 1

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();

1994315 14 1
1994315 14 1

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();

1994315 15 1
1994315 15 1

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

1994315 16 1
1994315 16 1

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(); }

1994315 17 1
1994315 17 1

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 ….

  • Merk eerst op dat de syntaxis van glRotatief() is vergelijkbaar met die van glColor3f() en glVertex3f() maar vereist altijd 4 parameters. De eerste parameter is de toe te passen rotatiegraad. De volgende drie parameters bepalen om welke as moet worden gedraaid, waarbij de eerste de x-as is, de tweede de y-as en de derde de z-as. Op dit moment hoef je alleen maar om de x- en y-as te draaien.
  • Alle transformaties die u in uw programma schrijft, hebben soortgelijke regels nodig. Conceptueel kun je dit zien als het roteren van je object om de x-as met de hoeveelheid gedefinieerd door roteren_x en dan roteren rond de y-as door roteren_y. OpenGL combineert echter al deze uitspraken in één matrixtransformatie. Elke keer dat u de weergavefunctie aanroept, bouwt u een transformatiematrix en glLoadIdentity() zorgt ervoor dat u in elke doorgang met een nieuwe matrix begint.
  • De andere transformatiefuncties die u kunt toepassen zijn glTranslatef() en glScalef(). Deze functies zijn vergelijkbaar met glRotatef() met de uitzondering dat ze slechts 3 parameters nodig hebben, de bedragen x, y en z om het object te vertalen of te schalen.
  • Om het juiste effect te krijgen bij het toepassen van alle drie de transformaties op één object, moet u ze in de juiste volgorde toepassen. Schrijf ze altijd in de volgorde glTranslate, glRotate, dan glScale. OpenGL past de transformaties in wezen bottom-up toe. Om dit te begrijpen, probeer je voor te stellen hoe een eenvoudige 1x1x1 kubus eruit zou zien met de transformaties als OpenGL ze van boven naar beneden zou toepassen en als OpenGL ze van onder naar boven zou toepassen.
1994315 18 1
1994315 18 1

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);

1994315 19 1
1994315 19 1

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

1994315 20 1
1994315 20 1

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; }

Aanbevolen: