在没有GLUT的情况下初始化OpenGL

问题描述 投票:39回答:8

我能找到的每个介绍和样本似乎都使用GLUT或其他一些框架来“初始化”OpenGL。有没有办法用GL和GLU中的可用内容初始化OpenGL?如果没有,那么没有它,GLUT做什么是不可能的?

opengl glut
8个回答
34
投票

正如卢克所指出的,创建和绑定上下文的代码是特定于每个窗口平台的。

以下是一些函数,可帮助您开始在特定平台上初始化OpenGL:

Windows(教程是here

  • wglCreateContext(HDC)

Mac OS X - OS X基本上有三个选项:Carbon,Cocoa和底层的Core Graphics Layer

Linux的


5
投票

你正在做的是用OpenGL上下文初始化一个窗口。这需要对操作系统进行一些调用。只用gl.h和glu.h初始化OpenGL是不可能的。 glx(或GLUTSDL等)以独立于平台的方式为您工作。您也可以使用本机调用进行初始化。


2
投票

您可以抓住SMFL并查看您所关注的任何平台的init代码。


2
投票

GLUT source code最小的可运行的例子

改编自GLX

还处理键盘输入。

编译:

here

在Ubuntu 14.04中测试过。

gcc glx.c -lGLU -lGL -lX11

人们可以随时打开#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; } 的来源,看看它如何实现每个过剩功能,但是比GLX更低的水平可能是硬核。

EGL

看起来像是GLX的Khronos标准化替代品,目前最常用于OpenGL ES。

FreeGlut包含使用Mesa实现的示例,但我还没有设法让它们工作:

https://cgit.freedesktop.org/mesa/demos/tree/src/egl

失败:

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

但是Ubuntu 14.04在/work/git/mesa-demos/src/egl/opengl/demo1.c:26: undefined reference to `eglGetScreensMESA' 包中有es2gears,所以必须有办法。

另见:mesa-utils-extra


-1
投票

GL是一个API,GLU是GL之上的实用程序库。它完全独立于操作系统。

OpenGL初始化和扩展提取是与平台相关的操作。因此,您无法单独使用OpenGL。

GLUT是一个快速不足且非常糟糕的库,只有它的作用是它初始化opengl上下文并提供一些原始的鼠标/键盘输入模块来让你继续。

Win32还提供了初始化opengl上下文的工具。对于linux,您可以查看GLX。此外,如果您想要一种独立于系统的方式,那么您可以查看SDL。对于不同的编程语言,可能有一些实用程序可为您提供独立于平台的桌面API。


-1
投票

你可以看一下Galaxy Forces V2,What is EGL And How Can I Use It的来源

它在Windows,Mac和Linux上不使用GLUT或其他库来实现OpenGL的类。使用本机平台代码,所有公共域。


-2
投票

这里是一个基本的,很好的介绍如何初始化OpenGL(假设Windows)而不使用GLUT:

http://www.galaxy-forces.com/

正如Luke所说,如果你不想使用GLUT,你需要有关你正在开发的操作系统的具体信息。使用GLUT将使您的代码更容易移植。


-2
投票

GLUT通常是学习OpenGL的好工具,没有窗口化的细节。您可以轻松学习OpenGL而无需不必要的细节。没有任何用于在OpenGL中创建窗口和管理窗口的功能。这是可能的,但您必须使用您使用的操作系统提供的功能。例如Windows或Linux对初学者来说是一个真正的噩梦,尤其是Windows,如果你不熟悉OpenGL,那么GLUT就是最佳选择。

基本代码

© www.soinside.com 2019 - 2024. All rights reserved.