openglAan de slag met opengl


Opmerkingen

OpenGL is een open standaard voor het renderen van 2D- en 3D-graphics met grafische hardware. OpenGL is geïmplementeerd op een verbluffend scala aan platforms waardoor apps die zich richten op OpenGL uiterst flexibel zijn.

versies

Versie Publicatiedatum
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

Maak Opengl-context met Java en LWJGL 3.0

In deze voorbeeldcode maken we een leeg Opengl-venster met LWJGL 3.0+, dit bevat geen stappen om het project in uw IDE te maken

voer hier de afbeeldingsbeschrijving in

  1. Maak een klassenaam WindowManager die alle ketelplaatcode bevat voor het maken van een opengl-contextvenster op het scherm

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. Maak vervolgens een klasse met de hoofdrenderingslus, die alle hierboven gemaakte functies aanroept

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

Kijk voor meer informatie op de officiële LWJGL-gids

OpenGL 4.1 maken met C ++ en Cocoa

Opmerking: in dit voorbeeld komt Objective-c voor. We zullen in dit voorbeeld een Wrapper maken voor C ++, dus maak je daar geen zorgen over.

Start eerst Xcode en maak een project.

voer hier de afbeeldingsbeschrijving in

En selecteer een Cocoa-applicatie voer hier de afbeeldingsbeschrijving in

Verwijder alle bronnen behalve het bestand Info.plist. (Uw app werkt niet zonder)

Maak 4 nieuwe bronbestanden: een Objective-c ++ bestand en header (ik heb mine MacApp genoemd) Een C ++ klasse (ik heb mine genoemd (Toepassing)

Klik linksboven (met de projectnaam) erop en voeg gekoppelde frameworks en bibliotheken toe. Toevoegen: OpenGL.Framework AppKit.Framework GLKit.Framework

Uw project zal er waarschijnlijk zo uitzien:

voer hier de afbeeldingsbeschrijving in

NSApplication is de hoofdklasse die u gebruikt bij het maken van een MacOS-app. Hiermee kunt u vensters registreren en evenementen vastleggen.

We willen (ons eigen) venster registreren bij de NSApplication. Maak eerst in uw objectief-c ++ kop een objectief-c klasse die van NSWindow erft en NSApplicationDelegate implementeert Het NSWindow heeft een pointer nodig naar de C ++ applicatie, een openGL View en een timer voor de tekenlus

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

We noemen dit vanaf de hoofdregel met

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

De implementatie van ons venster is eigenlijk vrij eenvoudig. Eerst verklaren we met onze glview en voegen we een globale objectieve c boolean toe wanneer het venster zou moeten sluiten.

#import "MacApp.h"

@implementation MacApp

@synthesize glView;

BOOL shouldStop = NO;
 

Nu voor de constructeur. Mijn voorkeur gaat uit naar het gebruik van 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;
}
 

Oké ... nu hebben we eigenlijk een app die kan worden uitgevoerd .. Misschien zie je een zwart scherm of flikkeren.

Laten we beginnen met het tekenen van een geweldige driehoek. (In c ++)

Mijn applicatiekopbal

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

De implementatie:

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

Nu hoeven we alleen maar update steeds opnieuw aan te roepen (als je iets wilt verplaatsen) Implementeer in je Objective-C klasse

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

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

}
 

En voeg de deze methode toe bij de implementatie van uw doelstelling-c klasse:

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

dit roept de updatefunctie van je c ++ -klasse keer op keer op (elke 0,000001 seconden om precies te zijn)

Om te eindigen sluiten we het venster wanneer de sluitknop wordt ingedrukt:

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

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

Gefeliciteerd, nu heb je een geweldig venster met een OpenGL-driehoek zonder frameworks van derden. eindresultaat

Cross Platform OpenGL context creatie (met behulp van SDL2)

Een venster met OpenGL-context maken (extensie laden via 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;
}

Handmatige OpenGL-instelling op Windows

Volledige voorbeeldcode opgenomen aan het einde

Windows-componenten voor OpenGL

WGL

WGL (kan worden uitgesproken als wiggle ) staat voor "Windows-GL", zoals in "een interface tussen Windows en OpenGL" - een set functies uit de Windows API om te communiceren met OpenGL. WGL-functies hebben een WGL- voorvoegsel en de tokens hebben een WGL_- voorvoegsel.

De standaard OpenGL-versie die wordt ondersteund op Microsoft-systemen is 1.1. Dat is een zeer oude versie (de meest recente versie is 4.5). De manier om de meest recente versies te krijgen, is door uw grafische stuurprogramma's bij te werken, maar uw grafische kaart moet die nieuwe versies ondersteunen.

Een volledige lijst met WGL-functies vindt u hier .

Grafische apparaatinterface (GDI)

GDI (vandaag bijgewerkt naar GDI +) is een 2D-tekeninterface waarmee u in Windows op een venster kunt tekenen. U hebt GDI nodig om OpenGL te initialiseren en ermee te kunnen communiceren (maar zal GDI zelf niet gebruiken).

In GDI heeft elk venster een apparaatcontext (DC) die wordt gebruikt om het tekeningdoel te identificeren bij het aanroepen van functies (u geeft dit door als parameter). OpenGL gebruikt echter zijn eigen renderingcontext (RC) . Dus, DC zal worden gebruikt om RC te creëren.


Basisopstelling

Een venster maken

Dus om dingen te doen in OpenGL hebben we RC nodig, en om RC te krijgen hebben we DC nodig, en om DC te krijgen hebben we een venster nodig. Een venster maken met behulp van de Windows API vereist verschillende stappen. Dit is een basisroutine, dus voor een meer gedetailleerde uitleg moet u andere documentatie raadplegen, omdat dit niet gaat over het gebruik van de Windows API.

Dit is een Windows-installatie, dus Windows.h moet worden opgenomen en het toegangspunt van het programma moet de WinMain procedure zijn met zijn parameters. Het programma moet ook worden gekoppeld aan opengl32.dll en aan gdi32.dll (ongeacht of u een 64- of 32-bits systeem gebruikt).

Eerst moeten we ons venster beschrijven met behulp van de WNDCLASS structuur. Het bevat informatie over het venster dat we willen maken:

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

Raadpleeg MSDN-documentatie voor een precieze uitleg van de betekenis van elk veld (en voor een volledige lijst met velden).

Vervolgens kunnen we een venster maken met CreateWindowEx . Nadat het venster is gemaakt, kunnen we de DC verkrijgen:

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

Ten slotte moeten we een berichtenlus maken die venstergebeurtenissen van het besturingssysteem ontvangt:

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

Pixel formaat

OpenGL moet enige informatie over ons venster kennen, zoals kleurbitness, buffermethode, enzovoort. Hiervoor gebruiken we een pixelindeling . We kunnen het besturingssysteem echter alleen maar voorstellen welk pixelformaat we nodig hebben, en het besturingssysteem levert het meest vergelijkbare ondersteunde formaat, we hebben er geen directe controle over. Daarom wordt het alleen een descriptor genoemd .

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

We hebben dubbele buffering ingeschakeld in het veld dwFlags , dus we moeten SwapBuffers aanroepen om de dingen na het tekenen te zien.

Rendering context

Daarna kunnen we eenvoudig onze renderingcontext maken:

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

Merk op dat slechts één draad tegelijkertijd de RC kan gebruiken. Als je het later uit een andere thread wilt gebruiken, moet wglMakeCurrent daar wglMakeCurrent om het opnieuw te activeren (dit zal het deactiveren op de thread die momenteel actief is, enzovoort).

OpenGL-functies verkrijgen

OpenGL-functies worden verkregen met behulp van functie-aanwijzers. De algemene procedure is:

  1. Op de een of andere manier verkrijgt u functiepointertypen (in wezen de functieprototypes)
  2. Verklaar elke functie die we willen gebruiken (met het type functiepointer)
  3. Verkrijg de eigenlijke functie

Overweeg bijvoorbeeld 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" betekent "pointer to function", volgt dan de naam van een OpenGL-functie, en "PROC" aan het einde - dat is de gebruikelijke naam van het OpenGL-functiepointertype.)

Hier is hoe het gedaan is op Windows. Zoals eerder vermeld, levert Microsoft alleen OpenGL 1.1. Allereerst kunnen functiepointertypen voor die versie worden gevonden door GL/gl.h . Daarna verklaren we alle functies die we van plan zijn te gebruiken zoals hierboven getoond (door dat in een header-bestand te doen en ze "extern" te verklaren, zouden we ze allemaal kunnen gebruiken nadat ze eenmaal zijn geladen, alleen door het op te nemen). Ten slotte wordt het laden van de OpenGL 1.1-functies gedaan door de DLL te openen:

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

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

FreeLibrary(gl_module);
 

We willen echter waarschijnlijk iets meer dan OpenGL 1.1. Maar Windows geeft ons niet de functieprototypes of geëxporteerde functies voor iets daarboven. De prototypes moeten worden verkregen van het OpenGL-register . Er zijn drie interessante bestanden voor ons: GL/glext.h , GL/glcorearb.h en GL/wglext.h .

Om GL/gl.h geleverd door Windows te voltooien, hebben we GL/glext.h . Het bevat (zoals beschreven door het register) "OpenGL 1.2 en hoger compatibiliteitsprofiel en extensie-interfaces" (later meer over profielen en extensies, waar we zullen zien dat het eigenlijk geen goed idee is om die twee bestanden te gebruiken ).

De eigenlijke functies moeten worden verkregen door wglGetProcAddress (het is niet nodig om de DLL voor deze man te openen, ze zijn er niet, gebruik gewoon de functie). Hiermee kunnen we alle functies van OpenGL 1.2 en hoger ophalen (maar niet 1.1). Merk op dat, om het goed te laten werken, de OpenGL-renderingcontext moet worden gecreëerd en actueel gemaakt . Dus bijvoorbeeld 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");
 

We kunnen een wrapper get_proc procedure bouwen die zowel wglGetProcAddress als 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;
}
 

Dus om af te ronden, zouden we een headerbestand maken vol met functie pointer verklaringen zoals deze:

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

We kunnen vervolgens een procedure maken zoals load_gl_functions die we slechts één keer aanroepen en werkt als volgt:

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

En je bent helemaal klaar! Neem gewoon de koptekst op met de functiewijzers en GL weg.


Betere installatie

OpenGL-profielen

OpenGL is al meer dan 20 jaar in ontwikkeling en de ontwikkelaars waren altijd streng in achterwaartse compatibiliteit (BC) . Daarom is het toevoegen van een nieuwe functie erg moeilijk. Zo werd het in 2008 gescheiden in twee "profielen". Core en compatibiliteit . Kernprofiel breekt BC ten gunste van prestatieverbeteringen en enkele van de nieuwe functies. Het verwijdert zelfs enkele oude functies volledig. Compatibiliteitsprofiel onderhoudt BC met alle versies tot 1.0, en sommige nieuwe functies zijn niet beschikbaar. Het moet alleen worden gebruikt voor oude, oudere systemen, alle nieuwe toepassingen moeten het kernprofiel gebruiken.

Daarom is er een probleem met onze basisconfiguratie - het biedt alleen de context die achterwaarts compatibel is met OpenGL 1.0. Het pixelformaat is ook beperkt. Er is een betere aanpak, met behulp van extensies.

OpenGL-extensies

Elke toevoeging aan de oorspronkelijke functionaliteit van OpenGL wordt extensies genoemd. Over het algemeen kunnen ze sommige dingen legaal maken die nog niet eerder waren, het bereik van de parameterwaarden uitbreiden, GLSL uitbreiden en zelfs volledig nieuwe functionaliteit toevoegen.

Er zijn drie grote groepen extensies: leverancier, EXT en ARB. Leveranciersextensies komen van een specifieke leverancier en ze hebben een leverancierspecifiek merk, zoals AMD of NV. EXT-extensies worden gemaakt door verschillende leveranciers die samenwerken. Na enige tijd kunnen dit ARB-extensies worden, dit zijn alle officieel ondersteunde en door ARB goedgekeurde.

Om functiepointertypen en functieprototypes van alle extensies te verkrijgen en zoals eerder vermeld, alle functiepointertypen van OpenGL 1.2 en hoger , moet u de header-bestanden downloaden van het OpenGL-register . Zoals besproken, is het voor nieuwe toepassingen beter om het kernprofiel te gebruiken, dus het is beter om GL/glcorearb.h plaats van GL/gl.h en GL/glext.h (als je GL/glcorearb.h dan don GL/gl.h ) niet GL/gl.h .

Er zijn ook uitbreidingen voor de WGL, in GL/wglext.h . De functie voor het wglGetExtensionsStringARB de lijst met alle ondersteunde extensies is bijvoorbeeld eigenlijk een extensie zelf, de wglGetExtensionsStringARB (deze retourneert een grote tekenreeks met een door spaties gescheiden lijst van alle ondersteunde extensies).

Het verkrijgen van extensies wordt ook afgehandeld via wglGetProcAddress , dus we kunnen onze wrapper net als voorheen gebruiken.

Geavanceerde pixelindeling en contextcreatie

De extensie WGL_ARB_pixel_format biedt ons de mogelijkheid om geavanceerde pixelformaten te maken. Anders dan voorheen gebruiken we geen struct. In plaats daarvan passeren we de lijst met gewenste kenmerken.

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

Op dezelfde manier biedt de extensie WGL_ARB_create_context ons de geavanceerde contextcreatie:

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

Raadpleeg de OpenGL-specificatie voor een precieze uitleg van de parameters en functies.

Waarom zijn we niet net met hen begonnen? Nou, dat komt omdat de extensies ons in staat stellen dit te doen, en om extensies te krijgen hebben we wglGetProcAddress nodig, maar dat werkt alleen met een actieve geldige context. Dus voordat we in staat zijn om de context te creëren die we willen, moeten we al enige context actief hebben, en dit wordt meestal een dummy context genoemd .

Windows staat echter niet toe om het pixelformaat van een venster meer dan één keer in te stellen. Daarom moet het venster worden vernietigd en opnieuw worden gemaakt om nieuwe dingen toe te passen:

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

// Recreate the window...
 

Volledige voorbeeldcode:

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

Gecompileerd met g++ GLExample.cpp -lopengl32 -lgdi32 met MinGW / Cygwin of cl GLExample.cpp opengl32.lib gdi32.lib user32.lib met MSVC-compiler. Zorg er echter voor dat de headers van het OpenGL-register zich in het include-pad bevinden. Zo niet, gebruik dan de vlag -I voor g++ of /I voor cl om de compiler te vertellen waar ze zijn.

OpenGL verkrijgen

Een van de meest voorkomende misvattingen over OpenGL is dat het een bibliotheek is die kan worden geïnstalleerd vanuit bronnen van derden. Deze misvatting leidt tot veel vragen in de vorm "Hoe installeer ik OpenGL" of "Waar kan ik de OpenGL SDK downloaden".

Dit is niet hoe OpenGL de weg vindt naar een computersysteem. OpenGL is op zichzelf slechts een set specificaties voor welke opdrachten een implementatie moet volgen. Dus het is de implementatie die ertoe doet. En voorlopig maken OpenGL-implementaties deel uit van de GPU-stuurprogramma's. Dit kan in de toekomst veranderen, wanneer de nieuwe GPU-programmeerinterface het mogelijk maakt om OpenGL echt als een bibliotheek te implementeren, maar voor nu is het een programmeer-API voor de grafische stuurprogramma's.

Toen OpenGL voor het eerst werd uitgebracht, vond de API op de een of andere manier zijn weg naar het ABI-contract (Application Binary Interface) van Windows, Solaris en Linux (LSB-4 Desktop) naast de oorsprong Sun Irix. Apple volgde en integreerde OpenGL zelfs zo diep in MacOS X, dat de beschikbare OpenGL-versie nauw is gekoppeld aan de geïnstalleerde versie van MacOS X. Dit heeft het opmerkelijke effect, dat systeemprogrammeeromgevingen voor deze besturingssystemen (dwz de compiler en linker toolchain die native op deze systemen is gericht) ook OpenGL API-definities moeten leveren. Het is dus niet nodig om een SDK voor OpenGL te installeren. Het is technisch mogelijk om OpenGL op deze besturingssystemen te programmeren zonder de noodzaak om een speciale SDK te installeren, ervan uitgaande dat een buildomgeving volgens de beoogde ABI is geïnstalleerd.

Een neveneffect van deze strikte ABI-regels is dat de OpenGL-versie die wordt weergegeven via de bindende interface een kleinste gemene deler is die programma's die op het doelplatform worden uitgevoerd mogelijk verwachten. Daarom zijn moderne OpenGL-functies toegankelijk via het uitbreidingsmechanisme, dat afzonderlijk in detail wordt beschreven.

Linux

In Linux is het vrij gebruikelijk om de ontwikkelingspakketten voor verschillende aspecten van het systeem te compartimenteren, zodat deze afzonderlijk kunnen worden bijgewerkt. In de meeste Linux-distributies bevinden de ontwikkelingsbestanden voor OpenGL zich in een speciaal pakket, dat meestal afhankelijk is van een meta-pakket voor de ontwikkeling van desktopapplicaties. Dus het installeren van de OpenGL-ontwikkelingsbestanden voor Linux wordt meestal verzorgd met de installatie van het / de meta-pakket (s) voor desktopontwikkeling. *

Microsoft Windows

De API-bindende bibliotheek opengl32.dll (zo genoemd voor zowel 32-bits als 64-bits versies van Windows) wordt standaard geleverd bij elke Windows-versie sinds Windows NT-4 en Windows 95B (beide ca. 1997). Deze DLL biedt echter geen daadwerkelijke OpenGL-implementatie (afgezien van een software-fallback met als enig doel om te fungeren als een vangnet voor programma's als er geen andere OpenGL-implementatie is geïnstalleerd). Deze DLL is van Windows en mag niet worden gewijzigd of verplaatst! Moderne OpenGL-versies worden geleverd als onderdeel van de zogenaamde Installable Client Driver (ICD) en zijn toegankelijk via de standaard opengl32.dll die vooraf wordt geïnstalleerd bij elke versie van Windows. Intern werd echter besloten door Microsoft dat grafische stuurprogramma's die via Windows Update waren geïnstalleerd, geen OpenGL ICD zouden installeren / bijwerken. Als zodanig ontbreken nieuwe installaties van Windows met automatisch geïnstalleerde stuurprogramma's geen ondersteuning voor moderne OpenGL-functies. Om een OpenGL ICD met moderne functies te verkrijgen, moeten grafische stuurprogramma's rechtstreeks van de website van de GPU-leverancier worden gedownload en handmatig worden geïnstalleerd.

Ten aanzien van de ontwikkeling hoeven op zich geen extra stappen te worden gezet. Alle C / C ++ -compilers volgens de Windows ABI-specificaties worden geleverd met headers en de linker stub (opengl32.lib) die nodig zijn om uitvoerbare bestanden te bouwen en te koppelen die gebruik maken van OpenGL.

Modern OpenGL 4.1 instellen op macOS (Xcode, GLFW en GLEW)

1. Installeer GLFW

De eerste stap is om een OpenGL-venster te maken. GLFW is een Open Source, multi-platformbibliotheek voor het maken van vensters met OpenGL, om GLFW te installeren, download eerst de bestanden van www.glfw.org

GLFW-webpagina

Pak de GLFW-map uit en de inhoud ziet er zo uit

Inhoud GLFW-map

Download en installeer CMake om GLFW te bouwen. Ga naar www.cmake.org/download/ , download CMake en installeer voor MAC OS X

CMake Downloads webpagina

Als Xcode niet is geïnstalleerd. Download en installeer Xcode van Mac App Store.

Xcode van Mac App Store

Maak een nieuwe map Bouwen in de GLFW-map

GLFW-map na het maken van de map "Build"

Open CMake, klik op Bladeren in bronknop om de GLFW-map te selecteren (zorg ervoor dat CMakeLists.txt) zich in die map bevindt. Klik daarna op Browse Build- knop en selecteer de nieuw gemaakte Build- map in de vorige stap.

CMake Paths

Klik nu op de knop Configureren en selecteer Xcode als generator met de optie Standaard native compilers gebruiken en klik op Gereed .

Makefile voor Xcode

Vink de optie BUILD_SHARED_LIBS aan en klik vervolgens opnieuw op de knop Configureren en klik ten slotte op de knop Genereren .

Selecteer BUILD_SHARED_LIBS

Na generatie zou CMake er zo uit moeten zien

Laatste CMake

Open nu Finder en ga naar / usr , maak een lokale mapnaam aan als deze er nog niet is. Open de lokale map en maak twee mappen include en lib als deze er nog niet is.

Open nu de GLFW-map en ga naar Build (waar CMake de bestanden had gebouwd). Open het bestand GLFW.xcodeproj in Xcode.

Xcode-projectbestand

Selecteer installeren> Mijn Mac en klik vervolgens op uitvoeren (knop Afspelen in de vorm).

GLFW installeren

Het is nu met succes geïnstalleerd (negeer de waarschuwingen).

Om er zeker van te zijn dat Open Finder en de map goto / usr / local / lib en drie GLFW-bibliotheekbestanden daar al aanwezig zijn (zo niet, open dan de map Build in de GLFW-map en ga naar src / Debug kopieer alle bestanden naar / usr / local / lib )

GLFW Lib-bestanden

Open Finder en ga naar / usr / local / include en er zal al een GLFW-map aanwezig zijn met twee header-bestanden erin met de naam glfw3.h en glfw3native.h

GLFW-koptekstbestanden

2. Installeer GLEW

GLEW is een platformonafhankelijke bibliotheek die helpt bij het opvragen en laden van OpenGL-extensies. Het biedt runtime-mechanismen om te bepalen welke OpenGL-extensies worden ondersteund op het doelplatform. Het is alleen voor moderne OpenGL (OpenGL versie 3.2 en hoger waarvoor functies moeten worden bepaald tijdens runtime). Download eerst de bestanden van glew.sourceforge.net om te installeren

GLEW-webpagina

Pak de GLFW-map uit en de inhoud ziet er zo uit.

GLEW Map Inhoud

Open nu Terminal, navigeer naar GLEW-map en typ de volgende opdrachten

make
sudo make install 
make clean
 

Nu is GLEW met succes geïnstalleerd. Om er zeker van te zijn dat het geïnstalleerd is, Open Finder, ga naar / usr / local / include en er zal al een GL-map aanwezig zijn met drie header-bestanden erin met de naam glew.h , glxew.h en wglew.h

GLEW-koptekstbestanden

Open Finder en ga naar / usr / local / lib en GLEW bibliotheekbestanden zullen daar al aanwezig zijn

GLEW-bibliotheekbestanden

3. Test en voer uit

Nu hebben we met succes GLFW en GLEW geïnstalleerd. Het is tijd om te coderen. Open Xcode en maak een nieuw Xcode-project. Selecteer Command Line Tool en ga vervolgens verder en selecteer C ++ als taal.

Xcode-project

Xcode maakt een nieuw opdrachtregelproject aan.

Klik op de projectnaam en schakel op het tabblad Build-instellingen van Basic naar All , onder Search Paths , voeg / usr / local / include toe in Header Search Paths en voeg / usr / local / lib toe in Library Search Paths

Zoekpaden

Klik op de projectnaam en onder het tabblad Build Phases en onder Link With Binary Libraries voeg OpenGL.framework toe en voeg ook recent aangemaakte GLFW- en GLEW- bibliotheken toe van / usr / local / lib

Link binaries

Nu zijn we klaar om te coderen in Modern Open GL 4.1 op macOS met behulp van C ++ en Xcode. De volgende code maakt een OpenGL-venster met behulp van GLFW met lege schermuitvoer.

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

Leeg OpenGL-venster