Witaj w 9. tutorialu. W tej chwili powinieneś już bardzo dobrze rozumieć OpenGL. Nauczyłeś się wszystkiego od tworzenia okna dla OpenGL po mapowanie tekstur na obracającym się obiekcie podczas używania oświetllenia i przezroczystości (alpha blendingu). To będzie pierwszy zaawansowany tutorial, w którym nauczysz się jak poruszać bitmapy po ekranie w 3D, usuwać czarne piksele wokół bitmapy (używając blendingu), dodawać kolor do czarnobiałej tekstury i na końcu, nauczysz się jak stworzyć fantazyjne kolory i prostą animację przez mieszanie różnokolorowych tekstur.
W tym turorialu będziemy modyfikować kod z pierwszej lekcji. Na początek dodamy kilka zmiennych na początku programu. Przepiszę całą sekcję kodu aby było łatwiej zobaczyć wprowadzane zmiany.
Następujące linie są nowe. twinkle i tp są zmiennymi typu BOOL co oznacza że mogą przyjmować tylko wartości TRUE albo FALSE (prawda albo fałsz). twinkle będzie informować czy aktywny jest efekt migotania (twinkle effect). tp będzie zawierać informację czy klawisz 'T' został wciśnięty albo puszczony (wciśnięty tp=TRUE, puszczony [itp[/i]=FALSE).
num będzie zawierać ilość gwiazd, które narysujemy na ekranie. Jest zdefiniowane jako stała, co oznacza ze nie zostanie zmienione w żadnym miejscu w kodzie. Powodem dla którego definiujemy ją jako stałą jest to że nie mozna zdefiniować ponownie tablicy więc jeśli ustawiliśmy tablicę na 50 i zdecydujemy na zwiększenie ilości gwiazd do 51 to pojawi się błąd, bo tablica nie może zwiększyć się do 51. Jeśli chcesz, możesz zmienić liczbę gwiazd TYLKO w tej linii. Nie próbuj zmieniać wartości num później jeśli nie chcesz doprowadzić do katastrofy.
Teraz stworzymy strukturę. Słowo struktura brzmi może troche strasznie ale nie jest takie naprawdę. Struktura to grupa prostych danych (zmiennych, itp.) reprezentujących większą grupę. Zobaczysz, że 7. linia kodu poniżej zawiera 'stars;'. Wiemy że każda gwiazda będzie miała 3 wartości dla koloru i wszystkie te wartości będą typu całkowitego (integer). Trzecia linia 'int r, g, b' tworzy 3 zmienne typu całkowitego. Jedną dla składowej czerwonej (r), jedną dla zielonej (g) i jedną dla niebieskiej (b). Wiemy że każda gwiazda będzie w różnej ogległości od środka ekranu i może być umieszczona pod kątem od 0 do 360 stopni. W 4. lini kodu niżej tworzymy wartość zmiennoprzecinkową nazwaną dist. Ta zmienna będzie przechowywała odległość od śreodka ekranu. Piąta linia tworzy zmienną zmiennoprzecinkową angle, w której będzie przechowywany kąt.
Następnie ustawiamy zmienne definiujące jak daleko od gwiazd stoi oglądający (zbliżenie [zoom]), i pod jakim kątem oglądamy gwiazdy (nachylenie [tilt]). Tworzymy zmienną spin, która będzie obracać migające gwiazdy wokół osi Z dzieki czemu będzie to wyglądać jakby obracały się na ich aktualnych pozycjach.
loop to zmienna, którą będziemy używać w programie aby narysować wszystkie 50 giwazd, a texture[1] będzie użyte w celu przechowania czarnobiałej tekstury którą załadujemy. Jeśli chcesz więcej tekstur to zmien ilość tekstur z 1 na tyle ile chcesz uzyć.
Zaraz po powyższym dodamy kod, który załaduje naszą teksturę. Nie muszę tłumaczyć tego kodu z wielkimi detalami. Jest to ten sam kawałek kodu który użyliśmy aby załadować tekstury w lekcji 6, 7 i 8. Bitmapa którą tym razem załadujemy nazywa się star.bmp. Wygenerujemy tylko jedną teksturę używając glGenTextures(1, &texture[0]). Tekstura będzie filtrowana liniowo.
To jest sekcja, która ładuje bitmapę (używając powyższego kodu) i konwertuje ją na tekstury. Status jest uzyte do okreslenia czy tekstura została załadowana.
Teraz ustawimy OpenGL aby renderował tak jak chcemy. Nie zamierzemy używać Testowania Głębokości (Depth Test) w tym projekcie, więc upewnij się że używasz kodu z lekcji pierwszej z usuniętym glDepthFunc(GL_LEQUAL); i glEnagle(GL_DEPTH_TEST); w innym przypadku efekty nie będą przyjemne dla oka. Używamy mapowania tekstur wiec włączymy je razem z mieszaniem (blending).
Następujący kod jest nowy. Ustawia początkowy kąt, odległość i kolor dla każdej gwiazdy. Zauważ jak łatwo jest zmieniać informacje w strukturze. Pętla przerobi wszystkie 50 gwiazd. Aby zmienić kąt gwiazdy star[1] wszystko co musimy zrobić to napisać star[1].angle={jakiś numer}. To takie proste!
Obliczam odległość przez wzięcie aktualnej gwiazdy (ktrórej indeks to loop) i podzielenie jej przez maksymalną ilość gwiazd. Wtedy mnożę wynik przez 5.0f. W ten sposób każda gwiazda jest lekko przesunięta w stosunku do poprzedniej . Kiedy loop osiągnie wartość 50 (ostatnia gwiazda), loop podzielone przez num da wynik 1.0f. Powodem dla którego mnożę przez 5.0f jest to że 1.0f*5.0f = 5.0f, a 5.0f jest odległością brzegu od śdodka. Nie chcę żeby gwiazdy były poza ekranem wiec 5.0f jest dobre. Jeśli ustawisz zoom bardziej w kierunku ekranu możesz użyć wiekszej liczby niż 5.0f, ale Twoje gwiazy będą znacznie mniejsze (przez perspektywę).
Zauważysz że kolor każdej z gwiazd stworzony jest z losowych wartości od 0 do 255. Pewnie się zastanawiasz jak możemy użyć tak duże wartości kiedy normalnie kolory są z przedziału od 0.0f do 1.0f. Kiedy będziemy ustawiać kolor użyjemy glColor4ub zamiast glColor4f. ub znaczy Unsigned Byte (nieznakowany bajt). Bajt może przyjmować wartości tylko od 0 do 255. W tym programie łatwiej jest używać bajtów niż tworzyć losowe wartości zmiennoprzecinkowe.
Kod zmieniania rozmiaru jest taki sam więc go ominiemy i przeskoczymy od razu do kodu rysującego. Jeśli używasz kodu z pierwszej lekcji, usuń funkcję DrawGLScene i wklej tą która jest poniżej. W lekcji pierwszej są tylko 2 linijki kodu więc nie ma specjalnie dużo do usuwania.
Teraz poruszymy gwiazdę. Gwiazda znajduje się teraz w środku ekranu. Pierwszą rzeczą jaką zrobimy jest obrót sceny wokół osi Y o 90. Jeśli obrócimy o 90 stopni, to oś X nie będzie już biegła od lewej do prawej tylko od ekranu wgłąb sceny. Jako przykład aby pomóc zrozumieć. Wyobraź sobie że jestes w centrum jakiegoś pokoju. Teraz wyobraź sobie że na lewej ścianie jest napisane -x, na ścianie przed Tobą jest -z, na prawej ścianie jest +x, a na ścianie za Tobą jest +z. Jeśli pokój obróci się o 90 stopni w prawo, ale bez Ciebie, na ścianie przed Tobą będzie teraz napis -x. Wszystkie ściany się przemieściły. -z będzie po prawej, +z po lewej, a +x za Tobą. Ma sens? Przez obrót sceny, zmieniamy kierunek płaszczyzn x i z.
Następna linijka przemieszcza gwiazdę w dodatnią stronę osi X. Normalnie dodatnia wartość na osi X przesunęłaby gwiazdę w prawą stronę ekranu (gdzie znajduje sie domyslnie +x), ale obrócilismy układ i teraz +x moze być wszędzie. Jeśli obrócimy o 180 stopni to +x będzie po lewej stronie ekranu zamiast po prawej. Kiedy przesuniemy gwiazdę na stronę dodatnią osi X moze ona przemieszczać się w którąkolwiek stronę.
Teraz bedzie chytry kod. Gwiazda jest właściwie tylko płaską teksturą. Jeśli narysujesz czworokąt w środku ekranu i oteksturujesz ją to będzie wyglądała dobrze. Będzie zwrócona przodem do Ciebie tak jak powinna, ale jeśli obrócisz układ o 90 stopni wokół osi Y, tekstura bedzie zwrócona w prawo, a wszystko co zobaczysz to będize cienka lnia. Nie chcemy aby tak się stało. Chcemy aby gwiazdy były zwrócone w naszą strone przez cały czas niezależnie od tego o ile obrócimy układ i jak zmienimy nachylenie.
Nasz cel osiągniemy przez anulowanie rotacji które zrobiliśmy tuż przed narysowaniem gwiazdy. Musisz anulować rotacje w odwrodtnej kolejności. Najpierw nachyliliśmy ekran, a potem obracaliśmy układ o kąt zawarty w strukturze gwiazdy. W odwrotnej kolejności najpierw anulujemy obrót, a potem nachylenie. Aby to zrobić użyjemy wartości przeciwnych danych kątków i obrócimy o te kąty układ. Jeśli obrócilismy gwiazdę o 10 stopni to obrót o -10 stopni sprawi, że gwiazda będzie zwrócona do nas przodem na danej osi. Pierwsza linia poniższego kodu anuluje rotacje na osi Y. W nastepnej linii musimy anulować nachylenie na osi X. Aby to zrobić musimy obrócić układ o -tilt. Po tym jak anulujemy te obroty gwiazda będzie zwrócona w naszą stronę całkowicie.
Jeżeli twinkle jest ustawione na TRUE, to bedziemy rysować nieobracające się gwiazdy na ekranie. Aby osiągnąć inny kolor weźmiemy maksymalną ilośc gwiazd(num) i odejmiemy numer aktualnej gwiazdy (loop), a nastepnie odejmiemy jeszcze 1 ponieważ loop w pętli przyjmuje wartości od 0 do num-1. Jeśli wynik byłby 10 to użylibyśmy koloru z gwiazdy numer 10. W ten sposób kolor dwóch gwiazd jest zazwyczaj inny. Nie jest to najlepszy sposób na zrobienie tego ale za to jest efektywny. Ostatnia wartość to wartość alpha. Im niższa wartość, tym ciemniejsza będzie gwiazda.
Jeśli miganie jest włączone to kazda gwiazda będzie rysowana podwójnie. To spowolni troche komputer w zależności od tego jakim komputerem dysponujesz. Jeśli miganie będzie włączone to kolory dwóch nakładających się gwiazd będą mieszane ze sobą tworząc naprawde fajne kolory.
Zauważ jak łatwo jest dodać kolor do tekstury. Nawet jeśli tekstura jest czarnobiała to po wyswietleniu na ekranie bedzie miala wybrany kolor. Zwróć też uwagę na to że używamy kolorów z przeciałów 0-255 niz 0.0f-1.0f.
Teraz narysujemy główną gwiazdę. Jedyna różnica od kodu powyżej jest taka, że ta gwiazda jest rysowana zawsze i kręci się wokół osi Z.
Teraz napiszemy cały ruch. Obracamy normalne gwiazdy poprzez zwiększanie wartości spin. Następnie zmieniamy kąt kazdej gwiazdy. Kąt każdej z nich jest zwiększany o loop/num, co powoduje ze gwiazdy będące dalej od środka kręcą się szybciej, a te które są blisko - wolniej. Na końcu zmniejszamy odległość każdej gwiazdy od środka ekranu. To sprawia ze wygladaja jakby srodek ekranu je przyciągał.
Linie ponizej sprawdzają czy któraś z gwiazd nie osiągnęła środka ekranu. Jeśli tak to dostaje ona nowy kolor i znów odsuwana jest o 5 jednostek od środka tak aby mogła zacząć swoją podróż jako nowa gwiazda.
Teraz dodamy kod do sprawdzenia czy został wciśnięty jakiś klawisz. Znajdź funkcję WinMain(), a w niej linijkę SwapBuffers(hDC). Dodamy nasz kod zaraz pod tą linią.
Kod poniżej sprawdza czy klawisz 'T' nie został wciśnięty. Jeśli tak i nie był wcisnięty wczesniej to włączy lub wyłączy miganie gwiazd oraz ustawia tp na TRUE co zapobiega powtarzaniu wykonywania kodu bez przerwy dopoki wcisniety jest klawisz 'T'.
Poniższy kod sprawdza czy klawisz 'T' został puszczony i jeśli tak to ustawia tp na FALSE. Naciskanie klawisza 'T' nic nie da dopóki tp jest równe FALSE, więc ta sekcja kodu jest bardzo ważna.
Reszta kodu sprawdza czy któraś ze strzałek (w górę, w dół, w prawo, w lewo) nie została wciśnięta.
Tak jak we wszystkich poprzednich tutorialach, upewnij się że tytuł głównego okienka jest prawidłowy.
W tym tutorialu próbowałem porządnie wytłumaczyć jak załadować bitmapę w skali szarości, usunąć czarny obszar dookoła niej (używając mieszania [blendingu]), dodać kolor do obrazka i poruszać obrazek po ekranie w świecie 3D. Pokazałem Ci także jak stworzyć piękne kolory i animacje poprzez nakładanie kopii bitmapy na oryginalną bitmapę. Jeśli raz zrozumiesz to czego Cię nauczyłem do tej pory, nie powinieneś mieć żadnych problemów z tworzeniem dem (przyp. tłumacza: animacji) w 3D na własną rękę. Wszystkie podstawy zostały przedstawione!