2009-05-18 3 views
37

Каждое введение и образец, который я могу найти, по-видимому, используют GLUT или некоторые другие рамки для «инициализации» OpenGL. Есть ли способ инициализировать OpenGL только тем, что доступно в GL и GLU? Если нет, то что же делает GLUT без него?Инициализация OpenGL без GLUT

+1

Никто не упоминается [EGL] (http://www.khronos.org/egl)? Это стандарт Khronos для взаимодействия между операционной системой и API-интерфейсами, такими как OpenGL, целью которых является объединение таких вещей. Тем не менее, IDK широко распространена сегодня. – Kos

+0

, который является только Windows. – rotoglup

+0

Yup, но это по-прежнему поучительно. :-) Благодаря! –

ответ

33

Как отметил Люк, код для создания и привязки контекста специфичен для каждой оконной платформы.

Вот некоторые функции, чтобы вы начали с точки зрения инициализация OpenGL на определенных платформах:

для Windows (учебник является here)

  • wglCreateContext (HDC)

Mac OS X - OS X имеет по существу три варианта: углерод, какао и базовый графический слой Core

  • The entire guide for Mac OS X OpenGL development
  • Carbon: aglCreateContext
  • Cocoa: Создать (или подкласс) в NSOpenGLView. Они создают свой собственный контекст, и вы можете прочитать их документацию по методу, чтобы узнать, как сделать его актуальным.
  • CoreGraphicsLayer: CGLCreateContext

Linux

  • glx: glXCreateContext
+0

Спасибо, это полезно. Теперь я понимаю, что моя проблема специфична для Windows стороне кода, а не просто OpenGL (т. е. пытаться заставить OpenGL работать сверху или сбоку?) GDI +). – 2009-05-18 20:28:13

+1

Вы не подклассифицируете NSOpenGLView, вы подклассифицируете NSView и используете NSOpenGLContext и NSPixelFormat для большей гибкости (и вы используйте только NSOpenGLView для очень простых вещей). – mk12

+2

Также обратите внимание, что Carbon почти тупик (без поддержки 64 бит), и CGL не может создать окно, поэтому для OS X используйте NSGL для окон Cocoa, меню и т. Д. И CGL для полноэкранных приложений. – mk12

5

Что вы делаете, это инициализация окна контекстом OpenGL. Это требует некоторых вызовов операционной системы. Невозможно инициализировать OpenGL только с помощью gl.h и glu.h. GLUT (или SDL, SMFL и т. Д.), Это работает для вас в приятной независимой платформе. Вы также можете выполнить инициализацию с помощью собственных вызовов.

2

Вы можете захватить GLUT source code и посмотреть код инициализации для любой платформы, о которой вы говорите.

-2

Вот основной и хорошее введение как инициализировать OpenGL (предполагая, окна) без использования GLUT:

Init OpenGL without GLUT

Как сказал Люк, если вы не хотите использовать GLUT, вам конкретную информацию о которую вы разрабатываете. Использование GLUT упростит перенос кода.

+1

Этот пример использует глют? –

-1

GL - это API, а GLU - это утилитная библиотека поверх GL. Он полностью независим от операционной системы.

Инициализация и расширение OpenGL - это операции, зависящие от платформы. Поэтому вы можете ничего не делать с OpenGL.

GLUT - это быстрая и ужасно белая библиотека, и только в том, что она инициализирует контекст opengl и предоставляет некоторые примитивные модули ввода/ввода для клавиатуры, чтобы вы продолжали работать.

Win32 предоставляет инструменты для инициализации контекста opengl. Для Linux вы можете проверить GLX. Кроме того, если вы хотите независимый от системы способ сделать это, вы можете проверить SDL. Для разных языков программирования могут быть утилиты, которые предоставляют вам независимый от платформы настольный API.

-1

Вы можете проверить источник Galaxy сил V2, http://www.galaxy-forces.com/

Он реализует классы для OpenGL без используя GLUT или другие библиотеки в Windows, Mac, и Linux. Используя собственный код платформы, все общедоступные.

2

GLX минимально работоспособного пример

адаптирован из here.

Также касается ввода с клавиатуры.

Compile с:

gcc glx.c -lGLU -lGL -lX11 

Испытано в 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; 
} 

всегда можно было открыть источник FreeGlut, чтобы увидеть, как он реализует каждую функцию GLUT, но происходит более низкий уровень, чем GLX, вероятно, хардкор.

EGL

Похоже Khronos стандартизированной альтернативы GLX, в настоящее время наиболее часто используется с OpenGL ES.

https://cgit.freedesktop.org/mesa/demos/tree/src/egl содержит примеры использования реализации Mesa, но я до сих пор не удалось сделать их работу:

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

терпит неудачу с:

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

Но Ubuntu 14.04 имеет es2gears в mesa-utils-extra пакете, поэтому должен быть способ.

Смотрите также: What is EGL And How Can I Use It