GLFW, które udało mi się z sukcesem zainstalować (link do wpisu) teoretycznie wystarczy, żeby pracować z OpenGL. Dlaczego teoretycznie? OpenGL nie jest samodzielną biblioteką implementującą funkcje graficzne. Tak naprawdę jest to standard definiujący interfejs sterownika karty graficznej i za implementację poszczególnych funkcji odpowiedzialny jest producent sterownika karty graficznej. Jest to rozsądne, bo każda karta graficzna działa inaczej i ma inne możliwości. Dodatkowo są pewne różnice pomiędzy poszczególnymi wersjami OpenGL. Czym to skutkuje? Poszczególnie funkcje znajdują się „gdzieś” w przestrzeni systemu i podczas kompilacji nie mamy do nich dostępu. Dostęp do tych funkcji trzeba uzyskać poprzez wskaźnik do funkcji, który trzeba „wyłuskać” podczas działania programu. Służy do tego funkcja wglGetProcAddress
. Oto przykład (z popularnego tutoriala):
// define the function's prototype typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*); // find the function and assign it to a function pointer GL_GENBUFFERS glGenBuffers = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
Jak widać nie jest to szczególnie skomplikowane. Problem w tym, że trzeba tą procedurę przeprowadzić dla dziesiątków czy setek funkcji. Ręczne pisanie tego kodu nie ma większego sensu. Dlatego powstał GLAD. Nie jest to biblioteka, tylko generator kodu „wyłuskującego” adresy funkcji. Generatora tego można używać na wiele sposobów. Powstała także witryna internetowa, za pośrednictwem której możemy taki kod wygenerować. Glad występuje w dwóch wersjach (witryna internetowa):
Wynik ich działania jest nieco inny. GLAD generuje plik nagłówkowy glad.h
a GLAD2 gl.h
. Powinny być ze sobą kompatybilne, ale tego nie będę sprawdzał. Wiele poradników skazuje na GLAD, ja jednak będę korzystał z GLAD2, gdyż producent GLFW wskazuje właśnie na ten w swoim poradniku.
Na marginesie. Próbując uruchamiać przykładowy kod OpenGL napotkany w sieci można się zdziwić. W poprzednim wpisie napisałem jak zainstalować GLFW. Ale GLFW to nie jedyna bibioteka umożliwiająca korzystanie z OpenGL. W ogólności można spotkać się z:
- GLUT
- FREEGLUT
- GLFW
- SDL
- SFML
- Allegro
Pierwsze dwie zasługują na uwagę, gdyż bardzo wiele przykładów OpenGL jest opartych o GLUT, który jest kodem – muzealnym, nie rozwijanym od 20 lat. Na szczęście FREEGLUT jest teoretycznie kompatybilny wstecz. Ja zdecydowałem się na GLFW, jako współczesne rozwiązanie.
Ok. Zaczynamy. Nie rozmieniałem się na drobne. Używamy generatora glad2 dostępnego jako witryna internetowa. Ustawienia:
- Generator: C/C++
- APIs: gl, version 4.6, pozostałe pozostawiamy niewybrane.
- Compatibilty: Core
- Extentions: Add All
- Zaznaczamy: loader, merge – ewentualnie debug
Klikamy Generate. Będziemy mogli pobrać archiwum, które zawiera pliki nagłówkowe oraz kod źródłowy loadera. Mamy dwie opcje. Możemy te pliki nagłówkowe dodać do projektu w sposób klasyczny (czyli dodać odpowiednie plik gl.c
do projektu oraz ścieżkę do folderów zawierających folder glad
oraz KHR
dodać do ścieżek przeszukiwania). Przeszedłem tą ścieżkę – działa. Spróbowałem też innego rozwiązania. Stworzyłem z tego bibliotekę statyczną, aby nie mnożyć sobie tego samego kodu w wielu miejscach na dysku. Do rozwiązania dodałem nowy projekt projekt biblioteki statycznej. Trzeba w nim jednak zrobić kilka zmian:
- Usuwamy wszystkie pliki, które domyślnie generuje Visual Studio.
- Prawy przycisk na projekcie:
Properties --> C/C++ --> Precompiled Headers --> Precompiled Header
ustawiam naNot Using Precompiled Headers
. - Dla konfiguracji Release
C/C++ --> Optimalization --> Whole Program Optimalization
ustawiamy naNo
. Dzięki temu pozbędziemy się ostrzeżeń linkera, gdy będziemy używać tej biblioteki w późniejszych programach. - W
Configuration Properties --> VC++ Directories --> Include Directories
do istniejącego wpisu dołączamy wpis:$(ProjectDir)\inc;
przy założeniu, że zawartość katalogu include wygenerowanego przez generator się tam znalazła.
I w zasadzie to już koniec. Ustawiamy bieżącą konfigurację na Release. Budujemy projekt i jeżeli wszystko poszło ok, to wynikiem działania powinien być plik glad.lib
(bo tak nazwałem projekt biblioteki statycznej). Co robimy z tym dalej? W folderze lib
naszego rozwiązania (o którym wspominałem w poprzednim wpisie) tworzymy folder glad
. Do jego wnętrza kopiujemy folder include, który został wygenerowany przez generator glad2 oraz naszą bibliotekę glad.lib.
Czas użyć biblioteki. Jak dodać bibliotekę i pliki nagłówkowe do projektu opisywałem w poprzednim wpisie w tematyce OpenGL. Zatem tworzymy nowy pusty projekt. Dodajemy bibliotekę glfw oraz glad. Tworzymi plik źródłowy main.cpp i wklejamy do niego zawartość przykładu kręcącego się trójkąta. Próbujemy kompilować? Zonk! Brakuje jeszcze pliku linmath.h. Trzeba go pobrać i dodać do projektu. Teraz wszystko powinno się ładnie kompilować i uruchamiać.