Question

chaque introduction et l'échantillon que je peux trouver semble utiliser GLUT ou un autre cadre pour OpenGL « initialiser ». Est-il un moyen d'initialisation OpenGL avec juste ce qui est disponible dans GL et GLU? Sinon, qu'est-ce GLUT fait qui est impossible sans elle?

Était-ce utile?

La solution

Luc a noté, le code de créer et de lier le contexte est spécifique à chaque plate-forme de fenêtrage.

Voici quelques fonctions pour vous aider à démarrer en termes d'initialisation OpenGL sur des plates-formes spécifiques:

Windows (ce tutoriel est )

  • wglCreateContext (hDC)

Mac OS X - OS X a essentiellement trois options: carbone, le cacao et la couche de base sous-jacente graphique

Linux

Autres conseils

Qu'est-ce que vous faites est l'initialisation d'une fenêtre avec un contexte OpenGL. Cela nécessite des appels au système d'exploitation. Il est impossible d'initialiser OpenGL avec juste gl.h et glu.h. GLUT (ou SDL , SMFL , etc.) fait que travailler pour vous dans une belle plate-forme de manière indépendante. Vous pouvez faire l'initialisation des appels natifs ainsi.

Vous pouvez saisir le code source GLUT et voir le code d'initialisation pour quelque la plate-forme qui vous concerne.

exemple GLX runnable minimum

Adapté de .

traite également avec des entrées du clavier.

Compiler avec:

gcc glx.c -lGLU -lGL -lX11

Testé dans Ubuntu 14.04.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#define GL_GLEXT_PROTOTYPES
#define GLX_GLXEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glx.h>

struct MyWin {
    Display  *display;
    Window win;
    int displayed;
    int width;
    int height;
};

const int WIN_XPOS = 256;
const int WIN_YPOS = 64;
const int WIN_XRES = 320;
const int WIN_YRES = 320;
const int NUM_SAMPLES = 4;

struct MyWin Win;

double elapsedMsec(const struct timeval *start, const struct timeval *stop) {
    return ((stop->tv_sec  - start->tv_sec ) * 1000.0 +
            (stop->tv_usec - start->tv_usec) / 1000.0);
}

void displayCB() {
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
    glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);
    glVertex3f( 0.0f, 1.0f, 0.0f);
    glVertex3f(-1.0f, -1.0f, 0.0f);
    glVertex3f( 1.0f, -1.0f, 0.0f);
    glEnd();
    glFlush();
    glXSwapBuffers(Win.display, Win.win);
}

void keyboardCB(KeySym sym, unsigned char key, int x, int y,
        int *setting_change) {
    switch (tolower(key)) {
        case 27:
            exit(EXIT_SUCCESS);
            break;
        case 'k':
            printf("You hit the 'k' key\n");
            break;
        case 0:
            switch (sym) {
                case XK_Left  :
                    printf("You hit the Left Arrow key\n");
                    break;
                case XK_Right :
                    printf("You hit the Right Arrow key\n");
                    break;
            }
            break;
    }
}

void reshapeCB(int width, int height) {
    Win.width = width;
    Win.height = height;
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
    glMatrixMode(GL_MODELVIEW);
}

/* Try to find a framebuffer config that matches
 * the specified pixel requirements.
 */
GLXFBConfig chooseFBConfig(Display *display, int screen) {
    static const int Visual_attribs[] = {
        GLX_X_RENDERABLE  , True,
        GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
        GLX_RENDER_TYPE   , GLX_RGBA_BIT,
        GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
        GLX_RED_SIZE      , 8,
        GLX_GREEN_SIZE    , 8,
        GLX_BLUE_SIZE     , 8,
        GLX_ALPHA_SIZE    , 8,
        GLX_DEPTH_SIZE    , 24,
        GLX_STENCIL_SIZE  , 8,
        GLX_DOUBLEBUFFER  , True,
        GLX_SAMPLE_BUFFERS, 1,
        GLX_SAMPLES       , 4,
        None
    };
    int attribs [ 100 ] ;
    memcpy(attribs, Visual_attribs, sizeof(Visual_attribs));
    GLXFBConfig ret = 0;
    int fbcount;
    GLXFBConfig *fbc = glXChooseFBConfig(display, screen, attribs, &fbcount);
    if (fbc) {
        if (fbcount >= 1)
            ret = fbc[0];
        XFree(fbc);
    }
    return ret;
}

GLXContext createContext(Display *display, int screen,
        GLXFBConfig fbconfig, XVisualInfo *visinfo, Window window) {
#define GLX_CONTEXT_MAJOR_VERSION_ARB       0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB       0x2092
    typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*,
            GLXFBConfig, GLXContext, int, const int*);
    /* Verify GL driver supports glXCreateContextAttribsARB() */
    /*   Create an old-style GLX context first, to get the correct function ptr. */
    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
    GLXContext ctx_old = glXCreateContext(display, visinfo, 0, True);
    if (!ctx_old) {
        printf("Could not even allocate an old-style GL context!\n");
        exit(EXIT_FAILURE);
    }
    glXMakeCurrent (display, window, ctx_old) ;
    /* Verify that GLX implementation supports the new context create call */
    if (strstr(glXQueryExtensionsString(display, screen),
                "GLX_ARB_create_context") != 0)
        glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
            glXGetProcAddress((const GLubyte *) "glXCreateContextAttribsARB");
    if (!glXCreateContextAttribsARB) {
        printf("Can't create new-style GL context\n");
        exit(EXIT_FAILURE);
    }
    /* Got the pointer.  Nuke old context. */
    glXMakeCurrent(display, None, 0);
    glXDestroyContext(display, ctx_old);

    /* Try to allocate a GL 4.2 COMPATIBILITY context */
    static int Context_attribs[] = {
        GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
        GLX_CONTEXT_MINOR_VERSION_ARB, 2,
        GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
        /*GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, */
        /*GLX_CONTEXT_FLAGS_ARB       , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, */
        /*GLX_CONTEXT_FLAGS_ARB       , GLX_CONTEXT_DEBUG_BIT_ARB, */
        None
    };
    GLXContext context = glXCreateContextAttribsARB(display, fbconfig, 0,
            True, Context_attribs);
    /* Forcably wait on any resulting X errors */
    XSync(display, False);
    if (!context) {
        printf("Failed to allocate a GL 4.2 context\n");
        exit(EXIT_FAILURE);
    }
    printf("Created GL 4.2 context\n");
    return context;
}

void createWindow() {
    /* Init X and GLX */
    Win.displayed = 0;
    Display *display = Win.display = XOpenDisplay(":0.0");
    if (!display)
        printf("Cannot open X display\n");
    int    screen   = DefaultScreen(display);
    Window root_win = RootWindow(display, screen);
    if (!glXQueryExtension(display, 0, 0))
        printf("X Server doesn't support GLX extension\n");
    /* Pick an FBconfig and visual */
    GLXFBConfig fbconfig = chooseFBConfig(display, screen);
    if (!fbconfig) {
        printf("Failed to get GLXFBConfig\n");
        exit(EXIT_FAILURE);
    }
    XVisualInfo *visinfo = glXGetVisualFromFBConfig(display, fbconfig);
    if (!visinfo) {
        printf("Failed to get XVisualInfo\n");
        exit(EXIT_FAILURE);
    }
    printf("X Visual ID = 0x%.2x\n", (int)visinfo->visualid);
    /* Create the X window */
    XSetWindowAttributes winAttr ;
    winAttr.event_mask = StructureNotifyMask | KeyPressMask ;
    winAttr.background_pixmap = None ;
    winAttr.background_pixel  = 0    ;
    winAttr.border_pixel      = 0    ;
    winAttr.colormap = XCreateColormap(display, root_win,
            visinfo->visual, AllocNone);
    unsigned int mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
    Window win = Win.win = XCreateWindow (display, root_win,
            WIN_XPOS, WIN_YPOS,
            WIN_XRES, WIN_YRES, 0,
            visinfo->depth, InputOutput,
            visinfo->visual, mask, &winAttr) ;
    XStoreName(Win.display, win, "My GLX Window");
    /* Create an OpenGL context and attach it to our X window */
    GLXContext context = createContext(display, screen, fbconfig, visinfo, win);
    if (! glXMakeCurrent(display, win, context))
        printf("glXMakeCurrent failed.\n");
    if (! glXIsDirect (display, glXGetCurrentContext()))
        printf("Indirect GLX rendering context obtained\n");
    /* Display the window */
    XMapWindow(display, win);
    if (! glXMakeCurrent(display, win, context))
        printf("glXMakeCurrent failed.\n");
    printf("Window Size    = %d x %d\n", WIN_XRES, WIN_YRES);
    printf("Window Samples = %d\n", NUM_SAMPLES);
}

void processXEvents(Atom wm_protocols, Atom wm_delete_window) {
    int setting_change = 0;
    while (XEventsQueued(Win.display, QueuedAfterFlush)) {
        XEvent event;
        XNextEvent(Win.display, &event);
        if(event.xany.window != Win.win)
            continue;
        switch (event.type) {
            case MapNotify:
                {
                    Win.displayed = 1;
                    break;
                }
            case ConfigureNotify:
                {
                    XConfigureEvent cevent = event.xconfigure;
                    reshapeCB(cevent.width, cevent.height);
                    break;
                }
            case KeyPress:
                {
                    char chr;
                    KeySym symbol;
                    XComposeStatus status;
                    XLookupString(&event.xkey, &chr, 1, &symbol, &status);
                    keyboardCB(symbol, chr, event.xkey.x, event.xkey.y,
                            &setting_change);
                    break;
                }
            case ClientMessage:
                {
                    if (event.xclient.message_type == wm_protocols &&
                            (Atom)event.xclient.data.l[0] == wm_delete_window) {
                        exit(EXIT_SUCCESS);
                    }
                    break;
                }
        }
    }
}

void mainLoop() {
    /* Register to receive window close events (the "X" window manager button) */
    Atom wm_protocols     = XInternAtom(Win.display, "WM_PROTOCOLS"    , False);
    Atom wm_delete_window = XInternAtom(Win.display, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(Win.display, Win.win, &wm_delete_window, True);

    while (1) {
        /* Redraw window (after it's mapped) */
        if (Win.displayed)
            displayCB();

        /* Update frame rate */
        struct timeval last_xcheck = {0, 0};
        struct timeval now;
        gettimeofday(&now, 0);

        /* Check X events every 1/10 second */
        if (elapsedMsec(&last_xcheck, &now) > 100) {
            processXEvents(wm_protocols, wm_delete_window);
            last_xcheck = now;
        }
    }
}

int main(int argc, char *argv[]) {
    Win.width = WIN_XRES;
    Win.height = WIN_YRES;
    createWindow();

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);

    printf("Valid keys: Left, Right, k, ESC\n");
    printf("Press ESC to quit\n");
    mainLoop();
    return EXIT_SUCCESS;
}

On peut toujours ouvrir la source de Freeglut pour voir comment il met en œuvre chaque fonction GLUT, mais aller plus bas que GLX est hardcore probable.

EGL

On dirait une alternative standardisée Khronos à GLX, actuellement le plus souvent utilisé avec OpenGL ES.

https://cgit.freedesktop.org/mesa/demos/tree / src / EGL contient des exemples en utilisant la mise en œuvre de Mesa, mais je n'ai pas encore réussi à les faire fonctionner:

git checkout mesa-demos-8.1.0
./autogen.sh
./configure
make

échoue avec:

/work/git/mesa-demos/src/egl/opengl/demo1.c:26: undefined reference to `eglGetScreensMESA'

Mais Ubuntu 14.04 a es2gears dans le paquet mesa-utils-extra, il doit y avoir un moyen.

Voir aussi: Qu'est-ce EGL et comment puis-je utiliser il

GL est une API, et GLU est une bibliothèque d'utilitaires au-dessus de GL. Il est système complètement indépendant d'exploitation.

initialisation OpenGL et extraction d'extension sont des opérations qui dépendent de la plate-forme. Par conséquent, vous pouvez faire rien avec OpenGL seul.

GLUT est rapide insuffisante et d'une bibliothèque terriblement pauvres, et environ seulement il est qu'il initialise le contexte opengl et fournit des modules d'entrée souris primitive / clavier pour vous obtenir en cours.

Win32 fournit des outils pour initialiser le contexte opengl ainsi. Pour Linux, vous pouvez vérifier GLX. En outre, si vous voulez un système de manière indépendante de le faire, vous pouvez consulter SDL. Pour différents langages de programmation il peut y avoir des services publics qui vous fournissent une plate-forme API de bureau indépendant.

Vous pouvez consulter la source de Galaxy Forces V2, http://www.galaxy-forces.com/

Il implémente des classes pour OpenGL sans utiliser GLUT ou d'autres bibliothèques sous Windows, Mac et Linux. En utilisant le code de la plate-forme native, tout domaine public.

Voici une introduction de base et bon à la façon dont vous initialisez OpenGL (en supposant Windows) sans utiliser GLUT:

Init OpenGL sans GLUT

Comme Luc dit, si vous ne voulez pas utiliser GLUT, vous avez besoin d'informations spécifiques sur le système d'exploitation que vous développez sur. L'utilisation GLUT rendra votre code plus facile au port.

GLUT est pour l'outil généralement idéal pour l'apprentissage d'une OpenGL sans les détails de choses fenêtrage. vous pouvez apprendre OpenGL facilement sans détails inutiles. Non il n'y a pas de fonctions pour la création d'une fenêtre et la gestion de la fenêtre OpenGL. Il est possible, mais vous devez utiliser les fonctions fournies par le système d'exploitation que vous utilisez. Par exemple, Windows ou Linux qui est un vrai cauchemar pour les débutants en particulier Windows si vous êtes nouveau à OpenGL GLUT est alors le chemin à parcourir.

Le code de base pour

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top