Suche…


Bemerkungen

OpenGL ist ein offener Standard für das Rendern von 2D- und 3D-Grafiken unter Verwendung von Grafikhardware. OpenGL wurde auf zahlreichen Plattformen implementiert, sodass Apps, die auf OpenGL abzielen, äußerst flexibel sind.

Versionen

Ausführung Veröffentlichungsdatum
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 2009-03-24
3.2 2009-08-03
3.3 2010-03-11
4,0 2010-03-11
4.1 2010-07-26
4.2 2011-08-08
4.3 2012-08-06
4.4 2013-07-22
4,5 2014-08-11

OpenGL erhalten

Eine der häufigsten falschen Vorstellungen von OpenGL ist, dass es sich um eine Bibliothek handelt, die aus Quellen von Drittanbietern installiert werden kann. Dieses Missverständnis führt zu vielen Fragen in der Form "Wie installiere ich OpenGL" oder "Wo soll das OpenGL SDK heruntergeladen werden?".

So findet OpenGL nicht den Weg in das Computersystem. OpenGL an sich ist lediglich eine Reihe von Spezifikationen, welchen Befehlen eine Implementierung folgen muss. Es kommt also auf die Implementierung an. Derzeit sind OpenGL-Implementierungen Teil der GPU-Treiber. Dies kann sich in der Zukunft ändern, wenn die neue GPU-Programmierschnittstelle es ermöglicht, OpenGL wirklich als Bibliothek zu implementieren. Im Moment ist dies jedoch eine Programmierschnittstelle für die Grafiktreiber.

Als OpenGL zum ersten Mal veröffentlicht wurde, fand die API in den ABI-Vertrag (Application Binary Interface) von Windows, Solaris und Linux (LSB-4 Desktop) neben Sun Irix ihren Ursprung. Apple folgte und integrierte OpenGL so tief in MacOS X, dass die verfügbare OpenGL-Version eng mit der installierten Version von MacOS X gekoppelt ist. Dies hat den bemerkenswerten Effekt, dass Systemprogrammierungsumgebungen für diese Betriebssysteme (dh die Compiler- und Linker-Toolchain, die diese Systeme gezielt ansprechen) auch OpenGL-API-Definitionen bereitstellen müssen . Daher ist es nicht erforderlich, ein SDK für OpenGL zu installieren. Es ist technisch möglich, OpenGL auf diesen Betriebssystemen zu programmieren, ohne dass ein dediziertes SDK installiert werden muss, vorausgesetzt, dass eine Build-Umgebung installiert ist, die auf die Ziel-ABI folgt.

Ein Nebeneffekt dieser strengen ABI-Regeln ist, dass die über die Bindungsschnittstelle bereitgestellte OpenGL-Version der kleinste gemeinsame Nenner ist, von dem auf der Zielplattform ausgeführte Programme möglicherweise als verfügbar gelten. Daher sind moderne OpenGL-Funktionen über den Erweiterungsmechanismus zugänglich, der ausführlich beschrieben wird.

Linux

In Linux ist es üblich, die Entwicklungspakete für verschiedene Aspekte des Systems zu unterteilen, so dass diese einzeln aktualisiert werden können. In den meisten Linux-Distributionen sind die Entwicklungsdateien für OpenGL in einem dedizierten Paket enthalten, das in der Regel von einem Meta-Paket für die Entwicklung von Desktop-Anwendungen abhängig ist. Die Installation der OpenGL-Entwicklungsdateien für Linux wird daher normalerweise bei der Installation des Desktop-Entwicklungs-Metapakets / der Desktop-Entwicklungspakete beachtet. *

Microsoft Windows

Die API-Bindungsbibliothek opengl32.dll (so benannt für 32-Bit- und 64-Bit-Versionen von Windows) wird seit Windows NT-4 und Windows 95B (beide ca. 1997) standardmäßig mit jeder Windows-Version ausgeliefert. Diese DLL bietet jedoch keine tatsächliche OpenGL-Implementierung (abgesehen von einem Software-Fallback, dessen einziger Zweck darin besteht, als Sicherheitsnetz für Programme zu fungieren, wenn keine andere OpenGL-Implementierung installiert ist). Diese DLL gehört zu Windows und darf nicht verändert oder verschoben werden! Moderne OpenGL-Versionen werden als Teil des sogenannten Installable Client Driver (ICD) ausgeliefert. Der Zugriff erfolgt über die Standard- opengl32.dll , die in jeder Windows-Version vorinstalliert ist. Intern wurde von Microsoft entschieden, dass Grafiktreiber, die über Windows Update installiert wurden, keine OpenGL-ICDs installieren / aktualisieren können. Neuinstallationen von Windows mit automatisch installierten Treibern bieten daher keine Unterstützung für moderne OpenGL-Funktionen. Um ein OpenGL-ICD mit modernen Funktionen zu erhalten, müssen Grafiktreiber direkt von der Website des GPU-Anbieters heruntergeladen und manuell installiert werden.

In Bezug auf die Entwicklung müssen keine zusätzlichen Schritte an sich gemacht werden. Alle C / C ++ - Compiler, die den Windows ABI-Spezifikationen entsprechen, werden mit Headern und dem Linker-Stub (opengl32.lib) ausgeliefert, die zum Erstellen und Verknüpfen von ausführbaren Dateien, die OpenGL verwenden, erforderlich sind.

Manuelles OpenGL-Setup unter Windows

Vollständiger Beispielcode am Ende

Windows-Komponenten für OpenGL

WGL

WGL (kann ausgesprochen werden Wiggle) steht für „Windows-GL“, wie in „eine Schnittstelle zwischen Windows und OpenGL“ - einer Reihe von Funktionen aus dem Windows - API mit OpenGL zu kommunizieren. WGL-Funktionen haben ein WGL- Präfix und ihre Token haben ein WGL_- Präfix.

Die auf Microsoft-Systemen unterstützte Standard-OpenGL-Version ist 1.1. Dies ist eine sehr alte Version (die neueste Version ist 4.5). Um die neuesten Versionen zu erhalten, müssen Sie die Grafiktreiber aktualisieren, aber Ihre Grafikkarte muss diese neuen Versionen unterstützen.

Eine vollständige Liste der WGL-Funktionen finden Sie hier .

Grafikgeräteschnittstelle (GDI)

GDI (heute auf GDI + aktualisiert) ist eine 2D-Zeichnungsschnittstelle, mit der Sie in Windows in ein Fenster zeichnen können. Sie benötigen GDI, um OpenGL zu initialisieren und die Interaktion mit OpenGL zuzulassen (ohne GDI selbst zu verwenden).

In GDI verfügt jedes Fenster über einen Gerätekontext (Device Context, DC) , mit dem das Zeichnungsziel beim Aufruf von Funktionen identifiziert wird (Sie übergeben es als Parameter). OpenGL verwendet jedoch einen eigenen Rendering-Kontext (RC) . Daher wird DC zum Erstellen von RC verwendet.


Grundeinstellung

Fenster erstellen

Um OpenGL zu erledigen, brauchen wir RC, und um RC zu bekommen, brauchen wir DC, und um DC zu bekommen, brauchen wir ein Fenster. Das Erstellen eines Fensters mithilfe der Windows-API erfordert mehrere Schritte. Dies ist eine grundlegende Routine. Für eine detailliertere Erklärung sollten Sie die andere Dokumentation lesen, da es sich nicht um die Verwendung der Windows-API handelt.

Dies ist ein Windows-Setup, daher muss Windows.h enthalten sein, und der Einstiegspunkt des Programms muss die WinMain Prozedur mit ihren Parametern sein. Das Programm muss auch mit opengl32.dll und gdi32.dll verknüpft sein (unabhängig davon, ob Sie sich auf einem 64- oder 32-Bit-System befinden).

Zuerst müssen wir unser Fenster anhand der WNDCLASS Struktur beschreiben. Es enthält Informationen zu dem Fenster, das wir erstellen möchten:

/* 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);
/* *************** */

Eine genaue Erklärung der Bedeutung der einzelnen Felder (und eine vollständige Liste der Felder) finden Sie in der MSDN-Dokumentation.

Dann können wir ein Fenster mit CreateWindowEx . Nachdem das Fenster erstellt wurde, können wir seinen DC erhalten:

/* 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);
/* ************* */

Schließlich müssen wir eine Meldungsschleife erstellen, die Fensterereignisse vom Betriebssystem empfängt:

/* 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
}
/* ********** */

Pixelformat

OpenGL muss einige Informationen zu unserem Fenster haben, wie z. B. Farbbitigkeit, Puffermethode usw. Dafür verwenden wir ein Pixelformat . Wir können dem Betriebssystem jedoch nur vorschlagen, welches Pixelformat wir benötigen, und das Betriebssystem wird das ähnlichste unterstützte Format bereitstellen. Wir haben keine direkte Kontrolle darüber. Deshalb wird es nur Deskriptor genannt .

/* 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);
/* *********************** */

Wir haben doppelte Pufferung im Feld dwFlags aktiviert. dwFlags müssen wir SwapBuffers aufrufen, um nach dem Zeichnen etwas zu sehen.

Rendering-Kontext

Danach können wir einfach unseren Rendering-Kontext erstellen:

/* RENDERING CONTEXT */
HGLRC rc = wglCreateContext(dc);
wglMakeCurrent(dc, rc);
/* ***************** */

Beachten Sie, dass jeweils nur ein Thread die RC verwenden kann. Wenn Sie es später von einem anderen Thread verwenden möchten, müssen wglMakeCurrent dort wglMakeCurrent aufrufen, um es erneut zu aktivieren (dies wird in dem Thread deaktiviert, in dem es gerade aktiv ist usw.).

OpenGL-Funktionen erhalten

OpenGL-Funktionen werden mit Funktionszeigern erhalten. Das allgemeine Verfahren ist:

  1. Erhalten Sie irgendwie Funktionszeiger-Typen (im Wesentlichen die Funktionsprototypen)
  2. Deklarieren Sie jede Funktion, die wir verwenden möchten (mit ihrem Funktionszeigertyp).
  3. Erhalten Sie die eigentliche Funktion

Betrachten Sie zum Beispiel 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" bedeutet "Zeiger auf Funktion", folgt dem Namen einer OpenGL-Funktion und "PROC" am Ende - das ist der übliche OpenGL-Funktionszeigertyp.)

So wird es unter Windows gemacht. Wie bereits erwähnt, liefert Microsoft nur OpenGL 1.1 aus. Zunächst können Funktionszeigertypen für diese Version gefunden werden, indem GL/gl.h . Danach deklarieren wir alle Funktionen, die wir verwenden möchten, wie oben gezeigt (wenn Sie dies in einer Header-Datei tun und sie als "extern" deklarieren, können wir sie alle verwenden, nachdem Sie sie einmal geladen haben, indem Sie sie einfach hinzufügen). Zum Schluss laden Sie die OpenGL 1.1-Funktionen durch Öffnen der DLL:

HMODULE gl_module = LoadLibrary(TEXT("opengl32.dll"));

/* Load all the functions here */
glBegin = (PFNGLBEGINPROC)GetProcAddress("glBegin");
// ...
/* *************************** */

FreeLibrary(gl_module);

Wir wollen jedoch wahrscheinlich etwas mehr als OpenGL 1.1. Windows liefert uns jedoch nicht die Funktion Prototypen oder exportierte Funktionen für alles darüber. Die Prototypen müssen aus der OpenGL-Registry bezogen werden . Es gibt drei Dateien, die für uns von Interesse sind: GL/glext.h , GL/glcorearb.h und GL/wglext.h .

Um das von Windows bereitgestellte GL/gl.h , benötigen wir GL/glext.h . Es enthält (wie von der Registry beschrieben) "OpenGL 1.2 und höher Kompatibilitätsprofil und Erweiterungsschnittstellen" (mehr zu Profilen und Erweiterungen später, wo wir sehen werden, dass es eigentlich keine gute Idee ist, diese beiden Dateien zu verwenden ).

Die eigentlichen Funktionen müssen von wglGetProcAddress abgerufen werden (keine Notwendigkeit, die DLL für diesen Typ zu öffnen, sie sind nicht dort, verwenden Sie einfach die Funktion). Damit können wir alle Funktionen von OpenGL 1.2 und höher (aber nicht 1.1) abrufen. Beachten Sie, dass der OpenGL-Rendering-Kontext erstellt und aktualisiert werden muss, damit er ordnungsgemäß funktioniert. So zum Beispiel 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");

Wir können tatsächlich einen Wrapper bauen get_proc Verfahren , das sowohl verwendet wglGetProcAddress und 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;
}

Zum Abschluss erstellen wir eine Header-Datei mit Funktionszeiger-Deklarationen wie folgt:

extern PFNGLCLEARCOLORPROC glClearColor;
extern PFNGLCLEARDEPTHPROC glClearDepth;
extern PFNGLCLEARPROC glClear;
extern PFNGLCLEARBUFFERIVPROC glClearBufferiv;
extern PFNGLCLEARBUFFERFVPROC glClearBufferfv;
// And so on...

Wir können dann eine Prozedur wie load_gl_functions , die wir nur einmal aufrufen und wie load_gl_functions funktionieren:

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");

Und du bist fertig! Fügen Sie einfach den Header mit den Funktionszeigern und dem GL hinzu.


Besseres Setup

OpenGL-Profile

OpenGL ist seit über 20 Jahren in der Entwicklung, und die Entwickler haben sich stets mit der Rückwärtskompatibilität (BC) beschäftigt . Das Hinzufügen einer neuen Funktion ist deshalb sehr schwierig. So wurde es 2008 in zwei "Profile" unterteilt. Kern und Kompatibilität Das Kernprofil bricht zugunsten von Leistungsverbesserungen und einigen neuen Funktionen. Es entfernt sogar einige alte Funktionen vollständig. Das Kompatibilitätsprofil behält BC mit allen Versionen bis 1.0 bei, und einige neue Funktionen sind nicht verfügbar. Es ist nur für alte Altsysteme geeignet. Alle neuen Anwendungen sollten das Kernprofil verwenden.

Aus diesem Grund gibt es ein Problem mit unserer Grundeinstellung - es stellt nur den Kontext bereit, der mit OpenGL 1.0 abwärtskompatibel ist. Das Pixelformat ist ebenfalls begrenzt. Es gibt einen besseren Ansatz, Erweiterungen zu verwenden.

OpenGL-Erweiterungen

Jede Erweiterung der ursprünglichen Funktionalität von OpenGL wird als Erweiterungen bezeichnet. Im Allgemeinen können sie entweder einige Dinge legalisieren, die vorher nicht möglich waren, den Parameterwertbereich erweitern, GLSL erweitern und sogar völlig neue Funktionen hinzufügen.

Es gibt drei Hauptgruppen von Erweiterungen: Hersteller, EXT und ARB. Herstellererweiterungen stammen von einem bestimmten Anbieter und haben eine herstellerspezifische Kennzeichnung, wie AMD oder NV. EXT-Erweiterungen werden von mehreren Anbietern erstellt, die zusammenarbeiten. Nach einiger Zeit können sie zu ARB-Erweiterungen werden, die alle offiziell unterstützten und von ARB zugelassenen sind.

Um Funktionszeigertypen und Funktionsprototypen aller Erweiterungen zu erhalten, und wie bereits erwähnt, alle Funktionszeigertypen ab OpenGL 1.2 und höher , muss man die Header-Dateien von der OpenGL-Registry herunterladen. Wie bereits erwähnt, ist es für neue Anwendungen besser, ein Kernprofil zu verwenden. Daher ist es vorzuziehen, GL/glcorearb.h anstelle von GL/gl.h und GL/glext.h (wenn Sie GL/glcorearb.h dann don nicht GL/gl.h ).

Es gibt auch Erweiterungen für die WGL in GL/wglext.h . Die Funktion zum Abrufen der Liste aller unterstützten Erweiterungen ist beispielsweise eine Erweiterung selbst, die wglGetExtensionsStringARB (sie gibt eine große Zeichenfolge mit einer durch Leerzeichen getrennten Liste aller unterstützten Erweiterungen zurück).

Erweiterungen werden auch über wglGetProcAddress , sodass wir unseren Wrapper einfach wie zuvor verwenden können.

Erweiterte Pixelformat- und Kontexterstellung

Die Erweiterung WGL_ARB_pixel_format ermöglicht die erweiterte Erstellung des Pixelformats. Im Gegensatz zu früher verwenden wir keine Struktur. Stattdessen übergeben wir die Liste der gewünschten Attribute.

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

In ähnlicher WGL_ARB_create_context ermöglicht die Erweiterung WGL_ARB_create_context die Erstellung des erweiterten Kontexts:

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

Eine genaue Erläuterung der Parameter und Funktionen finden Sie in der OpenGL-Spezifikation.

Warum haben wir nicht einfach mit ihnen angefangen? Nun, das liegt daran, dass die Erweiterungen dies ermöglichen, und um Erweiterungen zu erhalten, benötigen wir wglGetProcAddress jedoch nur mit einem aktiven gültigen Kontext. Bevor wir also den gewünschten Kontext erstellen können, müssen wir bereits einen Kontext aktiv haben, der normalerweise als Dummy-Kontext bezeichnet wird .

Windows erlaubt jedoch nicht, das Pixelformat eines Fensters mehr als einmal einzustellen. Aus diesem Grund muss das Fenster zerstört und neu erstellt werden, um neue Dinge anzuwenden:

wglMakeCurrent(dc, NULL);
wglDeleteContext(rc);
ReleaseDC(window_handle, dc);
DestroyWindow(window_handle);

// Recreate the window...

Vollständiger Beispielcode:

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

Kompiliert mit g++ GLExample.cpp -lopengl32 -lgdi32 mit MinGW / Cygwin oder cl GLExample.cpp opengl32.lib gdi32.lib user32.lib mit MSVC-Compiler. Stellen Sie jedoch sicher, dass sich die Header der OpenGL-Registrierung im Include-Pfad befinden. Wenn nicht, verwenden Sie das Flag -I für g++ oder /I für cl , um dem Compiler mitzuteilen, wo sie sich befinden.

Erstellen von OpenGL 4.1 mit C ++ und Cocoa

Hinweis: In diesem Beispiel wird Objective-c verwendet. In diesem Beispiel werden wir einen Wrapper für C ++ erstellen. Machen Sie sich also keine Sorgen.

Starten Sie zuerst Xcode und erstellen Sie ein Projekt.

Geben Sie hier die Bildbeschreibung ein

Und wählen Sie eine Cocoa-Anwendung Geben Sie hier die Bildbeschreibung ein

Löschen Sie alle Quellen mit Ausnahme der Datei "Info.plist". (Ihre App funktioniert nicht ohne.)

Erstellen Sie 4 neue Quelldateien: Eine Objective-C ++ - Datei und einen Header (ich habe meine MacApp genannt) Eine C ++ - Klasse (Ich habe meine aufgerufen (Anwendung)

Klicken Sie oben links (mit dem Projektnamen) darauf und fügen Sie verknüpfte Frameworks und Bibliotheken hinzu. Fügen Sie Folgendes hinzu: OpenGL.Framework AppKit.Framework GLKit.Framework

Dein Projekt wird wahrscheinlich so aussehen:

Geben Sie hier die Bildbeschreibung ein

NSApplication ist die Hauptklasse, die Sie beim Erstellen einer MacOS-App verwenden. Sie können Fenster registrieren und Ereignisse abfangen.

Wir möchten (unser eigenes) Fenster bei der NSApplication registrieren. Erstellen Sie zunächst in Ihrem Objective-C ++ - Header eine Objective-C-Klasse, die von NSWindow erbt und NSApplicationDelegate implementiert. NSWindow benötigt einen Zeiger auf die C ++ - Anwendung, eine OpenGL-Ansicht und einen Zeitgeber für die Zeichenschleife

//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

Wir nennen das aus der Hauptsache mit

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

Die Implementierung unseres Fensters ist eigentlich ganz einfach. Zuerst erklären wir unseren Überblick und fügen einen globalen Objective-C-Boolean hinzu, wenn das Fenster geschlossen wird.

#import "MacApp.h"

@implementation MacApp

@synthesize glView;

BOOL shouldStop = NO;

Nun zum Konstruktor. Meine Präferenz ist die Verwendung von 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;
}

Okay ... jetzt haben wir eigentlich eine lauffähige App .. Vielleicht sehen Sie einen schwarzen Bildschirm oder flackern.

Beginnen wir mit dem Zeichnen eines fantastischen Dreiecks (in C ++)

Mein Anwendungsheader

#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 */

Die Umsetzung:

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

Jetzt müssen wir nur noch einmal update aufrufen (wenn Sie etwas verschieben möchten). Implementieren Sie es in Ihrer Objective-C-Klasse

-(void) drawLoop:(NSTimer*) timer{

if(shouldStop){
    [self close];
    return;
}
if([self isVisible]){
  
       appInstance->update();
    [glView update];
    [[glView openGLContext] flushBuffer];
}

}

Fügen Sie diese Methode bei der Implementierung Ihrer Objective-C-Klasse hinzu:

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
    [NSTimer scheduledTimerWithTimeInterval:0.000001 target:self selector:@selector(drawLoop:) userInfo:nil repeats:YES];
}

Dadurch wird die Aktualisierungsfunktion Ihrer C ++ - Klasse immer und immer wieder aufgerufen (jeweils 0,000001 Sekunden).

Zum Abschluss schließen wir das Fenster, wenn der Schließen-Button gedrückt wird:

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication     *)theApplication{
    return YES;
}

- (void)applicationWillTerminate:(NSNotification *)aNotification{
    shouldStop = YES;
}

Herzlichen Glückwunsch, jetzt haben Sie ein tolles Fenster mit einem OpenGL-Dreieck ohne Drittanbieter-Frameworks. Endergebnis

Plattformübergreifende OpenGL-Kontexterstellung (mit SDL2)

Erstellen eines Fensters mit OpenGL-Kontext (Erweiterung durch 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;
}

Setup moderne OpenGL 4.1 auf macOS (Xcode, GLFW und GLEW)

1. Installieren Sie GLFW

Zunächst müssen Sie ein OpenGL-Fenster erstellen. GLFW ist eine Open Source-Bibliothek mit mehreren Plattformen zum Erstellen von Fenstern mit OpenGL. Zur Installation von GLFW müssen zunächst die Dateien von www.glfw.org heruntergeladen werden

GLFW-Webseite

Extrahieren Sie den GLFW-Ordner und der Inhalt wird so aussehen

GLFW-Ordnerinhalt

Laden Sie CMake herunter und installieren Sie es, um GLFW zu erstellen. Gehen Sie zu www.cmake.org/download/ , laden Sie CMake herunter und installieren Sie es für MAC OS X

CMake-Downloadseite

Wenn Xcode nicht installiert ist. Laden Sie Xcode aus dem Mac App Store herunter und installieren Sie es.

Xcode aus dem Mac App Store

Erstellen Sie einen neuen Ordner Build innerhalb des GLFW-Ordners

GLFW-Ordner nach dem Erstellen des "Build" -Ordners

Öffnen Sie CMake und klicken Sie auf die Schaltfläche Browse Source ( Quelle durchsuchen), um den GLFW-Ordner auszuwählen (stellen Sie sicher, dass sich CMakeLists.txt befindet) in diesem Ordner. Klicken Sie anschließend auf die Schaltfläche Browse Build , und wählen Sie den im vorherigen Schritt neu erstellten Build- Ordner aus.

CMake-Pfade

Klicken Sie auf die Schaltfläche Konfigurieren und wählen Sie Xcode als Generator mit der Option Standarde Compiler verwenden aus , und klicken Sie auf Fertig .

Makefile für Xcode

Kreuzen Sie die Option BUILD_SHARED_LIBS an und klicken Sie erneut auf die Schaltfläche Konfigurieren und anschließend auf die Schaltfläche Generieren .

Wählen Sie BUILD_SHARED_LIBS

Nach der Generierung sollte CMake so aussehen

Final CMake

Öffnen Sie den Finder und gehen Sie zu / usr . Erstellen Sie einen lokalen Ordnernamen , falls noch nicht vorhanden. Öffnen Sie den lokalen Ordner und erstellen Sie zwei Ordner include und lib, falls noch nicht vorhanden.

Öffnen Sie nun den GLFW-Ordner und gehen Sie zu Build (wo CMake die Dateien erstellt hatte). Öffnen Sie die Datei GLFW.xcodeproj in Xcode.

Xcode-Projektdatei

Wählen Sie " Installieren"> "Mein Mac" und klicken Sie auf " Ausführen" (Schaltfläche "Form abspielen").

Installieren Sie GLFW

Es ist jetzt erfolgreich installiert (ignorieren Sie die Warnungen).

Um sicherzustellen, dass der Ordner "Open Finder" und "goto / usr / local / lib " sowie drei GLFW-Bibliotheksdateien bereits vorhanden sind (andernfalls öffnen Sie den Ordner " Build " innerhalb des GLFW-Ordners), und wechseln Sie zu src / Debug. Kopieren Sie alle Dateien nach / usr / local / lib )

GLFW Lib-Dateien

Öffnen Sie den Finder und gehen Sie nach / usr / local / include. Dort ist bereits ein GLFW-Ordner mit zwei Header-Dateien mit den Namen glfw3.h und glfw3native.h vorhanden

GLFW-Header-Dateien

2. Installieren Sie GLEW

GLEW ist eine plattformübergreifende Bibliothek, die beim Abfragen und Laden von OpenGL-Erweiterungen hilft. Es stellt Laufzeitmechanismen bereit, um zu bestimmen, welche OpenGL-Erweiterungen auf der Zielplattform unterstützt werden. Nur für moderne OpenGL (OpenGL-Version 3.2 und höher müssen Funktionen zur Laufzeit bestimmt werden). Zum Installieren laden Sie zunächst die Dateien von glew.sourceforge.net herunter

GLEW-Webseite

Extrahieren Sie den GLFW-Ordner und der Inhalt wird so aussehen.

GLEW-Ordnerinhalt

Öffnen Sie nun das Terminal, navigieren Sie zum GLEW-Ordner und geben Sie die folgenden Befehle ein

make
sudo make install 
make clean

Nun ist GLEW erfolgreich installiert. Um sicherzustellen, dass es installiert ist, öffnen Sie den Finder, gehen Sie zu / usr / local / include. Dort befindet sich bereits ein GL-Ordner mit drei Header-Dateien mit den Namen glew.h , glxew.h und wglew.h

GLEW-Header-Dateien

Öffnen Sie den Finder und gehen Sie zu / usr / local / lib. Dort sind bereits GLEW-Bibliotheksdateien vorhanden

GLEW-Bibliotheksdateien

3. Testen und ausführen

Nun haben wir GLFW und GLEW erfolgreich installiert. Es ist Zeit zu codieren. Öffnen Sie Xcode und erstellen Sie ein neues Xcode-Projekt. Wählen Sie das Befehlszeilentool aus und fahren Sie dann mit C ++ als Sprache fort.

Xcode-Projekt

Xcode erstellt ein neues Befehlszeilenprojekt.

Klicken Sie auf den Projektnamen, und wechseln Sie auf der Registerkarte Build Settings von Basic zu All . Fügen Sie im Abschnitt Search Paths / usr / local / include in den Header-Suchpfaden und in der Library- Suchpfad / usr / local / lib hinzu

Suchpfade

Klicken Sie auf Projektnamen, und unter Übersetzungs Phasen Registerkarte und unter Verknüpfung mit Binary Bibliotheken hinzufügen OpenGL.framework und auch hinzufügen , kürzlich erstellt GLFW und GLEW Bibliotheken von / usr / local / lib

Link-Binärdateien

Jetzt können wir in Modern Open GL 4.1 unter macOS mit C ++ und Xcode programmieren. Mit dem folgenden Code wird ein OpenGL-Fenster mit GLFW mit leerer Bildschirmausgabe erstellt.

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

Leeres OpenGL-Fenster

Erstellen Sie Opengl Context mit Java und LWJGL 3.0

In diesem Beispielcode erstellen wir ein leeres Opengl-Fenster mit LWJGL 3.0+. Dieses enthält keine Schritte zum Erstellen des Projekts in Ihrer IDE

Geben Sie hier die Bildbeschreibung ein

  1. Erstellen Sie einen Klassennamen WindowManager, der den gesamten Kesselplattencode zum Erstellen eines Opengl-Kontextfensters auf dem Bildschirm enthält

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. Als Nächstes erstellen Sie eine Klasse, die eine Haupt-Rendering-Schleife enthält, die alle zuvor erstellten Funktionen aufruft

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

Weitere Einzelheiten finden Sie im offiziellen LWJGL-Leitfaden



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow