OpenGl, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab4


Co to jest OpenGL ?

OpenGL to API (Aplication Program Interface) "programowy interfejs sprzętu graficznego". Jest ot biblioteka przeznaczona do tworzenia trójwymiarowej grafiki, bardzo szybka, potężna i niesamowicie prosta w obsłudze. Równie wielką zaletą OpenGL jest przenośność kodu na inne platformy. OpenGL istnieje na wszystkich (no prawie) systemach operacyjnych. W OpenGL zastosowano technologie stworzone przez Silicon Graphics (SGI).

OpenGL jest przeznaczony do używania w systemach wyposażonych w sprzętowe akceleratory grafiki 3D wspomagające OpenGL. Istnieje także programowa biblioteka OpenGL, jednak ustępuje ona prędkością wersji sprzętowej i nie polecam jej używania. 

Kolejne wersje OpenGL pojawiają się raz na kilka lat. Nie oznacza to, że OpenGL nie oferuje nowych efektów. Jedną z ciekawszych możliwości OpenGL to rozszerzenia "GL EXTENSIONS". Najprościej mówiąc są to dodatki do standardowej biblioteki OpenGL dostarczone przez producentów chipów graficznych. 

Dla domowych systemów komputerowych dostępne jest wiele kart wspomagających generowanie grafiki przy pomocy biblioteki OpenGL. Producenci tacy jak NVidia, 3Dfx, S3, Matrox od dawna wyposażają swoje chipy graficzne w obsługę OpenGL. Według nas najlepszymi kartami do OpenGL są karty oparte na chipach firmy NVidia.

Dlaczego OpenGL?

Alternatywą dla OpenGL'a jest Microsoft DirectX 3D (Ale tylko dla Windows). Jednak OpenGL jest dużo lepszy. Pierwszy argument przemawiający za OpenGL'em to fakt iż jest on niezależny od platformy. Działa począwszy od specjalistycznych stacji graficznych SGI, poprzez system Unix a na MS Windows skończywszy. Istnieje też specjalna wersja dla MS DOS. Kolejnym argumentem jest zgodność wersji. OpenGL posiada dwie wersje (Mesa jest wersją 1.2) . DirectX zaś powstaje sezonowo. OpenGL ma jeszcze jedną przewagę nad DirectX 3D - wielkość. DirectX wyróżnia się tym, że obsługuje on nie tylko grafikę 3D, ale również dźwięk, sieć, grafikę 2D, obsługę urządzeń typu joystick. OpenGL też ma swoje przykre uroki : pierwszy to że wsparcie sprzętowe do OpenGL oferują nie wszystkie akceleratory i karty graficzne.

Dodatkowo można powiedzieć że najnowsza część Gwiezdnych wojen była robiona w części na stacjach graficznych SGI wykorzystujących OpenGL.

Podstawy programowania w OpenGL'u

Podstawową jednostką jest tzw. Vertex (wierzchołek). Określa on współrzędne pojedynczego wierzchołka płaskiego wielokąta. Są różne rodzaje Vertexów. np. glVertex2f pozwala wprowadzić współrzędne dwuwymiarowe a glVertex3f trójwymiarowe. Litera 'f' po liczbie określającej ilość składowych (2,3 lub 4 ) oznacza rodzaj zmiennych określających współrzędne : f to float i to int...

glVertex2i

int

płaszczyzna XY

glVertex3i

int

przestrzeń XYZ

glVertex3f

float

przestrzeń XYZ

glVertex3d

double

przestrzeń XYZ

glVertex2f

float

płaszczyzna XY

glVertex2d

double

płaszczyzna XY

Programując dane obiekty warto zwrócić uwagę iż podstawową figurą kreśloną przez akceleratory i karty 3D jest trójkąt. Warto więc scenę budować z trójkątów. Jeżeli użyje się innych figur to nic się nie dzieje ale akcelerator / karta 3D musi go wtórnie rozbić na trójkąty (np. kwadrat to dwa przystające trójkąty) co w bardzo małym stopniu pochłania moc obliczeniową. W przypadku dużych scen i słabego sprzętu ta mała utrata mocy może być już zauważalna.

Tworzenie brył 3D polega na definiowaniu wierzchołków ich boków. Ten sposób zapewnia możliwość utworzenia dowolnie skomplikowanego kształtu. Można też posłużyć się zdefiniowanymi w module GLU gotowymi bryłami (prostopadłościan, kula, itp.) Wymaga to utworzenia nowego obiektu . Wskaźnik do niego jest wartością typu int. Później bardzo łatwo można modyfikować parametry tak utworzonej bryły.

Na tak przygotowane wielokąty lub bryły nakłada się tekstury. Można je dostosować stosując mip-mapping (dostosowanie tekstury do wielkości /odległości/ wielokąta). Później można określić rodzaj materiału z którego ma być wykonany dany wielokąt (ma to wpływ na sposób odbijania światła). Można jeszcze określić współczynnik Alfa odpowiedzialny za przeźroczystość wielokąta. Na koniec warto scenę oświetlić kilkoma źródłami światła.

Trzeba jednak pamiętać że wszystkie te dodatki obciążają sprzęt.

Bardziej rozbudowane sceny najlepiej jest przygotować w jakimś edytorze 3D (może 3D Studio MAX ?) a następnie tak utworzoną mapę wczytać jako zewnętrzny dokument do programu który na podstawie takiej mapy będzie kreślić scenę. Przykładowy wygląd takiego najprostszego formatu pozwalającego zapisać scenę 3D wygląda tak jak w tabelce poniżej :

x1,y1,z1

3 x float (12 bajtów)

Współrzędne pierwszego wierzchołka trójkąta

x2,y2,z2

3 x float (12 bajtów)

Współrzędne drugiego wierzchołka trójkąta

x3,y3,z3

3 x float (12 bajtów)

Współrzędne trzeciego wierzchołka trójkąta

R,G,B

3 x float (12 bajtów)

Parametry koloru RGB pierwszego wierzchołka

R,G,B

3 x float (12 bajtów)

Parametry koloru RGB drugiego wierzchołka

R,G,B

3 x float (12 bajtów)

Parametry koloru RGB trzeciego wierzchołka

nr_txt

1 x float

Numer tekstury nakładanej na trójkąt

Takie rozwiązanie wymaga jednak napisania własnego konwertera znanych formatów 3D do przedstawionego powyżej.

Wszystkie obiekty trójwymiarowe w grach czy programach do tworzenia grafiki 3D zbudowane są z prymitywów (prostych obiektów). Tymi prymitywami są trójkąty i czworokąty. Większość programów korzysta z trójkątów, ponieważ algorytm rysowania trójkąta jest prostszy niż rysowania czworokąta a co za tym idzie jest szybszy !. Co więcej wszystkie karty 3D wspomagają rysowanie trójkątów.

W OpenGL mamy możliwość narysowania punktów, linii, trójkątów, czworokątów, innych prymitywów. My zajmiemy się trójkątami i czworokątami.

Aby narysować jakikolwiek prymityw należy skorzystać z funkcji glBegin(GL_NAZWAPRYMITYWU). Nazwą prymitywu może być GL_TRIANGLES - trójkąt, GL_QUADS - czworokąt. glBegin(GL_TRIANGLES) rozpocznie rysowanie trójkąta.

int DrawGLScene(GLvoid) // Tu rysujemy wszystko
{ // Wyczyść ekran i bufor głębokości
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     glLoadIdentity();// Powróć do początku układu współrzędnych
     glBegin(GL_TRIANGLES);  // Powiadom OpenGL, że rysujemy trójkąt

 
 

Jak wiemy trójkąt składa się z 3 wierzchołków. W OpenGL wierzchołek nazywa się vertex. Kiedy napiszemy glBegin(GL_TRIANGLES) musimy podać wierzchołki. Służy do tego funkcja glVertex3f(X, Y, Z), gdzie X, Y, Z to współrzędne naszego wierzchołka. Współrzędne podajemy w liczbach typu float.

     glVertex3f(1.0f, 1.0f, -4.0f); // wierzchołek (vertex) 1
     glVertex3f(0.0f, 0.0f, -4.0f); // wierzchołek (vertex) 2
     glVertex3f(-1.0f, 0.0f, -4.0f); // wierzchołek (vertex) 3

Po zakończeniu podawania wierzchołków / vertexów musimy powiadomić OpenGL, że kończymy rysowanie trójkąta. Służy do tego polecenie glEnd().

 glEnd();     // Powiadom OpenGl,
                  // że kończymy rysowanie trójkąta.
 return TRUE;
 }

 
 

UWAGA !! Każdy trójkąt ma dwie strony Przednią i Tylną.
Aby zmienić domyślne działanie OpenGL, możesz wywołać funkcje glFrontFace(GL_CW). Parametr GL_CW mówi OpenGl, żeby za odwrócone przodem były uważane trójkąty o kierunku zgodnym z ruchem wskazówek zegara. Powrót do kierunku przeciwnego jest uzyskiwany przez podanie parametru GL_CCW funkcji glFrontFace(). glFrontFace(GL_CCW) - Mówi OpenGL, że odwrócone przodem są trójkąty o kierunku przeciwnym do wskazówek zegara. Na razie te ustawienia nas nie interesują, ale np. przy włączeniu usuwania niewidocznych / tylnich powierzchni trójkąty zwrócone tyłem są nie rysowane !!.

Rysowanie czworokąta jest podobne do rysowania trójkąta. Piszemy glBegin(GL_QUADS) i podajemy współrzędne 4 wierzchołków czworokąta. Kończymy pisząc glEnd().

Tryby Wielokątów

Standardowo w OpenGL wielokąty rysowane są wypełnione domyślnym kolorem. Jak wiecie każdy wielokąt może być także texturowany (opisze Teksturowanie w dalszej części), mogą być rysowane tylko linie tworzące wielokąt, bądź same punkty (są wtedy rysowane tylko wierzchołki / vertexy).

Jeżeli chcemy zmienić tryb rysowania wielokąta musimy wywołać funkcje glPolygonMode(GL_PARAM1, GL_PARAM2). Pierwszy parametr określa dla której strony ustawiamy tryb rysowania. GL_FRONT - przednia strona, GL_BACK - tylna, GL_FRONT_AND_BACK - tylna i przednia jednocześnie. Drugim parametrem jest tryb rysowania GL_LINE - rysuje tylko linie zewnętrzne, GL_FILL - rysuje wypełniony wielokąt (musi być włączone, jeżeli chcemy używać texturowania, OpenGL ustawia to domyślnie), GL_POINT - rysuje punkty (wierzchołki / vertexy).

    glPolygonMode(GL_FRONT, GL_LINE) - rysuje przody wielokątów jako zewnętrzne linie .

Przesunięcia i obroty.

Jak dotąd wszystko co rysowaliśmy na ekranie znajdowało się w środku sceny i nie poruszało się ani się nie obracało. Oczywiście żeby uzyskać efekt przesunięcia możemy dodawać do współrzędnych prymitywów jakieś wartości.

W OpenGL  przesunięcia (translacje) i obroty (rotacje) wykonuje się inaczej. Załóżmy, że posiadając wiedzę z poprzednich przykładów zbudowaliśmy sześcian na środku ekranu. Teraz chcemy, aby ten sześcian znajdował się po lewej stronę ekranu, a nie na środku. Aby przesunąć nasz obiekt w lewo używamy funkcji glTranslatef(X, Y, Z). X, Y, Z mówi OpenGL ile jednostek po osiach chcemy się poruszać. Dla przypomnienia X porusza w "lewo i prawo", Y "z góry na dół", a Z "w głąb sceny". Chcemy narysować  obiekt przesunięty o jedną jednostkę w lewo. Stoimy w punkcie 0,0,0 - początek układu współrzędnych. Wywołujemy glTranslatef(-1.0f, 0.0f, -0.0f) potem rysujemy nasz obiekt i gotowe !!!. (-1.0 przesunie obiekt w lewo o 1.0 jednostek, a 1.0 przesunie obiekt w prawo o 1.0 jednostek).

int DrawGLScene()
{
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Czyścimy Ekran i Bufor Głębokości
        glLoadIdentity();                                                                                // Powracamy do początku układu wsp.

        glTranslatef(-1.0f, 0.0f, 0.0f);                                                             // Przesuwamy się e lewo o 1.0
        RysujSześcian();                                                                                // Wywołujemy naszą funkcję rysującą.

        return TRUE;
}

Obroty są równie proste. Do obracania obiektami służy funkcja glRotatef(Kąt, X, Y, Z). X, Y, Z - oznacza po której osi będziemy się obracać. Kąt - o jaki kąt ma być obrót.

Chcemy obrócić nasz obiekt wokół osi Y o kąt 12.0f. Wykona to polecenie glRotatef(12.0f, 0.0f, 1.0f, 0.0f). Pewnie zastanawiasz się dlaczego w miejsce X, Z wpisaliśmy 0.0f a w Y 1.0f ?. To bardzo proste !!!. Wpisując wartość 1.0f w X, Y lub Z powiadamiamy OpenGL po jakiej osi ma być obrót. W naszym przypadku po osi Y, więc piszemy 1.0f w miejsce Y. Można także stosować kombinacje glTranslatef(1.0f, 1.0f, 0.0f, 12.0f) - obróci po osiach X, Y o 12.0f na każda z osi, glTranslatef(0.0f, 1.0f, 1.0f, 45.0f) - obróci po osiach Y, X o 45.0f, itd.

int DrawGLScene()
{
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Czyścimy Ekran i Bufor Głębokości
        glLoadIdentity();                                                                                // Powracamy do początku układu wsp.

        glTranslatef(-1.0f, 0.0f, 0.0f);                                                             // Przesuwamy się e lewo o 1.0
        glRotatef(12.0f, 0.0f, 0.0f, 1.0f);                                                        // Obrót o 12.0 jednostek
        RysujSześcian();                                                                                // Wywołujemy naszą funkcję rysującą.

        return TRUE;
}

 
 

Wszystkie operacje translacji i rotacji MUSZĄ być wywołane przed narysowaniem obiektu, ale to chyba oczywiste.

UWAGA !!! Kolejność wywołania tych funkcji ma duże znaczenie !!!. Jeżeli wywołamy glRotatef() przed glTranslatef() to obiekt się obróci i jednocześnie obrócą się współrzędne !!!!. Teraz X, Y, Z nie będą wskazywały tam gdzie na początku i translacja o jakąś wartość po osiach  może umieścić obiekt nie tam gdzie chcemy !!!!.

Napisaliśmy prawidłowe i nie prawidłowe w cudzysłowiu, ponieważ czasami potrzeba zrobić translacje i obrót właśnie w ten nietypowy sposób.

Kolory

W poprzednich przykładach nauczyliśmy się rysować i przemieszczać w scenę obiekty. Czegoś tym obiektom brakowało? Tym czymś jest kolor i textura. Najpierw zajmiemy się kolorem.

W OpenGL do ustawiania wartości kolory używamy funkcji glColor<x><t>().

<x> - liczba parametrów,

<t> typ parametru.

My będziemy korzystać z funkcji:

glColor3f(float red, float green, float blue),

glColor3ub(unsigned byte red, unsigned byte gren, unsigned byte blue).

f - oznacza float, a ub - unsigned byte.

Podając wartości kolorów podajemy 3 składniowe czerwoną - red, zieloną - green i niebieską - blue. Dla glColor3f() 1.0f to maksymalna (najjaśniejsza) wartość składniowej koloru, a dla glColor3ub() 255 to maksymalna wartość. Jeżeli chcemy ustawić kolor na biały wywołujemy glColor3f(1.0f, 1.0f, 1.0f) lub glColor3ub(255, 255,255). Niebieski kolor uzyskamy przez glColor3f(0.0f, 0.0f, 1.0f) lub glColor3ub(0, 0, 255). Inne kolory uzyskujemy tak samo jak poprzednie, czyli przez dowolne mieszanie składowych koloru.

Istnieją także inne wersje tej funkcji. Np. glColor4f(red, green, blue, alpha), glColor4ub(red, green, blue, alpha)  gdzie alpha to przeźroczystość koloru (zajmiemy się tym w późniejszych przykładach, teraz podaje to jako ciekawostkę).

Nadając kolor prymitywom warto też wspomnieć o modelu cieniowania. Cieniowanie to jest metoda z jaką masz kolor zostanie nałożony na prymityw. Do zmiany cieniowania służy glShadeModel(GL_PARAM), gdzie GL_PARAM to GL_FLAT - cieniowanie płaskie, GL_SMOOTH - cieniowanie płynne. Cieniowanie płaskie oznacza wypełnienie jednolitym kolorem całego prymitywu, a cieniowanie płynne tworzy płynne przejścia kolorów pomiędzy wierzchołkami wielokąta. Najlepiej zilustrują to obrazki.  Przy cieniowaniu płaskim kolor wypełnienie brany jest z ostatniego wywołania funkcji glColor(). Przy cieniowaniu płynnym, każdy z vertexów może mieć inny kolor.

int DrawGLScene(GLvoid)      // Tu rysujemy wszystko
{
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //Wyczyść ekran i bufor głębokości
     glLoadIdentity();                                                                         // Powróć do początku układu współrzędnych

     glShadeModel(GL_SMOOTH);                                                  // Typ Cieniowania Płynny
     glBegin(GL_TRIANGLES);                                                        // Powiadom OpenGL, że rysujemy trójkąt

     glVertex3f(1.0f, 1.0f, -4.0f);                                                        // wierzchołek (vertex) 1
     glColor3ub(255, 0, 0);                                                                // czerwony
     glVertex3f(0.0f, 0.0f, -4.0f);                                                        // wierzchołek (vertex) 2
     glColor3ub(0, 255, 0);                                                                // zielony
     glVertex3f(-1.0f, 0.0f, -4.0f);                                                      // wierzchołek (vertex) 3
     glColor3ub(0, 0, 255);                                                                // niebieski

     glEnd();                                                                                      // Powiadom OpenGl, że kończymy
                                                                                                          // rysowanie trójkąta.

     return TRUE;
}

Przy cieniowaniu płaskim (GL_FLAT) kolor ustawia ostatnie wywołanie funkcji glColor().

0x01 graphic

int DrawGLScene(GLvoid)                                                              // Tu rysujemy wszystko
{
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  //Wyczyść ekran i bufor głębokości
     glLoadIdentity();                                                                         // Powróć do początku układu współrzędnych

     glShadeModel(GL_FLAT);                                                         // Cieniowanie Płaskie

     glBegin(GL_TRIANGLES);                                                        // Powiadom OpenGL, że rysujemy trójkąt

     glVertex3f(1.0f, 1.0f, -4.0f);                                                        // wierzchołek (vertex) 1
     glColor3ub(255, 0, 0);                                                                // czerwony
     glVertex3f(0.0f, 0.0f, -4.0f);                                                        // wierzchołek (vertex) 2
     glColor3ub(0, 255, 0);                                                                // zielony
     glVertex3f(-1.0f, 0.0f, -4.0f);                                                      // wierzchołek (vertex) 3
     glColor3ub(0, 0, 255);                                                               // niebieski

     glEnd();                                                                                     // Powiadom OpenGl, że kończymy rysowanie trójkąta.
                                                                                                      // Trójkąt będzie niebieski, ponieważ ostatnie
                                                                                                         // wywołanie glColor() ustawia Niebieski kolor
                                                                                                         // a cieniowanie jest płaskie (GL_FLAT).
     return TRUE;
}
0x01 graphic

Teksturowanie

Teksturowanie to naciąganie obrazu (mapy bitowej) na prymityw. Dzięki teksturowaniu możemy stworzyć bardzo realistyczne obiekty / sceny. Możemy np. stworzyć stół i pokryć go teksturą zawierającą ze skanowany wzór drewna. Na pewno taki obiekt będzie lepiej wyglądał niż obiekt cały pokryty brązowym kolorem, który miał imitować drewno.

Tekstury w OpenGL muszą mieć wysokość i szerokość równą jakiejś potędze dwójki. Minimalnym rozmiarem tekstury jest 64x64. Dalsze formaty zależą od waszej karty 3D. Często pojawia się problem, gdy używa się tekstur większych niż 256x256 np. 512x512. Wtedy zamiast tekstury na prymitywie pojakia sie jednolity kolor. Wynika to z tego, ze nasza karta 3d obsługuje tekstury o maksymalnym rozmiarze 256x256. Takie ograniczenia są na wszystkich chipach 3DFX. Proponuję zmianę karty na jakaś NVidia Riva TNT/ TNT 2, G-Force 256 lub korzystanie z textur o rozmiarze maksymalnym 256x256 .

Żeby korzystać z texturowania trzeba je włączyć. Służy do tego funkcja glEnable(GL_TEXTURE_2D). glEnable() służy do włączania różnych rzeczy w OpenGL.

Aby wyłączyć teksturowanie korzystamy z glDisable(GL_TEXTURE_2D). GL_TEXTURE_2D - mówi OpenGL, że będziemy używać textur dwu wymiarowych (standardowych obrazów). Można jeszcze korzystać z textur jedno wymiarowych, ale w naszych przykładach wykorzystujemy tekstury 2D.

W OpenGl tekstury przechowywane są w zmiennych typu GLuint.

GLuint texture[1];  // zmienna dla naszej tekstury.

Następnie mówimy OpenGL, że chcemy wygenerować 1 texture i nadać jest właściwości texture dwu wymiarowej.

glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);

W celu zdefiniowania tekstury 2D należy wywołać funkcje glTextImage2D().

glTexImage2D(GLenum target, GLint level, GLint components,
                    GLSize width, GLsize height, GLint border,
                    GLenum format, GLenum type, const GLvoid *pixels)

Parametr :


glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmap_pixels);

Teraz mówimy OpenGL jakiego rodzaju filtrowanie chcemy użyć.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

Gotowe !!! Mamy w zmiennej texture[0] nasz obraz tekstury z pliku graficznego.

Żeby naciągnąć texture na prymityw musimy każdemu z wierzchołków prymitywu podać współrzędne tekstury. Służy do tego

glTexCord2f(TYPE s, TYPE t);

s, t - współrzędne tekstury. glTExCord3f(0.0f, 0.0f) - dolny lewy róg tekstury, glTexCord2f(1.0f, 1.0f) - górny prawy róg tekstury, glTexCord2f(0.0f, 1.0f) - dolny prawy róg tekstury, glTexCord2f(1.0f, 0.0f) - Górny lewy róg tekstury.

Złóżmy teraz to wszystko do kupy. Napiszemy funkcje odczytującą pliki *.bmp (muszą być to bitmapy z 3 składniowymi kolory - RGB), potem wgramy texture i naciągniemy ją na Czworokąt.

Teraz potrzebujemy odczytać obraz tekstury z jakiegoś pliku graficznego np. *.BMP (bo jest najprostszy).

AUX_RGBImageRec *LoadBMP(char *Filename)                // Wgrywa plik *.BMP
{
        FILE *File=NULL;

        if (!Filename)                                                                // Jeżeli łańcuch znaków Filename jest pusty
       {
                return NULL;                                                       //
Zwróć NULL
       }

  File=fopen(Filename,"r");                                                    // Otwieramy plik do odczytu

  if (File)                                                                                 // Sprawdzamy czy plik istnieje
        {                                                                                  // Jeżeli istnieje to :
                fclose(File);                                                            // Zamykamy plik
                return auxDIBImageLoad(Filename);                      // Wgrywamy Bitmape i zwracamy wskaźnik
        }

   return NULL;                                                                    // Zwracamy NULL, bitmapa nie wgrana !!!
}

int LoadTexture()
{
   int Status=FALSE;                                                            // Będziemy sprawdzali czy wystąpił jakiś błąd.
   AUX_RGBImageRec *TextureImage[1];                          // Tu przechowujemy obraz z pliku *.bmp

   if (TextureImage[0]=LoadBMP("Data\\texture.bmp"))
   {

          glGenTextures(1, &texture[0]);                                    // Tworzymy / Generujemy texture
          glBindTexture(GL_TEXTURE_2D, texture[0]);

            glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); // Ustawiamy parametry textury (wysokosc, szerokosc, ... )

           glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
           glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

          Status=TRUE;                                                            // Wszystko O.K
   }

 if(TextureImage[0 // Jeżeli istnieje zaalokowana pamięc dla danych z pliku *.BMP
  {
           if(TextureImage[0]->data)                                         // Jeżeli istnieją dane o obrazie
          {
              delete[]  TextureImage[0]->data;                          // usuń dane o obrazie z pamięci i zwolnij ją
          }
         delete TextureImage[0];                                            // usuń i zwolnij pamieć dla danych z pliku *.BMP
 }

 if(!Status) return FALSE;                                                  // Jeżeli gdzieś wystąpił bład zwróć FALSE

 return TRUE;                                                                   // Wszystko O.K
}

int InitGL(GLvoid)                                                             // Ustawiamy OpenGL
{

 glShadeModel(GL_SMOOTH);                                    // Płynne cieniowanie
 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                                // CZarne tło
 glClearDepth(1.0f);                                                           // CZycimy bufor głębokoci
 glEnable(GL_DEPTH_TEST);                                         // Włączamy testowanie głebokoci
 glDepthFunc(GL_LEQUAL);                                        // Typ testowania głębokoci
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Korekcja perspektywy

 if(!LoadTexture())                                                            // Wgrywamy tekstury
 {
  exit(0);                                                                         // Jak bład podczas wgrywania to spadamy do win32
 }

 glEnable(GL_TEXTURE_2D);                                        // włączamy Teksturowanie 2D.

 return TRUE;                                                                   // Wszystko O.K
}

Solidne Obiekty

Do tej pory wszystkie obiekty jakie rysowaliśmy były to obiekty 2D rysowane w 3D przestrzeni. Teraz nadszedł czas na zbudowanie z prymitywów jakiegoś obiektu 3D. Teraz zbudujemy stożek. Do tego użyjemy oczywiście trójkątów.

Budując obiekt 3D musimy pamiętać, aby zaprojektować go wokół środka osi współrzędnych, czyli punktu 0,0,0. W innym wypadku nasz obiekt nie będzie zachowywał się poprawnie przy obrotach i przesunięciach !. Tworząc ten stożek narysowaliśmy go sobie na kartce papieru i dokładnie w środku stożka umieściliśmy punkt 0,0,0. Z rysunkiem pod ręką jest o wiele łatwiej pisać kod budujący nasz obiekt. Jak nauczycie się odczytywać format obiektów np. z 3DStudio to nie musicie martwić się o poprawność obiektu, ponieważ 3DStudio buduje obiekty właśnie wokół 0,0,0. Żeby nasz obiekcik przesuwać po scenie wystarczy użyć funkcji glTranslatef() a potem narysować nasz obiekcik. To Proste. Poniżej znajdziecie kod rysujący stożek.

int DrawGLScene(GLvoid)
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Czyścimy Ekran i bufor głębokości
 glLoadIdentity();                                                                                 // Przenosimy się do początku układu współrzędnych

 glColor3ub(255, 255, 255);                                                                // Ustawiamy kolor rysowania na Biały
 

 glTranslatef(-1.0f, 0.0f, -4.0f);
 glRotatef(kat,0.0,1.0,0.0);

 glBegin(GL_TRIANGLES);                                                             // Mówimy OpenGL, że rysujemy trójkąty
       glVertex3f(-1.0f, -1.0f, 0.0f);                                                    // wierzchołek 1
       glColor3ub(64, 64, 255);                                                          // Ustawiamy kolor rysowania
       glVertex3f(1.0f, -1.0f, 0.0f);                                                      // wierzchołek 2
       glColor3ub(255, 64, 64);                                                           // Ustawiamy kolor rysowania
       glVertex3f(0.0f, 1.0f, 0.0f);                                                        // wierzchołek 3
  glEnd();                                                                                            // Koniec rysowania trójkąta
 

 glBegin(GL_TRIANGLES);
        glColor3ub(64, 64, 255);                                                         // Ustawiamy kolor rysowania
        glVertex3f(1.0f, -1.0f, 0.0f);                  //
wierzchołek 1
        glVertex3f(0.0f, -1.0f, -1.0f);                                                    // wierzchołek 3
        glColor3ub(255, 64, 64);                                                          // Ustawiamy kolor rysowania
        glVertex3f(0.0f, 1.0f, 0.0f);                                                       // wierzchołek 3
 glEnd();                                                                                           // Koniec rysowania trójkąta

 glBegin(GL_TRIANGLES) ;
        glColor3ub(64, 255, 64);
        glVertex3f(0.0f, -1.0f, -1.0f);                                                  // wierzchołek 3
        glVertex3f(-1.0f, -1.0f, 0.0f);                                                 // wierzchołek 3
        glColor3ub(255, 64, 64);                                                        // Ustawiamy kolor rysowania
        glVertex3f(0.0f, 1.0f, 0.0f);                                                     // wierzchołek 3
 glEnd();                                                                                        // Koniec rysowania trójkąta
 return TRUE;
}

OPEN GL

- 15 -

OPEN GL

Dariusz Kowalski

Krzysztof Waszkiewicz

- 1 -



Wyszukiwarka

Podobne podstrony:
sprawozdanie3, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab4
Zadania L3 I6X4S1, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab4
Zadania L4 I6Y4S1, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab4
Opała GK sprawozdanie lab4, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab4
Zadania L4 I6Y3S1, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab4
SPR-ANKI, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab2
sprawozdanie oswietlenie, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab3
KWADRYKI, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab2
Zadania L3 I6Y3S1, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab3
tresc lab3 gk, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab3
sprawko-pieci, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab2
Zadania L2 I6Y3S1, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab2
Zadania L3 I6Y4S1, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab3
sprko-pieci, Studia, WAT Informatyka, s3 - GK - lab grafika komputerowa, Lab3
Zadanie IY4S1, Studia, WAT Informatyka, s3 - GK - grafika komputerowa, LAB2
Rzezba Lab4, Studia, WAT Informatyka, s3 - GK - grafika komputerowa, LAB4
GK LAB3, Studia, WAT Informatyka, s3 - GK - grafika komputerowa, LAB4
Zadania I1Y3S1, Studia, WAT Informatyka, s3 - GK - grafika komputerowa, LAB4

więcej podobnych podstron