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:

  1. Jakoś uzyskać typy wskaźników funkcji (zasadniczo prototypy funkcji)
  2. Zadeklaruj każdą funkcję, której chcielibyśmy użyć (z jej typem wskaźnika funkcji)
  3. 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.

wprowadź opis zdjęcia tutaj

I wybierz aplikację kakao wprowadź opis zdjęcia tutaj

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:

wprowadź opis zdjęcia tutaj

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. ostateczny wynik

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

Strona GLFW

Wyodrębnij folder GLFW, a jego zawartość będzie wyglądać następująco

Zawartość folderu GLFW

Pobierz i zainstaluj CMake, aby zbudować GLFW. Idź do www.cmake.org/download/ , pobierz CMake i zainstaluj dla MAC OS X

Strona pobierania CMake

Jeśli Xcode nie jest zainstalowany. Pobierz i zainstaluj Xcode z Mac App Store.

Xcode z Mac App Store

Utwórz nowy folder Zbuduj w folderze GLFW

Folder GLFW po utworzeniu folderu „Kompilacja”

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.

CMake Paths

Teraz kliknij przycisk Konfiguruj i wybierz Xcode jako generator z opcją Użyj domyślnych kompilatorów natywnych , a następnie kliknij Gotowe .

Makefile dla Xcode

Zaznacz opcję BUILD_SHARED_LIBS , a następnie ponownie kliknij przycisk Konfiguruj , a na koniec przycisk Generuj .

Wybierz BUILD_SHARED_LIBS

Po wygenerowaniu CMake powinien wyglądać tak

Ostateczne CMake

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.

Plik projektu Xcode

Wybierz opcję instalacji> Mój Mac, a następnie kliknij przycisk Uruchom (przycisk w kształcie Play).

Zainstaluj GLFW

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 )

Pliki Lib GLFW

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

Pliki nagłówkowe GLFW

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

Strona GLEW

Wyodrębnij folder GLFW, a jego zawartość będzie wyglądać następująco.

Zawartość folderu GLEW

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

Pliki nagłówka GLEW

Otwórz Finder i przejdź do / usr / local / lib, a pliki bibliotek GLEW będą tam już obecne

Pliki bibliotek GLEW

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.

Projekt Xcode

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

Wyszukaj ścieżki

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

Łącza binarne

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;
}

Puste okno OpenGL

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

wprowadź opis zdjęcia tutaj

  1. 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);
    }
}
  1. 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



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow