opengl Samouczek
Rozpoczęcie pracy z Opengl
Szukaj…
Uwagi
OpenGL to otwarty standard renderowania grafiki 2D i 3D z wykorzystaniem sprzętu graficznego. OpenGL został wdrożony na oszałamiającej gamie platform, dzięki czemu aplikacje atakujące OpenGL są niezwykle elastyczne.
Wersje
Wersja | Data wydania |
---|---|
1.1 | 1997-03-04 |
1.2 | 1998-03-16 |
1.2.1 | 1998-10-14 |
1.3 | 2001-08-14 |
1.4 | 2002-07-24 |
1.5 | 2003-07-29 |
2.0 | 2004-09-07 |
2.1 | 2006-07-02 |
3.0 | 2008-08-11 |
3.1 | 24.03.2009 |
3.2 | 2009-08-03 |
3.3 | 2010-03-11 |
4.0 | 2010-03-11 |
4.1 | 2010-07-26 |
4.2 | 08.08.2011 |
4.3 | 06.08.2012 |
4.4 | 2013-07-22 |
4.5 | 2014-08-11 |
Uzyskiwanie OpenGL
Jednym z najczęstszych nieporozumień na temat OpenGL jest to, że była to biblioteka, którą można zainstalować ze źródeł zewnętrznych. To nieporozumienie prowadzi do wielu pytań w formie „jak zainstalować OpenGL” lub „skąd pobrać zestaw OpenGL SDK”.
Nie w ten sposób OpenGL znajduje drogę do systemu komputerowego. OpenGL sam w sobie jest jedynie zbiorem specyfikacji dotyczących poleceń, które musi wykonać implementacja. Tak więc liczy się implementacja. A na razie implementacje OpenGL są częścią sterowników GPU. To może się zmienić w przyszłości, gdy nowy interfejs programowania GPU pozwoli naprawdę zaimplementować OpenGL jako bibliotekę, ale na razie jest to API programowania do sterowników graficznych.
Kiedy OpenGL został wydany po raz pierwszy, API w jakiś sposób znalazło się w umowie ABI (Application Binary Interface) dla systemów Windows, Solaris i Linux (LSB-4 Desktop), oprócz swojego pochodzenia Sun Irix. Apple podążyło za tym i zintegrowało OpenGL tak głęboko w MacOS X, że dostępna wersja OpenGL jest ściśle powiązana z zainstalowaną wersją MacOS X. Ma to znaczący efekt, że środowiska programowania systemu dla tych systemów operacyjnych (tj. Zestaw narzędzi kompilatora i linkera, który natywnie celuje w te systemy) muszą również dostarczać definicje API OpenGL. Tak więc nie jest konieczne instalowanie zestawu SDK dla OpenGL. Jest technicznie możliwe programowanie OpenGL w tych systemach operacyjnych bez konieczności instalowania dedykowanego zestawu SDK, przy założeniu, że zainstalowane jest środowisko kompilacji zgodne z docelowym ABI.
Skutkiem ubocznym tych ścisłych reguł ABI jest to, że wersja OpenGL ujawniona przez interfejs wiązania jest najniższym wspólnym mianownikiem, którego programy działające na platformie docelowej mogą oczekiwać. Stąd dostęp do nowoczesnych funkcji OpenGL można uzyskać za pomocą mechanizmu rozszerzenia, który został szczegółowo opisany osobno.
Linux
W Linuksie dość często dzieli się pakiety programistyczne na różne aspekty systemu, aby można je było aktualizować indywidualnie. W większości dystrybucji Linuksa pliki programistyczne dla OpenGL są zawarte w dedykowanym pakiecie, który zwykle jest zależny od meta-pakietu programistycznego do tworzenia aplikacji komputerowych. Tak więc instalowanie plików programistycznych OpenGL dla systemu Linux zwykle odbywa się przy instalacji pakietu / pakietów meta rozwoju pulpitu. *
Microsoft Windows
Biblioteka opengl32.dll
API opengl32.dll
(nazwana tak dla 32-bitowych i 64-bitowych wersji systemu Windows) jest dostarczana domyślnie z każdą wersją systemu Windows od Windows NT-4 i Windows 95B (oba ok. 1997). Jednak ta biblioteka DLL nie zapewnia rzeczywistej implementacji OpenGL (poza awarią oprogramowania, której jedynym celem jest działanie jako sieć bezpieczeństwa dla programów, jeśli nie jest zainstalowana żadna inna implementacja OpenGL). Ta biblioteka DLL należy do systemu Windows i nie wolno jej zmieniać ani przenosić! Nowoczesne wersje OpenGL są dostarczane jako część tak zwanego Sterownika Klienta Instalowanego (ICD) i są dostępne przez domyślny opengl32.dll
który jest fabrycznie zainstalowany z każdą wersją systemu Windows. Microsoft zdecydował jednak wewnętrznie, że sterowniki graficzne zainstalowane za pomocą Windows Update nie instalują / nie aktualizują OpenGL ICD. W związku z tym nowe instalacje systemu Windows ze sterownikami instalowanymi automatycznie nie obsługują nowoczesnych funkcji OpenGL. Aby uzyskać OpenGL ICD z nowoczesnymi funkcjami, sterowniki graficzne należy pobrać bezpośrednio ze strony internetowej dostawcy GPU i zainstalować ręcznie.
Jeśli chodzi o rozwój, nie należy podejmować dodatkowych kroków per se. Wszystkie kompilatory C / C ++ zgodne ze specyfikacjami Windows ABI są dostarczane z nagłówkami i kodem pośredniczącym (opengl32.lib) wymaganym do budowania i łączenia plików wykonywalnych korzystających z OpenGL.
Ręczna konfiguracja OpenGL w systemie Windows
Pełny przykładowy kod zawarty na końcu
Komponenty Windows dla OpenGL
WGL
WGL (można wymówić wiggle ) oznacza „Windows-GL”, podobnie jak w „interfejsie między Windows a OpenGL” - zestaw funkcji z Windows API do komunikacji z OpenGL. Funkcje WGL mają przedrostek wgl, a jego tokeny mają przedrostek WGL_ .
Domyślna wersja OpenGL obsługiwana w systemach Microsoft to 1.1. To jest bardzo stara wersja (najnowsza to 4.5). Aby uzyskać najnowsze wersje, należy zaktualizować sterowniki karty graficznej, ale karta graficzna musi obsługiwać te nowe wersje.
Pełna lista funkcji WGL znajduje się tutaj .
Interfejs urządzenia graficznego (GDI)
GDI (dziś zaktualizowany do GDI +) to interfejs do rysowania 2D, który pozwala rysować w oknie w systemie Windows. Potrzebujesz GDI do zainicjowania OpenGL i umożliwienia mu interakcji z nim (ale tak naprawdę nie użyje samego GDI).
W GDI każde okno ma kontekst urządzenia (DC), który służy do identyfikacji celu rysowania podczas wywoływania funkcji (przekazujesz go jako parametr). Jednak OpenGL używa własnego kontekstu renderowania (RC) . Tak więc DC zostanie użyty do stworzenia RC.
Podstawowe ustawienia
Tworzenie okna
Więc do robienia rzeczy w OpenGL potrzebujemy RC, a aby uzyskać RC, potrzebujemy DC, a aby uzyskać DC, potrzebujemy okna. Utworzenie okna za pomocą interfejsu API systemu Windows wymaga kilku kroków. Jest to podstawowa procedura, dlatego w celu uzyskania bardziej szczegółowych wyjaśnień należy zapoznać się z inną dokumentacją, ponieważ nie chodzi o korzystanie z interfejsu API systemu Windows.
Jest to konfiguracja systemu Windows, dlatego należy dołączyć Windows.h
, a punktem wejścia programu musi być procedura WinMain
z jej parametrami. Program musi być również powiązany z opengl32.dll
i gdi32.dll
(niezależnie od tego, czy korzystasz z systemu 64-bitowego, czy 32-bitowego).
Najpierw musimy opisać nasze okno za pomocą struktury WNDCLASS
. Zawiera informacje o oknie, które chcemy utworzyć:
/* REGISTER WINDOW */
WNDCLASS window_class;
// Clear all structure fields to zero first
ZeroMemory(&window_class, sizeof(window_class));
// Define fields we need (others will be zero)
window_class.style = CS_OWNDC;
window_class.lpfnWndProc = window_procedure; // To be introduced later
window_class.hInstance = instance_handle;
window_class.lpszClassName = TEXT("OPENGL_WINDOW");
// Give our class to Windows
RegisterClass(&window_class);
/* *************** */
Aby uzyskać dokładne wyjaśnienie znaczenia każdego pola (i pełną listę pól), zapoznaj się z dokumentacją MSDN.
Następnie możemy utworzyć okno za pomocą CreateWindowEx
. Po utworzeniu okna możemy uzyskać jego kontroler domeny:
/* CREATE WINDOW */
HWND window_handle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
TEXT("OPENGL_WINDOW"),
TEXT("OpenGL window"),
WS_OVERLAPPEDWINDOW,
0, 0,
800, 600,
NULL,
NULL,
instance_handle,
NULL);
HDC dc = GetDC(window_handle);
ShowWindow(window_handle, SW_SHOW);
/* ************* */
Wreszcie musimy utworzyć pętlę komunikatów, która odbiera zdarzenia okna z systemu operacyjnego:
/* EVENT PUMP */
MSG msg;
while (true) {
if (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// draw(); <- there goes your drawing
SwapBuffers(dc); // To be mentioned later
}
/* ********** */
Format pikseli
OpenGL musi znać pewne informacje o naszym oknie, takie jak bitowość kolorów, metoda buforowania i tak dalej. W tym celu używamy formatu pikseli . Możemy jednak jedynie zasugerować systemowi operacyjnemu, jakiego rodzaju formatu pikseli potrzebujemy, a system operacyjny zapewni najbardziej podobny obsługiwany format, nie mamy nad nim bezpośredniej kontroli. Dlatego nazywa się to jedynie deskryptorem .
/* PIXEL FORMAT */
PIXELFORMATDESCRIPTOR descriptor;
// Clear all structure fields to zero first
ZeroMemory(&descriptor, sizeof(descriptor));
// Describe our pixel format
descriptor.nSize = sizeof(descriptor);
descriptor.nVersion = 1;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER | PFD_SWAP_LAYER_BUFFERS;
descriptor.iPixelType = PFD_TYPE_RGBA;
descriptor.cColorBits = 32;
descriptor.cRedBits = 8;
descriptor.cGreenBits = 8;
descriptor.cBlueBits = 8;
descriptor.cAlphaBits = 8;
descriptor.cDepthBits = 32;
descriptor.cStencilBits = 8;
// Ask for a similar supported format and set it
int pixel_format = ChoosePixelFormat(dc, &descriptor);
SetPixelFormat(dc, pixel_format, &descriptor);
/* *********************** */
dwFlags
podwójne buforowanie w polu dwFlags
, więc musimy wywołać SwapBuffers
, aby zobaczyć rzeczy po losowaniu.
Kontekst renderowania
Następnie możemy po prostu stworzyć nasz kontekst renderowania:
/* RENDERING CONTEXT */
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
/* ***************** */
Pamiętaj, że tylko jeden wątek może używać RC jednocześnie. Jeśli chcesz użyć go z innego wątku później, musisz wywołać tam wglMakeCurrent
, aby go ponownie aktywować (spowoduje to dezaktywację go w wątku, w którym jest on aktualnie aktywny itd.).
Uzyskiwanie funkcji OpenGL
Funkcje OpenGL uzyskuje się za pomocą wskaźników funkcji. Ogólna procedura to:
- Jakoś uzyskać typy wskaźników funkcji (zasadniczo prototypy funkcji)
- Zadeklaruj każdą funkcję, której chcielibyśmy użyć (z jej typem wskaźnika funkcji)
- Uzyskaj rzeczywistą funkcję
Rozważmy na przykład glBegin:
// We need to somehow find something that contains something like this,
// as we can't know all the OpenGL function prototypes
typedef void (APIENTRY *PFNGLBEGINPROC)(GLenum);
// After that, we need to declare the function in order to use it
PFNGLBEGINPROC glBegin;
// And finally, we need to somehow make it an actual function
(„PFN” oznacza „wskaźnik do funkcji”, po którym następuje nazwa funkcji OpenGL, a na końcu „PROC” - jest to zwykle nazwa typu wskaźnika funkcji OpenGL).
Oto jak to się robi w systemie Windows. Jak wspomniano wcześniej, Microsoft dostarcza tylko OpenGL 1.1. Po pierwsze, typy wskaźników funkcji dla tej wersji można znaleźć, włączając GL/gl.h
Następnie deklarujemy wszystkie funkcje, których zamierzamy używać, jak pokazano powyżej (zrobienie tego w pliku nagłówkowym i zadeklarowanie ich jako „extern” pozwoliłoby nam korzystać z nich wszystkich po załadowaniu ich tylko raz, po prostu przez włączenie go). Wreszcie, ładowanie funkcji OpenGL 1.1 odbywa się poprzez otwarcie biblioteki DLL:
HMODULE gl_module = LoadLibrary(TEXT("opengl32.dll"));
/* Load all the functions here */
glBegin = (PFNGLBEGINPROC)GetProcAddress("glBegin");
// ...
/* *************************** */
FreeLibrary(gl_module);
Jednak prawdopodobnie chcemy nieco więcej niż OpenGL 1.1. Ale Windows nie daje nam prototypów funkcji ani eksportowanych funkcji w przypadku czegokolwiek powyżej. Prototypy należy pobrać z rejestru OpenGL . Istnieją trzy pliki, które nas interesują: GL/glext.h
, GL/glcorearb.h
i GL/wglext.h
.
Aby ukończyć GL/gl.h
dostarczone przez Windows, potrzebujemy GL/glext.h
. Zawiera (zgodnie z opisem w rejestrze) „OpenGL 1.2 i wyższe profile zgodności i interfejsy rozszerzeń” (więcej o profilach i rozszerzeniach później, gdzie zobaczymy, że tak naprawdę nie jest dobrym pomysłem używanie tych dwóch plików ).
Rzeczywiste funkcje muszą zostać uzyskane przez wglGetProcAddress
(nie ma potrzeby otwierania biblioteki DLL dla tego faceta, nie ma ich tam, wystarczy użyć funkcji). Dzięki niemu możemy pobrać wszystkie funkcje z OpenGL 1.2 i nowszych (ale nie 1.1). Należy pamiętać, że w celu poprawnego działania kontekst renderowania OpenGL musi zostać utworzony i zaktualizowany . Na przykład glClear
:
// Include the header from the OpenGL registry for function pointer types
// Declare the functions, just like before
PFNGLCLEARPROC glClear;
// ...
// Get the function
glClear = (PFNGLCLEARPROC)wglGetProcAddress("glClear");
Możemy faktycznie zbudować procedurę get_proc
opakowania, która używa zarówno wglGetProcAddress
jak i GetProcAddress
:
// Get function pointer
void* get_proc(const char *proc_name)
{
void *proc = (void*)wglGetProcAddress(proc_name);
if (!proc) proc = (void*)GetProcAddress(gl_module, proc_name); // gl_module must be somewhere in reach
return proc;
}
Podsumowując, utworzylibyśmy plik nagłówkowy pełen deklaracji wskaźnika funkcji, taki jak ten:
extern PFNGLCLEARCOLORPROC glClearColor;
extern PFNGLCLEARDEPTHPROC glClearDepth;
extern PFNGLCLEARPROC glClear;
extern PFNGLCLEARBUFFERIVPROC glClearBufferiv;
extern PFNGLCLEARBUFFERFVPROC glClearBufferfv;
// And so on...
Następnie możemy utworzyć procedurę taką jak load_gl_functions
, którą wywołujemy tylko raz i działa ona tak:
glClearColor = (PFNGLCLEARCOLORPROC)get_proc("glClearColor");
glClearDepth = (PFNGLCLEARDEPTHPROC)get_proc("glClearDepth");
glClear = (PFNGLCLEARPROC)get_proc("glClear");
glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)get_proc("glClearBufferiv");
glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)get_proc("glClearBufferfv");
I wszystko gotowe! Wystarczy dołączyć nagłówek wraz ze wskaźnikami funkcji i GL.
Lepsza konfiguracja
Profile OpenGL
OpenGL jest rozwijany od ponad 20 lat, a programiści zawsze ściśle przestrzegali wstecznej kompatybilności (BC) . Z tego powodu dodanie nowej funkcji jest bardzo trudne. Tak więc w 2008 roku został on podzielony na dwa „profile”. Rdzeń i kompatybilność . Profil podstawowy łamie BC na rzecz poprawy wydajności i niektórych nowych funkcji. Nawet całkowicie usuwa niektóre starsze funkcje. Profil zgodności utrzymuje BC ze wszystkimi wersjami do 1.0, a niektóre nowe funkcje nie są w nim dostępne. Można go używać tylko w starszych, starszych systemach, wszystkie nowe aplikacje powinny korzystać z profilu podstawowego.
Z tego powodu istnieje problem z naszą podstawową konfiguracją - zapewnia ona tylko kontekst wstecznie zgodny z OpenGL 1.0. Format pikseli jest również ograniczony. Jest lepsze podejście, używając rozszerzeń.
Rozszerzenia OpenGL
Wszelkie dodatki do oryginalnej funkcjonalności OpenGL nazywane są rozszerzeniami. Zasadniczo mogą albo zalegalizować niektóre rzeczy, które nie były wcześniej, rozszerzyć zakres wartości parametrów, rozszerzyć GLSL, a nawet dodać zupełnie nową funkcjonalność.
Istnieją trzy główne grupy rozszerzeń: sprzedawca, EXT i ARB. Rozszerzenia dostawców pochodzą od konkretnego dostawcy i mają znak konkretnego dostawcy, na przykład AMD lub NV. Rozszerzenia EXT są tworzone przez kilku współpracujących dostawców. Po pewnym czasie mogą stać się rozszerzeniami ARB, które są oficjalnie wspierane i zatwierdzone przez ARB.
Aby uzyskać typy wskaźników funkcji i prototypy funkcji wszystkich rozszerzeń oraz, jak wspomniano wcześniej, wszystkie typy wskaźników funkcji z OpenGL 1.2 i nowszych , należy pobrać pliki nagłówkowe z rejestru OpenGL . Jak omówiono, w przypadku nowych aplikacji lepiej jest użyć profilu rdzenia, dlatego lepiej byłoby dołączyć GL/glcorearb.h
zamiast GL/gl.h
i GL/glext.h
(jeśli używasz GL/glcorearb.h
to nie obejmują GL/gl.h
).
Istnieją również rozszerzenia dla WGL, w GL/wglext.h
. Na przykład funkcja pobierania listy wszystkich obsługiwanych rozszerzeń jest w rzeczywistości samym rozszerzeniem, wglGetExtensionsStringARB
(zwraca duży ciąg z rozdzieloną spacjami listą wszystkich obsługiwanych rozszerzeń).
Pobieranie rozszerzeń jest obsługiwane również przez wglGetProcAddress
, więc możemy po prostu używać naszego opakowania tak jak wcześniej.
Zaawansowany format pikseli i tworzenie kontekstu
Rozszerzenie WGL_ARB_pixel_format
pozwala nam na zaawansowane tworzenie formatu pikseli. W przeciwieństwie do wcześniejszych nie używamy struktury. Zamiast tego przekazujemy listę poszukiwanych atrybutów.
int pixel_format_arb;
UINT pixel_formats_found;
int pixel_attributes[] = {
WGL_SUPPORT_OPENGL_ARB, 1,
WGL_DRAW_TO_WINDOW_ARB, 1,
WGL_DRAW_TO_BITMAP_ARB, 1,
WGL_DOUBLE_BUFFER_ARB, 1,
WGL_SWAP_LAYER_BUFFERS_ARB, 1,
WGL_COLOR_BITS_ARB, 32,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 32,
WGL_STENCIL_BITS_ARB, 8,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
0
};
BOOL result = wglChoosePixelFormatARB(dc, pixel_attributes, NULL, 1, &pixel_format_arb, &pixel_formats_found);
Podobnie rozszerzenie WGL_ARB_create_context
umożliwia nam zaawansowane tworzenie kontekstu:
GLint context_attributes[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
HGLRC new_rc = wglCreateContextAttribsARB(dc, 0, context_attributes);
Dokładne objaśnienie parametrów i funkcji można znaleźć w specyfikacji OpenGL.
Dlaczego nie zaczęliśmy od nich? To dlatego, że rozszerzenia pozwalają nam to robić, a aby uzyskać rozszerzenia, potrzebujemy wglGetProcAddress
, ale działa to tylko z aktywnym prawidłowym kontekstem. Zasadniczo więc, zanim będziemy w stanie stworzyć pożądany kontekst, musimy mieć jakiś aktywny kontekst, który zwykle jest nazywany kontekstem pozornym .
Jednak system Windows nie zezwala na ustawienie formatu pikseli okna więcej niż jeden raz. Z tego powodu okno musi zostać zniszczone i ponownie utworzone, aby zastosować nowe rzeczy:
wglMakeCurrent(dc, NULL);
wglDeleteContext(rc);
ReleaseDC(window_handle, dc);
DestroyWindow(window_handle);
// Recreate the window...
Pełny przykładowy kod:
/* We want the core profile, so we include GL/glcorearb.h. When including that, then
GL/gl.h should not be included.
If using compatibility profile, the GL/gl.h and GL/glext.h need to be included.
GL/wglext.h gives WGL extensions.
Note that Windows.h needs to be included before them. */
#include <cstdio>
#include <Windows.h>
#include <GL/glcorearb.h>
#include <GL/wglext.h>
LRESULT CALLBACK window_procedure(HWND, UINT, WPARAM, LPARAM);
void* get_proc(const char*);
/* gl_module is for opening the DLL, and the quit flag is here to prevent
quitting when recreating the window (see the window_procedure function) */
HMODULE gl_module;
bool quit = false;
/* OpenGL function declarations. In practice, we would put these in a
separate header file and add "extern" in front, so that we can use them
anywhere after loading them only once. */
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
PFNGLGETSTRINGPROC glGetString;
int WINAPI WinMain(HINSTANCE instance_handle, HINSTANCE prev_instance_handle, PSTR cmd_line, int cmd_show) {
/* REGISTER WINDOW */
WNDCLASS window_class;
// Clear all structure fields to zero first
ZeroMemory(&window_class, sizeof(window_class));
// Define fields we need (others will be zero)
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
window_class.lpfnWndProc = window_procedure;
window_class.hInstance = instance_handle;
window_class.lpszClassName = TEXT("OPENGL_WINDOW");
// Give our class to Windows
RegisterClass(&window_class);
/* *************** */
/* CREATE WINDOW */
HWND window_handle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
TEXT("OPENGL_WINDOW"),
TEXT("OpenGL window"),
WS_OVERLAPPEDWINDOW,
0, 0,
800, 600,
NULL,
NULL,
instance_handle,
NULL);
HDC dc = GetDC(window_handle);
ShowWindow(window_handle, SW_SHOW);
/* ************* */
/* PIXEL FORMAT */
PIXELFORMATDESCRIPTOR descriptor;
// Clear all structure fields to zero first
ZeroMemory(&descriptor, sizeof(descriptor));
// Describe our pixel format
descriptor.nSize = sizeof(descriptor);
descriptor.nVersion = 1;
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER | PFD_SWAP_LAYER_BUFFERS;
descriptor.iPixelType = PFD_TYPE_RGBA;
descriptor.cColorBits = 32;
descriptor.cRedBits = 8;
descriptor.cGreenBits = 8;
descriptor.cBlueBits = 8;
descriptor.cAlphaBits = 8;
descriptor.cDepthBits = 32;
descriptor.cStencilBits = 8;
// Ask for a similar supported format and set it
int pixel_format = ChoosePixelFormat(dc, &descriptor);
SetPixelFormat(dc, pixel_format, &descriptor);
/* *********************** */
/* RENDERING CONTEXT */
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
/* ***************** */
/* LOAD FUNCTIONS (should probably be put in a separate procedure) */
gl_module = LoadLibrary(TEXT("opengl32.dll"));
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)get_proc("wglGetExtensionsStringARB");
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)get_proc("wglChoosePixelFormatARB");
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)get_proc("wglCreateContextAttribsARB");
glGetString = (PFNGLGETSTRINGPROC)get_proc("glGetString");
FreeLibrary(gl_module);
/* ************** */
/* PRINT VERSION */
const GLubyte *version = glGetString(GL_VERSION);
printf("%s\n", version);
fflush(stdout);
/* ******* */
/* NEW PIXEL FORMAT*/
int pixel_format_arb;
UINT pixel_formats_found;
int pixel_attributes[] = {
WGL_SUPPORT_OPENGL_ARB, 1,
WGL_DRAW_TO_WINDOW_ARB, 1,
WGL_DRAW_TO_BITMAP_ARB, 1,
WGL_DOUBLE_BUFFER_ARB, 1,
WGL_SWAP_LAYER_BUFFERS_ARB, 1,
WGL_COLOR_BITS_ARB, 32,
WGL_RED_BITS_ARB, 8,
WGL_GREEN_BITS_ARB, 8,
WGL_BLUE_BITS_ARB, 8,
WGL_ALPHA_BITS_ARB, 8,
WGL_DEPTH_BITS_ARB, 32,
WGL_STENCIL_BITS_ARB, 8,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
0
};
BOOL result = wglChoosePixelFormatARB(dc, pixel_attributes, NULL, 1, &pixel_format_arb, &pixel_formats_found);
if (!result) {
printf("Could not find pixel format\n");
fflush(stdout);
return 0;
}
/* **************** */
/* RECREATE WINDOW */
wglMakeCurrent(dc, NULL);
wglDeleteContext(rc);
ReleaseDC(window_handle, dc);
DestroyWindow(window_handle);
window_handle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
TEXT("OPENGL_WINDOW"),
TEXT("OpenGL window"),
WS_OVERLAPPEDWINDOW,
0, 0,
800, 600,
NULL,
NULL,
instance_handle,
NULL);
dc = GetDC(window_handle);
ShowWindow(window_handle, SW_SHOW);
/* *************** */
/* NEW CONTEXT */
GLint context_attributes[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0
};
rc = wglCreateContextAttribsARB(dc, 0, context_attributes);
wglMakeCurrent(dc, rc);
/* *********** */
/* EVENT PUMP */
MSG msg;
while (true) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// draw(); <- there goes your drawing
SwapBuffers(dc);
}
/* ********** */
return 0;
}
// Procedure that processes window events
LRESULT CALLBACK window_procedure(HWND window_handle, UINT message, WPARAM param_w, LPARAM param_l)
{
/* When destroying the dummy window, WM_DESTROY message is going to be sent,
but we don't want to quit the application then, and that is controlled by
the quit flag. */
switch(message) {
case WM_DESTROY:
if (!quit) quit = true;
else PostQuitMessage(0);
return 0;
}
return DefWindowProc(window_handle, message, param_w, param_l);
}
/* A procedure for getting OpenGL functions and OpenGL or WGL extensions.
When looking for OpenGL 1.2 and above, or extensions, it uses wglGetProcAddress,
otherwise it falls back to GetProcAddress. */
void* get_proc(const char *proc_name)
{
void *proc = (void*)wglGetProcAddress(proc_name);
if (!proc) proc = (void*)GetProcAddress(gl_module, proc_name);
return proc;
}
Skompilowany z g++ GLExample.cpp -lopengl32 -lgdi32
z MinGW / Cygwin lub cl GLExample.cpp opengl32.lib gdi32.lib user32.lib
z kompilatorem MSVC. Upewnij się jednak, że nagłówki z rejestru OpenGL znajdują się w ścieżce dołączania. Jeśli nie, użyj opcji -I
dla g++
lub /I
dla cl
, aby poinformować kompilator, gdzie się znajdują.
Tworzenie OpenGL 4.1 z C ++ i Cocoa
Uwaga: w tym przykładzie będzie trochę Cel-c. W tym przykładzie stworzymy opakowanie dla C ++, więc nie przejmuj się zbytnio.
Najpierw uruchom Xcode i utwórz projekt.
Usuń wszystkie źródła z wyjątkiem pliku Info.plist (Twoja aplikacja nie będzie działać bez niego)
Utwórz 4 nowe pliki źródłowe: Plik Objective-c ++ i nagłówek (nazwałem mój MacApp) Klasa C ++ (nazwałem mój (Aplikacja)
W lewym górnym rogu (z nazwą projektu) kliknij na nią i dodaj połączone frameworki i biblioteki. Dodaj: OpenGL.Framework AppKit.Framework GLKit.Framework
Twój projekt prawdopodobnie będzie wyglądał tak:
NSApplication to główna klasa, której używasz podczas tworzenia aplikacji MacOS. Pozwala rejestrować okna i wychwytywać zdarzenia.
Chcemy zarejestrować (nasze) okno w aplikacji NSA. Najpierw utwórz w nagłówku Goal -c ++ klasę Goal -c, która dziedziczy po NSWindow i implementuje NSApplicationDelegate NSWindow potrzebuje wskaźnika do aplikacji C ++, widoku OpenGL i timera dla pętli rysującej
//Mac_App_H
#import <Cocoa/Cocoa.h>
#import "Application.hpp"
#import <memory>
NSApplication* application;
@interface MacApp : NSWindow <NSApplicationDelegate>{
std::shared_ptr<Application> appInstance;
}
@property (nonatomic, retain) NSOpenGLView* glView;
-(void) drawLoop:(NSTimer*) timer;
@end
Nazywamy to od głównego za pomocą
int main(int argc, const char * argv[]) {
MacApp* app;
application = [NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
//create a window with the size of 600 by 600
app = [[MacApp alloc] initWithContentRect:NSMakeRect(0, 0, 600, 600) styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:YES];
[application setDelegate:app];
[application run];
}
Implementacja naszego okna jest w rzeczywistości dość łatwa. Najpierw deklarujemy, syntezując nasz glview i dodając globalną wartość logiczną typu c, gdy okno powinno się zamknąć.
#import "MacApp.h"
@implementation MacApp
@synthesize glView;
BOOL shouldStop = NO;
Teraz konstruktor. Preferuję użycie initWithContentRect.
-(id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag{
if(self = [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag]){
//sets the title of the window (Declared in Plist)
[self setTitle:[[NSProcessInfo processInfo] processName]];
//This is pretty important.. OS X starts always with a context that only supports openGL 2.1
//This will ditch the classic OpenGL and initialises openGL 4.1
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] ={
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAColorSize , 24 ,
NSOpenGLPFAAlphaSize , 8 ,
NSOpenGLPFADoubleBuffer ,
NSOpenGLPFAAccelerated ,
NSOpenGLPFANoRecovery ,
0
};
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc]initWithAttributes:pixelFormatAttributes];
//Initialize the view
glView = [[NSOpenGLView alloc]initWithFrame:contentRect pixelFormat:format];
//Set context and attach it to the window
[[glView openGLContext]makeCurrentContext];
//finishing off
[self setContentView:glView];
[glView prepareOpenGL];
[self makeKeyAndOrderFront:self];
[self setAcceptsMouseMovedEvents:YES];
[self makeKeyWindow];
[self setOpaque:YES];
//Start the c++ code
appInstance = std::shared_ptr<Application>(new Application());
}
return self;
}
W porządku ... teraz mamy uruchomioną aplikację. Możesz zobaczyć czarny ekran lub migotanie.
Narysujmy niesamowity trójkąt. (W c ++)
Mój nagłówek aplikacji
#ifndef Application_hpp
#define Application_hpp
#include <iostream>
#include <OpenGL/gl3.h>
class Application{
private:
GLuint program;
GLuint vao;
public:
Application();
void update();
~Application();
};
#endif /* Application_hpp */
Implementacja:
Application::Application(){
static const char * vs_source[] =
{
"#version 410 core \n"
" \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID]; \n"
"} \n"
};
static const char * fs_source[] =
{
"#version 410 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
program = glCreateProgram();
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
}
void Application::update(){
static const GLfloat green[] = { 0.0f, 0.25f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, green);
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Application::~Application(){
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
}
Teraz musimy tylko wywoływać aktualizację w kółko (jeśli chcesz coś przenieść) Implementuj w klasie C celu
-(void) drawLoop:(NSTimer*) timer{
if(shouldStop){
[self close];
return;
}
if([self isVisible]){
appInstance->update();
[glView update];
[[glView openGLContext] flushBuffer];
}
}
I dodaj tę metodę do implementacji swojej klasy target-c:
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
[NSTimer scheduledTimerWithTimeInterval:0.000001 target:self selector:@selector(drawLoop:) userInfo:nil repeats:YES];
}
wywoła to funkcję aktualizacji Twojej klasy c ++ w kółko (co 0,000001 sekund, a dokładniej)
Aby zakończyć, zamykamy okno po naciśnięciu przycisku zamykania:
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication{
return YES;
}
- (void)applicationWillTerminate:(NSNotification *)aNotification{
shouldStop = YES;
}
Gratulacje, teraz masz niesamowite okno z trójkątem OpenGL bez żadnych ram zewnętrznych.
Wieloplatformowe tworzenie kontekstu OpenGL (przy użyciu SDL2)
Tworzenie okna z kontekstem OpenGL (ładowanie rozszerzenia przez GLEW ):
#define GLEW_STATIC #include <GL/glew.h> #include <SDL2/SDL.h> int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_VIDEO); /* Initialises Video Subsystem in SDL */ /* Setting up OpenGL version and profile details for context creation */ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); /* A 800x600 window. Pretty! */ SDL_Window* window = SDL_CreateWindow ( "SDL Context", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_OPENGL ); /* Creating OpenGL Context */ SDL_GLContext gl_context = SDL_GL_CreateContext(window); /* Loading Extensions */ glewExperimental = GL_TRUE; glewInit(); /* The following code is for error checking. * If OpenGL has initialised properly, this should print 1. * Remove it in production code. */ GLuint vertex_buffer; glGenBuffers(1, &vertex_buffer); printf("%u\n", vertex_buffer); /* Error checking ends here */ /* Main Loop */ SDL_Event window_event; while(1) { if (SDL_PollEvent(&window_event)) { if (window_event.type == SDL_QUIT) { /* If user is exiting the application */ break; } } /* Swap the front and back buffer for flicker-free rendering */ SDL_GL_SwapWindow(window); } /* Freeing Memory */ glDeleteBuffers(1, &vertex_buffer); SDL_GL_DeleteContext(gl_context); SDL_Quit(); return 0; }
Skonfiguruj Modern OpenGL 4.1 na macOS (Xcode, GLFW i GLEW)
1. Zainstaluj GLFW
Pierwszym krokiem jest utworzenie okna OpenGL. GLFW to wieloplatformowa biblioteka Open Source do tworzenia okien za pomocą OpenGL, aby zainstalować GLFW najpierw pobierz swoje pliki ze strony www.glfw.org
Wyodrębnij folder GLFW, a jego zawartość będzie wyglądać następująco
Pobierz i zainstaluj CMake, aby zbudować GLFW. Idź do www.cmake.org/download/ , pobierz CMake i zainstaluj dla MAC OS X
Jeśli Xcode nie jest zainstalowany. Pobierz i zainstaluj Xcode z Mac App Store.
Utwórz nowy folder Zbuduj w folderze GLFW
Otwórz CMake, kliknij przycisk Przeglądaj źródło , aby wybrać folder GLFW (upewnij się, że CMakeLists.txt) znajduje się w tym folderze. Następnie kliknij przycisk Przeglądaj kompilację i wybierz nowo utworzony folder kompilacji w poprzednim kroku.
Teraz kliknij przycisk Konfiguruj i wybierz Xcode jako generator z opcją Użyj domyślnych kompilatorów natywnych , a następnie kliknij Gotowe .
Zaznacz opcję BUILD_SHARED_LIBS , a następnie ponownie kliknij przycisk Konfiguruj , a na koniec przycisk Generuj .
Po wygenerowaniu CMake powinien wyglądać tak
Teraz otwórz Finder i goto / usr , utwórz nazwę folderu lokalnego, jeśli jeszcze jej nie ma. Otwórz folder lokalny i utwórz dwa foldery zawierają i lib jeśli nie już istnieje.
Teraz otwórz folder GLFW i goto Build (gdzie CMake zbudował pliki). Otwórz plik GLFW.xcodeproj w Xcode.
Wybierz opcję instalacji> Mój Mac, a następnie kliknij przycisk Uruchom (przycisk w kształcie Play).
Teraz został pomyślnie zainstalowany (zignoruj ostrzeżenia).
Aby upewnić się, że Open Finder i folder goto / usr / local / lib i trzy pliki biblioteki GLFW będą już tam obecne (jeśli nie, otwórz folder kompilacji w folderze GLFW i przejdź do src / Debuguj skopiuj wszystkie pliki do / usr / local / lib )
Otwórz Finder i goto / usr / local / include, a folder GLFW będzie już tam obecny z dwoma plikami nagłówkowymi o nazwach glfw3.h i glfw3native.h
2. Zainstaluj GLEW
GLEW to wieloplatformowa biblioteka, która pomaga w wyszukiwaniu i ładowaniu rozszerzeń OpenGL. Zapewnia mechanizmy wykonywania w celu ustalenia, które rozszerzenia OpenGL są obsługiwane na platformie docelowej. Dotyczy tylko nowoczesnego OpenGL (wersja 3.2 i nowsza OpenGL, która wymaga określenia funkcji w czasie wykonywania). Aby zainstalować najpierw pobierz jego pliki ze strony glew.sourceforge.net
Wyodrębnij folder GLFW, a jego zawartość będzie wyglądać następująco.
Teraz otwórz Terminal, przejdź do folderu GLEW i wpisz następujące polecenia
make
sudo make install
make clean
Teraz GLEW został pomyślnie zainstalowany. Aby upewnić się, że jest zainstalowany, otwórz Finder, przejdź do / usr / local / include, a folder GL będzie tam już obecny z trzema plikami nagłówkowymi o nazwach glew.h , glxew.h i wglew.h
Otwórz Finder i przejdź do / usr / local / lib, a pliki bibliotek GLEW będą tam już obecne
3. Przetestuj i uruchom
Teraz z powodzeniem zainstalowaliśmy GLFW i GLEW. Czas na kodowanie. Otwórz Xcode i utwórz nowy projekt Xcode. Wybierz Narzędzie wiersza poleceń, a następnie przejdź do następnego i wybierz C ++ jako język.
Xcode utworzy nowy projekt wiersza poleceń.
Kliknij nazwę projektu, a następnie w zakładce Ustawienia kompilacji przełącz się z Podstawowa na Wszystkie , w sekcji Ścieżki wyszukiwania dodaj / usr / local / include w Ścieżki wyszukiwania nagłówka i dodaj / usr / local / lib w Bibliotece ścieżek wyszukiwania
Kliknij na nazwę projektu, a w zakładce Etapy budowania i pod Linków binarne Bibliotek dodać OpenGL.framework a także dodać niedawno utworzonych bibliotek GLFW i glew z / usr / local / lib
Teraz jesteśmy gotowi do kodowania w Modern Open GL 4.1 na macOS przy użyciu C ++ i Xcode. Poniższy kod utworzy okno OpenGL przy użyciu GLFW z wyjściem pustego ekranu.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
// Define main function
int main()
{
// Initialize GLFW
glfwInit();
// Define version and compatibility settings
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
// Create OpenGL window and context
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
// Check for window creation failure
if (!window)
{
// Terminate GLFW
glfwTerminate();
return 0;
}
// Initialize GLEW
glewExperimental = GL_TRUE; glewInit();
// Event loop
while(!glfwWindowShouldClose(window))
{
// Clear the screen to black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
// Terminate GLFW
glfwTerminate(); return 0;
}
Utwórz kontekst Opengl za pomocą Java i LWJGL 3.0
W tym przykładowym kodzie utworzymy Puste okno Opengl przy użyciu LWJGL 3.0+, które nie zawiera kroków do utworzenia projektu w twoim IDE
- Utwórz nazwę klasy WindowManager, która będzie zawierała cały kod płyty kotła do utworzenia okna kontekstowego OpenGL na ekranie
WindowManager.java
import org.lwjgl.glfw.*;
import static org.lwjgl.glfw.Callbacks.*;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;
/**
* Class Containing code related to inflating Opengl Window
*/
public class Displaymanager {
private static long window;
public static void createDisplay(){
// Setup an error callback. The default implementation
// will print the error message in System.err.
GLFWErrorCallback.createPrint(System.err).set();
// Initialize GLFW. Most GLFW functions will not work before doing this.
if ( !glfwInit() )
throw new IllegalStateException("Unable to initialize GLFW");
// Configure our window
glfwDefaultWindowHints(); // optional, the current window hints are already the default
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable
int WIDTH = 300;
int HEIGHT = 300;
// Create the window
window = glfwCreateWindow(WIDTH, HEIGHT, "Hello World!", NULL, NULL);
if ( window == NULL )
throw new RuntimeException("Failed to create the GLFW window");
// Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, true); // We will detect this in our rendering loop
});
// Get the resolution of the primary monitor
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center our window
glfwSetWindowPos(
window,
(vidmode.width() - WIDTH) / 2,
(vidmode.height() - HEIGHT) / 2
);
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
}
public static boolean isCloseRequested(){
return glfwWindowShouldClose(window);
}
public static void updateDisplay(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
public static void destroyDisplay(){
// Terminate GLFW and free the error callback
cleanUp();
glfwTerminate();
glfwSetErrorCallback(null).free();
}
private static void cleanUp() {
// Free the window callbacks and destroy the window
glfwFreeCallbacks(window);
glfwDestroyWindow(window);
}
}
- Następnie utwórz klasę zawierającą główną pętlę renderowania, która wywoła wszystkie utworzone funkcje powyżej
OpenGlMain.java
import org.lwjgl.opengl.GL;
import renderEngine.Displaymanager;
import static org.lwjgl.opengl.GL11.glClearColor;
/**
* Class to test the opengl Window
*/
public class OpenGlMain {
public static void main(String[] args) {
Displaymanager.createDisplay();
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
while (!Displaymanager.isCloseRequested()){
// Set the clear color
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
Displaymanager.updateDisplay();
}
Displaymanager.destroyDisplay();
}
}
W celu uzyskania dalszych szczegółów sprawdź oficjalny przewodnik LWJGL