OpenGL to potężne narzędzie do programowania 3D używane do rysowania złożonych trójwymiarowych scen z prostych prymitywów. W tym artykule dowiesz się, jak narysować prosty sześcian, który możesz obracać, aby zobaczyć w trzech wymiarach!
Do tego projektu będziesz potrzebować edytora kodu i pewnej znajomości programowania w C.
Kroki
Część 1 z 3: Konfiguracja wstępna
Krok 1. Zainstaluj OpenGL Aby rozpocząć, wykonaj następujące kroki, aby zainstalować OpenGL w swoim systemie
Jeśli masz już zainstalowany OpenGL, a także kompatybilny kompilator C, możesz pominąć ten krok i przejść do następnego.
Krok 2. Utwórz dokument
Utwórz nowy plik w swoim ulubionym edytorze kodu i zapisz go jako mycube.c
Krok 3. Dodaj #zawiera
Są to podstawowe dodatki, których będziesz potrzebować w swoim programie. Ważne jest, aby zdać sobie sprawę, że w rzeczywistości istnieją różne dodatki wymagane dla różnych systemów operacyjnych. Pamiętaj, aby uwzględnić je wszystkie, aby zapewnić, że Twój program jest wszechstronny i może działać dla każdego użytkownika.
// Obejmuje #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif
Krok 4. Dodaj prototypy funkcji i zmienne globalne
Następnym krokiem jest zadeklarowanie prototypów funkcji.
// Prototypy funkcji void display(); nieważne klawisze specjalne(); // Zmienne globalne double rotate_y=0; podwójna rotacja_x=0;
Krok 5. Skonfiguruj funkcję main()
int main(int argc, char* argv){ // Inicjalizacja GLUT i przetwarzanie parametrów użytkownika glutInit(&argc, argv); // Zażądaj podwójnie buforowanego okna True Color z buforem Z glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
Krok 6. Utwórz okno
Następnym krokiem jest: utwórz okno w którym narysujesz sześcian. W tym samouczku okno nazywa się „Awesome Cube”.
// Utwórz okno glutCreateWindow("Niesamowita kostka");
Krok 7. Włącz test głębokości
OpenGL jest językiem ścisłym, ponieważ nie zakłada włączenia żadnych specjalnych funkcji. Aby Twój program poprawnie wyświetlał się w 3 wymiarach przy użyciu bufora Z, który oglądałeś wcześniej, musisz: włącz test głębokości. Kontynuując eksplorację OpenGL, odkryjesz wiele funkcji, które będziesz musiał włączyć, w tym oświetlenie, tekstury, celowanie i wiele więcej.
// Włącz test głębokości bufora Z glEnable(GL_DEPTH_TEST);
Krok 8. Dodaj funkcje zwrotne
Oto funkcje zwrotne, dla których napisałeś wcześniej prototypy. Za każdym razem, gdy przechodzimy przez główną pętlę, te funkcje będą wywoływane. Funkcja wyświetlania ponownie rysuje scenę na podstawie wszelkich zmian zmiennych, które zostały wprowadzone od poprzedniego wywołania. Funkcja specialKeys pozwala nam na interakcję z programem.
// Funkcje zwrotne glutDisplayFunc(display); glutSpecialFunc(specialKeys);
Krok 9. Uruchom MainLoop
Spowoduje to przywołanie głównej funkcji, dopóki nie zamkniesz programu, aby umożliwić animacje i interakcję użytkownika.
// Przekaż kontrolę do GLUT dla zdarzeń glutMainLoop(); // Powrót do systemu operacyjnego return 0; }
Część 2 z 3: Funkcja wyświetlania ()
Krok 1. Zrozum cel tej funkcji
Cała praca związana z rysowaniem sześcianu zostanie wykonana w tej funkcji. Ogólną ideą stojącą za kostką jest narysowanie wszystkich sześciu boków osobno i umieszczenie ich w odpowiedniej pozycji.
Koncepcyjnie każda strona zostanie narysowana poprzez zdefiniowanie czterech rogów i pozwolenie OpenGL na połączenie linii i wypełnienie ich zdefiniowanym kolorem. Poniżej znajdują się kroki, aby to zrobić
Krok 2. Dodaj glClear()
Pierwszym krokiem, który musisz wykonać w tej funkcji, jest: wyczyść kolor i bufor Z. Bez tych kroków stare rysunki mogą być nadal widoczne pod nowymi rysunkami, a narysowane obiekty nie będą znajdować się we właściwym miejscu na ekranie.
void display(){ // Wyczyść ekran i bufor Z glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
Krok 3. Dodaj glBegin() i glEnd()
OpenGL definiuje obiekty jako kombinacje różnych wielokątów. Używając glPoczątek() skutecznie odłożysz ołówek, który narysuje kształt. Aby podnieść ołówek i rozpocząć nowy kształt, musisz użyć gLend() Komenda. W tym samouczku będziesz używać GL_POLYGON do rysowania każdej strony sześcianu, ale możliwe jest użycie innych opcji parametrów, takich jak GL_LINE, GL_QUAD lub GL_TRIANGLE, aby utworzyć inne kształty.
- Tutaj zaczniesz od przodu swojej kostki. Później dodasz kolor na wszystkich 6 bokach.
// Wielokolorowa strona - FRONT glBegin(GL_POLYGON); // Wierzchołki zostaną dodane w następnym kroku glEnd();
Krok 4. Dodaj glVertex3f()
Po stwierdzeniu, że chcesz rozpocząć swój wielokąt, musisz: zdefiniuj wierzchołki obiektu. glVertex ma wiele form w zależności od tego, co chcesz zrobić ze swoim obiektem.
- Pierwszy to liczba wymiarów, w których pracujesz. 3 powyżej w glVertex3f mówi, że rysujesz w 3 wymiarach. Możliwa jest również praca w 2 lub 4 wymiarach. f powyżej w glVertex3f mówi, że pracujesz z liczbami zmiennoprzecinkowymi. Możesz również użyć krótkich, liczb całkowitych lub podwójnych.
- Zauważ, że te punkty są zdefiniowane w a przeciwnie do ruchu wskazówek zegara sposób. W tej chwili nie jest to bardzo ważne, ale kiedy zaczniesz pracować z oświetleniem, teksturami i celowaniem, stanie się to niezwykle ważne, więc przyzwyczaj się teraz do definiowania punktów przeciwnie do ruchu wskazówek zegara.
- Dodaj dodaj wierzchołki między wierszami glBegin() i glEnd().
// Wielokolorowa strona - 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();
Krok 5. Dodaj glColor3f()
glColor działa w podobny sposób jak glVertex. Możesz zdefiniować punkty jako krótkie, całkowite, podwójne lub zmiennoprzecinkowe. Każdy kolor ma wartość od 0 do 1. Wszystkie zera sprawiają, że punkt jest czarny, a wszystkie jedynki powodują, że punkt jest biały. 3 w glColor3f() odnosi się do systemu kolorów RGB bez kanału alfa. Alfa koloru określa jego przezroczystość. Aby zmienić poziom alfa, użyj glColor4f() z ostatnim parametrem o wartości od 0 do 1 dla nieprzezroczystego do przezroczystego.
- Kiedy wywołasz glColor3f(), każdy wierzchołek narysowany od tego punktu będzie miał ten kolor. Dlatego, jeśli chcesz, aby wszystkie cztery wierzchołki były czerwone, po prostu ustaw kolor raz w dowolnym momencie przed poleceniami glVertex3f(), a wszystkie wierzchołki będą czerwone.
- Strona przednia zdefiniowana poniżej pokazuje, jak zdefiniować nowy kolor dla każdego wierzchołka. Gdy to zrobisz, zobaczysz interesującą właściwość kolorów OpenGL. Ponieważ każdy wierzchołek wielokąta ma swój własny kolor, OpenGL automatycznie połączy kolory! Następny krok pokaże, jak przypisać cztery wierzchołki tego samego koloru.
//Wielokolorowa strona - FRONT glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); // P1 jest czerwony glColor3f(0.0, 1.0, 0.0); glVertex3f (0,5, 0,5, -0,5); // P2 jest zielony glColor3f(0.0, 0.0, 1.0); glVertex3f (-0,5, 0,5, -0,5); // P3 jest niebieskie glColor3f(1.0, 0.0, 1.0); glVertex3f (-0,5, -0,5, -0,5); // P4 jest fioletowy glEnd();
Krok 6. Zajmij się innymi stronami
Ustal, jakie będzie położenie każdego wierzchołka dla pozostałych pięciu boków sześcianu, ale dla uproszczenia zostały one obliczone dla Ciebie i są zawarte w funkcja końcowego wyświetlania() poniżej.
// Biała strona - 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(); // Fioletowa strona - PRAWY 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(); // Zielona strona - LEWA 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(); // Niebieska strona - 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(); // czerwona strona - BOTTOM 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(); glutSwapBufory(); }
Chcemy również dodać dwie ostatnie linijki kodu dla tej funkcji. To są glFlush();
oraz glutSwapBufory();
które dają nam efekt podwójnego buforowania, o którym dowiedziałeś się wcześniej.
Część 3 z 3: Interaktywność użytkownika
Krok 1. Dodaj specialKeys()
Prawie gotowe, ale w tej chwili możesz narysować sześcian, ale nie masz możliwości jego obrócenia. Aby to zrobić, będziesz utwórz klawisze specjalne() funkcja pozwalająca nam naciskać klawisze strzałek i obracać kostkę!
- Ta funkcja jest powodem, dla którego zadeklarowałeś zmienne globalne rotate_x i rotate_y. Po naciśnięciu prawego i lewego klawisza strzałki, rotate_y będzie zwiększany lub zmniejszany o 5 stopni. Podobnie, gdy naciśniesz klawisze strzałek w górę i w dół, wartość rotate_x zmieni się odpowiednio.
void specialKeys(int key, int x, int y) { // Strzałka w prawo - zwiększ obrót o 5 stopni jeśli (key == GLUT_KEY_RIGHT) rotate_y += 5; // Strzałka w lewo - zmniejsz obrót o 5 stopni w przeciwnym razie jeśli (key == GLUT_KEY_LEFT) rotate_y -= 5; inaczej if (klucz == GLUT_KEY_UP) rotate_x += 5; w przeciwnym razie if (klucz == GLUT_KEY_DOWN) rotate_x -= 5; // Poproś o aktualizację wyświetlania glutPostRedisplay(); }
Krok 2. Dodaj glRotate()
Twoim ostatnim stwierdzeniem jest dodanie stwierdzenia, które spowoduje rotację twojego obiektu. Wróć do funkcji display() i przed stroną FRONT dodaj te linie:
// Resetowanie transformacji glLoadIdentity(); // Obróć, gdy użytkownik zmieni rotate_x i rotate_y glRotatef(rotate_x, 1.0, 0.0, 0.0); glRotatef(obrót_y, 0.0, 1.0, 0.0); // Wielokolorowa strona - FRONT ….
Krok 3. Dodaj następujące polecenia, aby przeskalować sześcian o 2 wzdłuż osi x, 2 wzdłuż osi y, obrócić sześcian o 180 stopni wokół osi y i przesunąć sześcian o 0,1 wzdłuż osi x
Upewnij się, że ułożyłeś je oraz poprzednie polecenia glRotate() we właściwej kolejności, jak opisano powyżej. (Jeśli nie masz pewności, robi się to w końcowym kodzie na końcu samouczka).
// Inne przekształcenia glTranslatef(0.1, 0.0, 0.0); glRotatef(180, 0,0, 1,0, 0,0); glScalef (2,0, 2,0, 0,0);
Krok 4. Skompiluj i uruchom swój kod
Zakładając, że używasz gcc jako kompilatora, uruchom te polecenia z terminala, aby skompilować i przetestować swój program.
W systemie Linux: gcc cube.c -o cube -lglut -lGL./ mycube W systemie Mac: gcc -o foo foo.c -framework GLUT -framework OpenGL./ mycube W systemie Windows: gcc -Wall -ofoo foo.c -lglut32cu - lglu32 -lopengl32./ mycube
Krok 5. Sprawdź swój pełny kod
Powinno być tak:
// // Plik: mycube.c // Autor: Matt Daisley // Utworzono: 25.04.2012 // Projekt: Kod źródłowy do tworzenia kostki w OpenGL // Opis: Tworzy okno OpenGL i rysuje kostkę 3D // / Że użytkownik może obracać za pomocą klawiszy strzałek // // Sterowanie: Strzałka w lewo - Obróć w lewo // Strzałka w prawo - Obróć w prawo // Strzałka w górę - Obróć w górę // Strzałka w dół - Obróć w dół // ------ -------------------------------------------------- -- // Zawiera // -------------------------------------------- --------------- #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef _APPLE_ #include #else #include #endif // ------------- ---------------------------------------------- // Prototypy funkcji / / -------------------------------------------------- --------- nieważne wyświetlanie(); nieważne klawisze specjalne(); // ------------------------------------------------ ---------- // Zmienne globalne // ---------------------------------- ------------------------ podwójna rotacja_y=0; podwójna rotacja_x=0; // ------------------------------------------------ ---------- // display() Funkcja wywołania zwrotnego // -------------------- --------------------------- void display(){ // Wyczyść ekran i bufor Z glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Resetowanie transformacji glLoadIdentity(); // Inne przekształcenia // glTranslatef(0.1, 0.0, 0.0); // Nieuwzględnione // glRotatef(180, 0.0, 1.0, 0.0); // Nieuwzględnione // Obróć, gdy użytkownik zmieni rotate_x i rotate_y glRotatef(rotate_x, 1.0, 0.0, 0.0); glRotatef(obrót_y, 0.0, 1.0, 0.0); // Inne przekształcenia // glScalef(2.0, 2.0, 0.0); // Nieuwzględnione //Wielokolorowa strona - FRONT glBegin(GL_POLYGON); glColor3f(1.0, 0.0, 0.0); glVertex3f (0,5, -0,5, -0,5); // P1 jest czerwony glColor3f(0.0, 1.0, 0.0); glVertex3f (0,5, 0,5, -0,5); // P2 jest zielony glColor3f(0.0, 0.0, 1.0); glVertex3f (-0,5, 0,5, -0,5); // P3 jest niebieskie glColor3f(1.0, 0.0, 1.0); glVertex3f (-0,5, -0,5, -0,5); // P4 jest fioletowy glEnd(); // Biała strona - 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(); // Fioletowa strona - PRAWY 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(); // Zielona strona - LEWA 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(); // Niebieska strona - 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(); // czerwona strona - BOTTOM 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(); glutSwapBufory(); } // ----------------------------------------------- ----------- // specialKeys() Funkcja wywołania zwrotnego // ------------------------------ ---------------------------- void specialKeys(int key, int x, int y) { // Strzałka w prawo - zwiększ obrót o 5 stopień if (klucz == GLUT_KEY_RIGHT) obrót_y += 5; // Strzałka w lewo - zmniejsz obrót o 5 stopni w przeciwnym razie jeśli (key == GLUT_KEY_LEFT) rotate_y -= 5; inaczej if (klucz == GLUT_KEY_UP) rotate_x += 5; w przeciwnym razie if (klucz == GLUT_KEY_DOWN) rotate_x -= 5; // Poproś o aktualizację wyświetlania glutPostRedisplay(); } // ----------------------------------------------- ----------- // główna funkcja // ------------------------------- --------------------------- int main(int argc, char* argv){ // Zainicjuj GLUT i przetwórz parametry użytkownika glutInit(&argc, argv); // Zażądaj podwójnie buforowanego okna True Color z buforem Z glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Utwórz okno glutCreateWindow("Niesamowita kostka"); // Włącz test głębokości bufora Z glEnable(GL_DEPTH_TEST); // Funkcje zwrotne glutDisplayFunc(display); glutSpecialFunc(specialKeys); // Przekaż kontrolę do GLUT dla zdarzeń glutMainLoop(); // Powrót do systemu operacyjnego return 0; }