在没有GLUT的情况下初始化OpenGL
我能找到的每个介绍和示例似乎都使用GLUT或其他框架来“初始化”OpenGL。有没有一种方法可以用GL和GLU中可用的东西初始化OpenGL?如果不是,那么GLUT做什么没有它是不可能的?您正在做的是用OpenGL上下文初始化窗口。这需要对操作系统进行一些调用。仅用gl.h和glu.h初始化OpenGL是不可能的。(或者,等等)这是否以一种独立于平台的方式为您工作。您也可以使用本机调用进行初始化。您可以获取并查看您所关心的任何平台的初始化代码。下面是一个基本的、很好的介绍,介绍如何在不使用GLUT的情况下初始化OpenGL(假设为windows):在没有GLUT的情况下初始化OpenGL,opengl,glut,Opengl,Glut,我能找到的每个介绍和示例似乎都使用GLUT或其他框架来“初始化”OpenGL。有没有一种方法可以用GL和GLU中可用的东西初始化OpenGL?如果不是,那么GLUT做什么没有它是不可能的?您正在做的是用OpenGL上下文初始化窗口。这需要对操作系统进行一些调用。仅用gl.h和glu.h初始化OpenGL是不可能的。(或者,等等)这是否以一种独立于平台的方式为您工作。您也可以使用本机调用进行初始化。您可以获取并查看您所关心的任何平台的初始化代码。下面是一个基本的、很好的介绍,介绍如何在不使用GLU
正如Luke所说,如果你不想使用GLUT,你需要关于你正在开发的操作系统的具体信息。使用GLUT将使您的代码更易于移植。GL是一个API,GLU是GL之上的一个实用程序库。它完全独立于操作系统 OpenGL初始化和扩展获取是依赖于平台的操作。因此,仅使用OpenGL是无能为力的 GLUT的速度不够快,库的性能也非常差,它唯一能做的就是初始化opengl上下文,并提供一些原始的鼠标/键盘输入模块来让您继续工作
Win32还提供了初始化opengl上下文的工具。对于linux,您可以查看GLX。另外,如果您想要一种独立于系统的方式来实现它,那么您可以查看SDL。对于不同的编程语言,可能有一些实用程序为您提供独立于平台的桌面API。如luke所述,创建和绑定上下文的代码特定于每个窗口平台 以下是一些在特定平台上初始化OpenGL的函数: Windows(提供教程)
- wglCreateContext(hDC)
- :aglCreateContext
- :创建(或子类化)NSOpenGLView。他们创建自己的上下文,您可以阅读他们的方法文档来找到如何使其成为当前的
- :CGLCreateContext
- :glXCreateContext
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;
}
和Debian 8,带有:
Failed to get GLXFBConfig
我们可以随时打开GLX的源代码,看看它如何实现每个GLT功能,但低于GLX的级别可能是核心
EGL
看起来像是Khronos标准化的GLX替代品,目前最常用于OpenGL ES
包含使用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'
但是ubuntu14.04在mesa-utils-extra
包中有es2gear
,所以一定有办法
另请参见:谢谢,这些都很有用。现在我意识到,我的问题是特定于代码的Windows端,而不仅仅是OpenGL(即,试图让OpenGL在-GDI+之上或沿着-GDI+工作)。您不需要将NSOpenGLView子类化,而是将NSView子类化,并使用NSOpenGLContext和NSPixelFormat以获得更大的灵活性(并且您仅将NSOpenGLView用于非常简单的事情)。此外,请注意,Carbon几乎是一条死胡同(不支持64位),CGL无法创建窗口,因此对于OSX,将NSGL用于Cocoa窗口、菜单等,将CGL用于全屏应用程序。苹果的链接现在已断开。如果我能找到新的URL,我会建议编辑。Windows链接也断开。这只是Windows。是的,但它仍然很有指导意义。:-)谢谢“强调“易于理解”-但我无法阅读代码中的注释:(没有人提到?这是一个Khronos标准,用于操作系统和OpenGL等API之间的互操作,旨在统一这些东西。不过,IDK现在支持的范围有多广。这个示例确实使用了glut?@Ivanzinho,我得到了
无效的MIT-MAGIC-COOKIE-1密钥无法在Ubuntu 20.04上打开X显示。恐怕我不知道这是如何工作的。)我已经足够调试了,如果你发现了,请告诉我!@Yunnosch我很抱歉,我没有正确阅读,我认为是深夜。你是对的,我指定的问题已经记录在这里了。对不起。
/work/git/mesa-demos/src/egl/opengl/demo1.c:26: undefined reference to `eglGetScreensMESA'