Open GL Pierwszy program

background image

Open GL - Pierwszy program

Parametry:
Dodany:
2006-04-01 przez

!Reg

Autor: Wojciech Dudek
Opis: Jak powinien wyglądać szablon applikacji wykożystującej biblioteke OpenGL

Poziom:

Ocena: 22,8

Autor: Wojciech Dudek

Wstęp, czyli po co komu ten artykuł Opisy Open GL można znaleźć w wielu miejscach (książki, pliki z sieci itp.). W większości jednak są
one albo bardzo nieprecyzyjne, albo bardzo szerokie, co skutecznie do nich zniechęca osoby chcące zacząć zabawę z grafiką 3D. W tym
artykule chcę przedstawić podstawowy program w standardzie GL, od jakiego powinno się zaczynać. Konkretnie, bez zbytniego wgłębiania się
opiszę, jak zbudować pierwszą aplikację korzystającą z Open GL. Uwierzcie mi 90% rozbudowanych programów w GL opiera się na niej. W
opisie tym nie ma podanych nagłówków funkcji wraz z opisem, zakładam, że każdy coś na ten temat ma. Są za to dość dokładnie opisane
kolejne kroki przykładowego programu. Mam nadzieję, że artykuł będzie pomocą w rozpoczęciu programowania w Open GL.

1. Co jest potrzebne do pisania programów w Open GL

Kompilator języka C/C++ generujący kod 32 bitowy, czyli po ludzku taki, na którym można tworzyć programy pod Win 95 (lub
nowszym),
Biblioteki statyczne Open GL: opengl32.lib i glu32.lib,
Pliki nagłówkowe Open GL: gl.h i glu.h,
W systemie MUSI znajdować się sterownik Open GL o nazwie opengl32.dll i biblioteka pomocnicza glu32.dll. Mogą być w katalogu
programu, albo w podkatalogu Windows'a /System,
Bardzo zalecany byłby akcelerator 3D, chociaż nie jest konieczny.
Wszystko to (oprócz bibliotek .dll) jest w pliku do tego artykułu gl.rar. [Niestety plik zaginął - przyp. redakcja]

Uwaga 1: Biblioteki statyczne (lib) są różne dla Borland C++ i Visual C++. Są w podkatalogach: /libBOR i /libVC.
Uwaga 2: Sterownik opengl32.dll dla niektórych kart może mieć inną nazwę. No cóż, trzeba poeksperymentować (np. skopiować go do
katalogu programu i zmienić nazwę).

2. Szkielet programu w Open GL

Głównym plikiem programu jest gl.cpp.
Jest to standardowy program pod Win 95, w API.
Jest funkcja WinMain:

int

WINAPI WinMain(HINSTANCE Zad,HINSTANCE, LPSTR,

int

To)

która inicjuje okno i rozpoczyna cykl obsługi komunikatów.

W programie Open GL we właściwościach okna należy wpisać: WS_CLIPCHILDREN i WS_CLIPSIBLINGS, zalecam też WS_POPUP,
czyli pracę na pełnym ekranie.

Dalej znajduje się funkcja która obsługuje komunikaty:

LRESULT CALLBACK ProcOkna(HWND Okno,UINT Kom,WPARAM WP,LPARAM LP)

Interesują nas zdarzenia: . Rozpoczęcie programu: WM_CREATE, . Naciśnięcie klawisza: WM_KEYDOWN, . Zmiany rozmiaru okna:
WM_SIZE, . Zakończenia programu: WM_DESTROY, . Odrysowywania zawartości okna: WM_PAINT.

Program Open GL podczas rozpoczęcia programu inicjuje pewne rzeczy (o tym dalej). Odrysowanie zawartości okna to najlepsza część
programu (GL rendering). Musimy wychwycić naciśnięcie klawiszy: kursorów, Entera i Esc. Na końcu programu pewne rzeczy należy
doprowadzić do stanu przed jego uruchomieniem. Zmiana rozmiaru okna nam raczej nie grozi-rysujemy po całym ekranie. Z pewnych jednak
względów ten komunikat będzie jednak potrzebny.

3. Inicjalizacja Open GL

Jest realizowana w ramach komunikatu WM_CREATE, i jest to najdłuższa (i niezbędna) część programu.

Po kolei działa to tak:

hDC=GetDC(Okno); //Pobranie tzw. kontekstu okna
SetDCPixelFormat(hDC); //Ustawienie formatu pixeli (o tym poniżej)
hRC=wglCreateContext(hDC); //Stworzenie tzw. kontekstu Open GL

Open GL - Pierwszy program

http://www.gamedev.pl/articles.php?x=view&id=156

1 z 4

2010-04-30 10:33

background image

wglMakeCurrent(hDC, hRC); //I ustawienie go
glViewport(

0

,

0

,GetSystemMetrics( SM_CXSCREEN ),GetSystemMetrics( SM_CYSCREEN ));

// Ustawienie widoku, czyli tej części ekranu, na której będziemy renderować.
// W tym przypadku cały ekran
gluPerspective(

90.0f

,

1.0f

,

1.0f

,

1000.0f

);

//Ustawienie tzw. ostrosłupa widzenia.
// Kamera będzie mieć pole widzenia 90 stopni, będzie widzieć obiekty
//położone względem niej od 1 pixla do 1000 pixli,
// i będzie widzieć obiekty nie zniekształcone
glEnable(GL_DEPTH_TEST);
//Włączenie usuwania powierzchni zasłoniętych
glDepthFunc(GL_LEQUAL);
//Taki nieistotny szczegół związany z powyższym, można usunąć
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
//tzw. korekcja, tekstura będzie "ładnie" nałożona
glEnable(GL_CULL_FACE);
//usuwanie wielokątów odwróconych tyłem do obserwatora. Stosowane w grach,
//na razie można wyłączyć.

I to tyle niezbędnych ustawień. Teraz tylko trzeba załadować tekstury, których będziemy używać. W przykładzie są dwie: t0.bmp i t1.bmp.

Tu małe wyjaśnienie po co jest plik pomoc.cpp. W tym pliku znajdują się procedury ładujące bitmapę oraz ustawiające format pixeli. Na razie
można je traktować jako coś co jest i nie ważne skąd się wzięło. Nie jest to potrzebne do zrozumienia programu.

Za załadowanie tekstur odpowiada fragment kodu:

bits = LoadDIBitmap(

"t1.bmp"

,&info);

rgb = ConvertRGB(info, bits);
glBindTexture(GL_TEXTURE_2D,

1

); // od tego momentu tekstura "t1.bmp" jest pod uchwytem 1

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

0

,

3

, info->bmiHeader.biWidth, info->Header.biHeight,

0

,

GL_RGB, GL_UNSIGNED_BYTE, rgb);

free

(info);

free

(bits);

free

(rgb);

Pewne fragmenty kodu powtarzają się w komunikacie WM_SIZE. Jest to niestety konieczne, ze względu na właściwość API, która "traci"
pewne ustawienia przy wyświetlaniu okna (które traktuje jako zmianę rozmiarów).

Od tego momentu można zająć się już ciekawszymi sprawami.

4. Klawiatura

Podczas obsługi komunikatu WM_KEYDOWN rejestrujemy naciśnięcia kursorów (konkretnie zmieniamy pewne kąty, o których za chwilę),
Entera (zmienia sposób renderowania) i Esc (wyjście z programu).

5. Wyjście z programu

I usuwamy ten którego używaliśmy:

wglDeleteContext(hRC);

6. Rendering

Czyli najważniejsza część programu.

Renderowanie jest realizowane podczas obsługi komunikatu WM_PAINT. Niektóre źródła podają, że można je włączyć do pętli obsługi
komunikatów. Ma to zaletę w postaci zwiększenia szybkości (minimalnie). Wadą natomiast jest możliwość utraty niektórych zdarzeń np.
naciśnięcia klawisza. Ja proponuję pozostać przy WM_PAINT.

W naszym programie za renderowanie odpowiada funkcja void RenderujX(void); gdzie X to nr od 0 do 3. Cztery funkcje renderujące na
cztery różne sposoby.

Obsługa WM_PAINT wygląda tak:

Renderuj0(); //Renderuje funkcja 0
SwapBuffers(hDC); //tzw. przerzucenie buforów, mające zapobiec migotaniu obrazu.

Zajmijmy się teraz funkcją renderującą. Najprostsza jest Renderuj0, rysująca ładnie pokolorowany trójkąt:

Open GL - Pierwszy program

http://www.gamedev.pl/articles.php?x=view&id=156

2 z 4

2010-04-30 10:33

background image

void

Renderuj0(

void

)

{

Najpierw wyłączamy texturowanie:

glDisable(GL_TEXTURE_2D);

Teraz czyścimy bufory koloru i tzw Bufor Z:

glClearColor(

0.50f

,

0.50f

,

0.50f

,

1.0f

);

glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);

Zerujemy macierz transformacji:

glLoadIdentity();

Sprawdzamy, czy kąty o które obrócimy trójkąt są w granicach <0, 360) stopni:

if

(KatX<

0.0f

) KatX+=

360.0f

;

if

(KatX>=

360.0f

) KatX-=

360.0f

;

if

(KatY<

0.0f

) KatY+=

360.0f

;

if

(KatY>=

360.0f

) KatY-=

360.0f

;

Teraz ważna część. Chcemy obrócić trójkąt mniej więcej względem jego środka ciężkości o odpowiednie kąty KatX i KatY. W tym celu
przesuwamy obserwatora do środka (plus/minus) trójkąta, obracamy i oddalamy obserwatora z powrotem. Tu należy zwrócić uwagę na
ciekawą właściwość macierzy transformacji: transformacje Open GL należy przeprowadzać "od końca". Dlaczego ? Jak ktoś chce niech sobie
pomnoży kilka macierzy i będzie wiedział. Dla naszych potrzeb wystarczy wiedzieć, że jeśli chcemy obiekt najpierw przybliżyć (glTranslate), a
potem przekręcić (glRotate), to należy użyć: glRotate, glTranslate:

glTranslatef(

0.0f

,

0.0f

,-

200.0f

);

glRotatef(KatY,

1.0f

,

0.0f

,

0.0f

);

glRotatef(KatX,

0.0f

,

1.0f

,

0.0f

);

glTranslatef(

0.0f

,

0.0f

,

200.0f

);

Teraz już tylko narysowanie trójkąta. W tym celu używamy "klamer" glBegin...glEnd, wewnątrz których umieszczamy wierzchołki trójkąta.
Dodatkowo każdy wierzchołek kolorujemy innym kolorem:

glBegin(GL_TRIANGLES);
glColor3f(

1.0f

,

0.0f

,

0.0f

);

glVertex3f(

150.0f

,-

150.0f

,-

200.0f

);

glColor3f(

0.0f

,

1.0f

,

0.0f

);

glVertex3f(

0.0f

,

150.0f

,-

200.0f

);

glColor3f(

0.0f

,

0.0f

,

1.0f

);

glVertex3f(-

150.0f

,-

150.0f

,-

200.0f

);

glEnd();

Na koniec informujemy Open GL o skończonym renderingu. Teraz niech się martwi akcelerator (albo ostatecznie procesor).

glFinish();
}

Funkcja Renderuj1 jest znacznie ciekawsza, przedstawia teksturowany trójkąt. Nowe elementy to: Włączenie texturownia:

glEnable(GL_TEXTURE_2D);

Włączenie textury pierwszej:

glBindTexture(GL_TEXTURE_2D,

1

);

I podanie współrzędnych nabitmapie dla każdego wierzchołka:

glTexCoord2f(

0.0f

,

0.0f

);

Funkcja Renderuj2 to połączenie obu poprzednich.

Funkcja Renderuj3 pokazuje efekt Light Map'owania, czyli nakładania na teksturę światła obliczonego wcześniej (efekt stosowany w grach
3D). Realizuje się to przez dwukrotne nałożenie tekstury (zwykłej + światło). W nowych kartach 3D (od VooDoo 2) robi się to w jednym
przebiegu na raz, ale efekt jest ten sam.

Open GL - Pierwszy program

http://www.gamedev.pl/articles.php?x=view&id=156

3 z 4

2010-04-30 10:33

background image

Z nowych rzeczy występują funkcje mieszające nałożone tekstury:

glEnable(GL_BLEND);
glBlendFunc(GL_DST_COLOR,GL_SRC_COLOR);

7. Co dalej?

Dalej niech każdy poeksperymentuje sam... Proponuję rozbudować program tak, żeby wyświetlał np. więcej wielokątów, jakiś sześcian, może
prosty engine 3D w stylu Wolfa. Na podstawie tego kodu dużo da się zrobić.

8. Jak stąd daleko do Quake 3?

No cóż, to pytanie jest raczej bardziej śmieszne niż poważne, ale nie do końca... Funkcje renderujące w enginach 3D nie różnią się bardzo.
Należy zauważyć, że obecnie każdy może bawić się w programowanie silniczka 3D korzystającego z akceleratora. W Quake 1 w renderingu
programowym też jest funkcja rysująca trójkąt. Ile autorowi zajęło jej napisanie ? Miesiąc, dwa, albo więcej. Do tego konieczność stosowania
asemblera... Straszne ! Open GL rozwiązuje to w kilku linijkach kodu.

9. Open GL kontra Direct 3D

Zalety GL:

Bardzo łatwy w porównaniu w D3D,
Nieobiektowy, GL to raczej konsola do grafiki,
Ma więcej bajerów graficznych niż D3D,
Lepiej działa na VooDoo,
Dużo opisów dostępnych w sieci.

Wady GL:

Brak funkcji więżących program ze sterownikiem,
Zaawansowane właściwości GL (np. multiteksturowanie) są zawarte w tzw. GL Extensions, co zmusza do dokładnego badania
używanego sterownika.

D3D nie ma dwóch ostatnich wad, jest za to strasznie skomplikowany. Przeważnie jednak przydaje się znajomość obu, cóż takie czasy.

Powodzenia !

Komentarze (8)

Open GL - Pierwszy program

http://www.gamedev.pl/articles.php?x=view&id=156

4 z 4

2010-04-30 10:33


Wyszukiwarka

Podobne podstrony:
Cwiczenie 1 pierwszy program, przycisk BUTT
Open GL Podstawy
1 Pierwszy program konsolowyid Nieznany
Zapoznanie z AVR i pierwsze programy
Mój pierwszy program w Pascalu
Pierwszy program w C
OPEN GL pracownia 1
001 konspekt Pierwszy program w Paskalu
Open GL pomoc Zapis
Pierwszy program z algorytmem
10 KROKOW DO PIERWSZEGO PROGRAM Nieznany (2)
[lekcja 3] Uruchamiamy pierwszy program Kurs C++ » Poziom 1
kurs open gl
opengl pierwszy program
1 TurboPascal Pierwsze programy
Mój pierwszy program w Pascalu
beta kod pierwszy program

więcej podobnych podstron