Start z OpenGL ciąg dalszy – GLAD

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:

  1. Usuwamy wszystkie pliki, które domyślnie generuje Visual Studio.
  2. Prawy przycisk na projekcie: Properties --> C/C++ --> Precompiled Headers --> Precompiled Header ustawiam na Not Using Precompiled Headers.
  3. Dla konfiguracji Release C/C++ --> Optimalization --> Whole Program Optimalization ustawiamy na No.   Dzięki temu pozbędziemy się ostrzeżeń linkera, gdy będziemy używać tej biblioteki w późniejszych programach.
  4. 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ć.