cada introducción y muestra que puedo encontrar parece utilizar GLUT o algún otro marco para "inicializar" OpenGL. ¿Hay alguna manera de inicializar OpenGL con solo lo que está disponible en GL y GLU? Si no, ¿qué está haciendo GLUT que no es posible sin eso?Inicializando OpenGL sin GLUT
Respuesta
Como señaló Luke, el código para crear y vincular el contexto es específico para cada plataforma de ventanas.
Estas son algunas de las funciones para ayudarle a empezar en términos de inicializar OpenGL en plataformas específicas:
de Windows (un tutorial es here)
- wglCreateContext (hDC)
Mac OS X - OS X tiene esencialmente tres opciones: Carbono, Cacao y la Capa Gráfica Core subyacente
- The entire guide for Mac OS X OpenGL development
- Carbon: aglCreateContext
- Cocoa: Crear (o subclase) un NSOpenGLView. Crean su propio contexto, y puede leer la documentación de su método para encontrar cómo actualizarlo.
- CoreGraphicsLayer: CGLCreateContext
Linux
- glx: glXCreateContext
Gracias, estos son útiles. Ahora me doy cuenta de que mi problema es específico de Windows lado del código en lugar de solo OpenGL (es decir, tratando de que OpenGL funcione en la parte superior o al lado de? GDI +). –
No subclasifica NSOpenGLView, subclase NSView y usa NSOpenGLContext y NSPixelFormat para obtener más flexibilidad (y usted solo use un NSOpenGLView para cosas muy simples). – mk12
Además, tenga en cuenta que Carbon es prácticamente un callejón sin salida (sin soporte de 64 bits) y CGL no puede crear una ventana, por lo que para OS X use NSGL para ventanas Cocoa, menús, etc. y CGL para aplicaciones de pantalla completa. – mk12
Lo que está haciendo es inicializar una ventana con un contexto OpenGL. Esto requiere algunas llamadas al sistema operativo. No es posible inicializar OpenGL con solo gl.h y glu.h. GLUT (o SDL, SMFL, etc.) funciona para usted de una manera agradable plataforma independiente. Puede hacer la inicialización con llamadas nativas también.
Puede tomar el GLUT source code y ver el código de inicio para cualquier plataforma que le preocupe.
Aquí hay una introducción básica y buena a la forma de inicializar OpenGL (suponiendo ventanas) sin usar GLUT:
Como dijo Lucas, si no quieres usar GLUT, necesita información específica acerca de la sistema operativo en el que está desarrollando Usar GLUT hará que su código sea más fácil de portar.
Esta muestra utiliza glut? –
GL es una API, y GLU es una biblioteca de utilidades en la parte superior de GL. Es completamente independiente del sistema operativo.
La inicialización de OpenGL y la recuperación de extensión son operaciones dependientes de la plataforma. Por lo tanto, no puede hacer nada con OpenGL solo.
GLUT es una biblioteca insuficiente y terriblemente pobre, y lo único que hace es inicializar el contexto opengl y proporciona algunos módulos primitivos de entrada de mouse/teclado para que pueda continuar.
Win32 proporciona herramientas para inicializar el contexto OpenGL también. Para Linux, puedes ver GLX. Además, si desea una forma de hacerlo independiente del sistema, puede ver SDL. Para diferentes lenguajes de programación, puede haber utilidades que le proporcionen una API de escritorio independiente de la plataforma.
Es posible que echa un vistazo a la fuente del Galaxy Fuerzas V2, http://www.galaxy-forces.com/
Implementa clases para OpenGL sin usando GLUT u otras bibliotecas en Windows, Mac, y Linux. Usando el código de la plataforma nativa, todo el dominio público.
GLX mínimo ejemplo runnable
Adaptado de here.
También se trata de entradas de teclado.
compilar con:
gcc glx.c -lGLU -lGL -lX11
Probado en 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;
}
Uno siempre podría abrir la fuente de FreeGlut para ver cómo se implementa cada función exceso, pero yendo nivel más bajo que GLX es probable hardcore.
EGL
Parece que una alternativa estandarizada Khronos a GLX, actualmente se utiliza con más frecuencia OpenGL ES.
https://cgit.freedesktop.org/mesa/demos/tree/src/egl contiene ejemplos que utilicen la implementación de Mesa, pero aún no han logrado que funcionen:
git checkout mesa-demos-8.1.0
./autogen.sh
./configure
make
error con:
/work/git/mesa-demos/src/egl/opengl/demo1.c:26: undefined reference to `eglGetScreensMESA'
Pero Ubuntu 14.04 tiene es2gears
en el paquete mesa-utils-extra
, entonces debe haber una manera.
Consulte también: What is EGL And How Can I Use It
- 1. ¿Aprendizaje de OpenGL sin GLUT?
- 2. texto simple en OpenGL (sin GLUT)
- 3. Centrar una ventana OpenGL con GLUT
- 4. ¿El cl-opengl glut está maduro?
- 5. OpenGL GLUT ventana muy lenta, ¿por qué?
- 6. SDL vs GLUT en opengl Programación 3D
- 7. OpenGL y GLUT en Eclipse en OS X
- 8. ¿Cómo usar GLUT/OpenGL para renderizar en un archivo?
- 9. Relleno de líneas de escaneo Algoritmo OpenGL/GLUT en C++
- 10. GLUT en OS X con OpenGL 3.2 Core Profile
- 11. Transformar proyecto C++ openGL existente de glut/freeglut a glfw
- 12. ¿Cómo dibujo texto con GLUT/OpenGL en C++?
- 13. Menús emergentes GLUT
- 14. ¿Está GLUT muerto?
- 15. GLUT Alternativas para Haskell?
- 16. diferencia entre SDL y GLUT
- 17. Inicializando NSMutableArray con y sin capacidad de
- 18. Uso de GLUT con Visual C++ Express Edition
- 19. OpenGL sin una tarjeta gráfica
- 20. OpenGL sin X.org en Linux
- 21. Usando OpenGL/GLUT ¿cómo puedo detectar si dos teclas se mantienen presionadas al mismo tiempo?
- 22. Lua - inicializando
- 23. Inicializando data.frames()
- 24. Inicializando NSDictionary
- 25. Inicializando matrices en C++
- 26. Usando la rueda de desplazamiento del mouse en GLUT
- 27. Inicializando una matriz KeyValuePair
- 28. Inicializando C# auto-propiedades
- 29. Inicializando Log4J con Spring?
- 30. El proyecto XCode no puede reconocer ciertos comandos GLUT
Nadie mencionó [EGL] (http://www.khronos.org/egl)? Es un estándar de Khronos para la interoperabilidad entre el sistema operativo y las API como OpenGL, con el objetivo de unificar tales cosas. IDK, sin embargo, qué tan amplio es admitido hoy. – Kos
que solo es de Windows. – rotoglup
Sí, pero sigue siendo instructivo. :-) ¡Gracias! –