2009-05-18 41 views
37

mỗi phần giới thiệu và mẫu mà tôi có thể tìm thấy có vẻ như sử dụng GLUT hoặc một số khung công tác khác để "khởi tạo" OpenGL. Có cách nào để khởi tạo OpenGL chỉ với những gì có sẵn trong GL và GLU? Nếu không, thì GLUT làm điều gì là không thể nếu không có nó?Khởi tạo OpenGL mà không cần GLUT

+1

Không ai đề cập [EGL] (http://www.khronos.org/egl)? Đó là một tiêu chuẩn Khronos cho interop giữa hệ điều hành và các API như OpenGL, nhằm hợp nhất những thứ như vậy. Tuy nhiên, IDK đã được hỗ trợ rộng đến mức nào. – Kos

+0

chỉ dành cho Windows. – rotoglup

+0

Yup, nhưng nó vẫn mang tính hướng dẫn. :-) Cảm ơn! –

Trả lời

33

Như lưu ý, mã để tạo và ràng buộc ngữ cảnh là cụ thể cho từng nền tảng cửa sổ.

Dưới đây là một số chức năng để giúp bạn bắt đầu về khởi tạo OpenGL trên nền tảng cụ thể:

Windows (một hướng dẫn là here)

  • wglCreateContext (HDC)

Mac OS X - OS X có ba lựa chọn cơ bản: Carbon, Ca cao và Lớp Đồ họa Lõi cơ bản

Linux

  • glx: glXCreateContext
+0

Cảm ơn, đây là những hữu ích. Bây giờ tôi nhận ra rằng vấn đề của tôi là cụ thể cho Windows bên cạnh mã thay vì chỉ OpenGL (tức là cố gắng để OpenGL hoạt động trên đầu trang - hoặc bên cạnh? - GDI +) –

+1

Bạn không phân lớp NSOpenGLView, bạn phân lớp NSView và sử dụng NSOpenGLContext và NSPixelFormat để linh hoạt hơn (và bạn chỉ sử dụng NSOpenGLView cho những thứ rất đơn giản). – mk12

+2

Ngoài ra, lưu ý rằng Carbon là một kết thúc chết (không hỗ trợ 64 bit) và CGL không thể tạo cửa sổ, vì vậy OS X sử dụng NSGL cho cửa sổ Cocoa, menu vv và CGL cho các ứng dụng toàn màn hình. – mk12

5

Việc bạn đang làm đang khởi chạy một cửa sổ có ngữ cảnh OpenGL. Điều này yêu cầu một số cuộc gọi đến hệ điều hành. Không thể khởi chạy OpenGL chỉ với gl.h và glu.h. GLUT (hoặc SDL, SMFL, v.v.) có hoạt động với bạn theo cách độc lập hay không. Bạn cũng có thể thực hiện khởi tạo với các cuộc gọi gốc.

2

Bạn có thể lấy GLUT source code và xem mã init cho bất kỳ nền tảng nào bạn quan tâm.

-2

Dưới đây là một giới thiệu cơ bản và tốt để làm thế nào bạn khởi tạo OpenGL (giả sử cửa sổ) mà không sử dụng GLUT:

Init OpenGL without GLUT

Như Luke nói rằng, nếu bạn không muốn sử dụng dư thừa, bạn cần thông tin cụ thể về hệ điều hành bạn đang phát triển. Sử dụng GLUT sẽ làm cho mã của bạn dễ dàng hơn để chuyển.

+1

Mẫu này sử dụng glut? –

-1

GL là một API và GLU là một thư viện tiện ích trên đầu trang của GL. Nó hoàn toàn độc lập với hệ điều hành.

Khởi tạo OpenGL và tìm nạp tiện ích mở rộng là các hoạt động phụ thuộc nền tảng. Do đó bạn không thể làm gì với OpenGL một mình.

GLUT không đủ nhanh và thư viện cực kỳ kém, và chỉ có nó mới khởi tạo ngữ cảnh opengl và cung cấp một số mô-đun đầu vào chuột/bàn phím nguyên thủy để giúp bạn tiếp tục.

Win32 cũng cung cấp các công cụ để khởi chạy ngữ cảnh opengl. Đối với Linux bạn có thể kiểm tra GLX. Ngoài ra, nếu bạn muốn một cách độc lập hệ thống để làm điều đó, sau đó bạn có thể kiểm tra SDL. Đối với các ngôn ngữ lập trình khác nhau, có thể có các tiện ích cung cấp cho bạn một API nền tảng độc lập cho máy tính để bàn.

-1

Bạn có thể kiểm tra nguồn gốc của Galaxy Lực lượng V2, http://www.galaxy-forces.com/

Nó thực hiện các lớp học cho OpenGL không sử dụng GLUT hoặc các thư viện khác trên Windows, Mac, và Linux. Sử dụng mã nền tảng gốc, tất cả miền công cộng.

2

GLX tối thiểu dụ Runnable

Phỏng theo here.

Cũng đề cập đến đầu vào bàn phím.

Compile với:

gcc glx.c -lGLU -lGL -lX11 

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

Một luôn có thể mở ra nguồn gốc của FreeGlut để xem nó như thế nào thực hiện mỗi chức năng dư thừa, nhưng sẽ thấp hơn so với mức GLX có khả năng hardcore.

EGL

Trông giống như một Khronos thay thế tiêu chuẩn để GLX, hiện thường được sử dụng với OpenGL ES.

https://cgit.freedesktop.org/mesa/demos/tree/src/egl chứa các ví dụ sử dụng thực hiện Mesa, nhưng tôi vẫn chưa được quản lý để làm cho họ làm việc:

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

Không với:

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

Nhưng Ubuntu 14.04 có es2gears trong gói mesa-utils-extra, vì vậy phải có một cách.

Xem thêm: What is EGL And How Can I Use It

Các vấn đề liên quan