hi folks,
<some> time ago i posted a topic concerning VBOs in linux, because i couldn’t get them running. i did
not get a helping answer, so i dropped the topic and used display lists/vertex arrays as before.
now, i’ve finally found out what the problem was: when creating the GL context, it has to look like this:
Display *dpy;
XVisualInfo *vi;
…
glXCreateContext(dpy, vi, NULL, GL_TRUE);
the last parameter has to be GL_TRUE, otherwise it doesn’t work. according to the manual page, this parameter
“Specifies whether rendering is to be done with a direct connection to the graphics system if possible (True) or through the X server (False).”
small change, big effect…so- to whom it concerns, here’s a small snippet which uses VBOs. take it compile it, have fun, it’s free.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glext.h>
#include<GL/glu.h>
Display *dpy = XOpenDisplay(NULL);
Window root = DefaultRootWindow(dpy), win;
int att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, true, None };
XVisualInfo *vi = glXChooseVisual(dpy, 0, att);
Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
GLXContext glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
XWindowAttributes gwa;
#define GL_ARRAY_BUFFER_ARB 0x8892
#define GL_STATIC_DRAW_ARB 0x88E4
unsigned int VBOid[2] = { 0, 0 };
typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum, GLuint);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei, const GLuint *);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei, GLuint *);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum, int, const GLvoid *, GLenum);
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
//////////////////////////////////////////////////////////////////////////////////////////
// EXPOSE FUNC //
//////////////////////////////////////////////////////////////////////////////////////////
void ExposeFunc() {
XGetWindowAttributes(dpy, win, &gwa); // ADJUST VIEWPORT
glViewport(0, 0, gwa.width, gwa.height); // TO WINDOW SIZE
glClearColor(0.0, 0.0, 0.2, 1.0); // SET CLEAR COLOR
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // CLEAR BUFFERS
glMatrixMode(GL_PROJECTION); //
glLoadIdentity(); // ORTHOGONAL PROJECTION
glOrtho(-2., 2., -2., 2., 1., 100.); //
glMatrixMode(GL_MODELVIEW); //
glLoadIdentity(); // VIEW DIRECTION : -Z
gluLookAt(0., 0., 50., 0., 0., 0., 0., 1., 0.); //
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOid[0] ); // BIND VERTEX BUFFER
glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL ); // SETUP VERTEX POINTER
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOid[1] ); // BIND COLOR BUFFER
glColorPointer( 3, GL_FLOAT, 0, (char *) NULL ); // SETUP COLOR POINTER
glDrawArrays(GL_QUADS, 0, 4); // DRAW QUAD WITH 4 VERTICES
glXSwapBuffers(dpy, (GLXDrawable)win); } // SWAP BUFFERS
//////////////////////////////////////////////////////////////////////////////////////////
// INIT VBO //
//////////////////////////////////////////////////////////////////////////////////////////
void InitVBO() {
float vert[][3] = { {-1., -1., 0.} , {1., -1., 0.} , {1., 1., 0.} , {-1., 1., 0.} };
float col[][3] = { { 1., 0., 0.} , {0., 1., 0.} , {1., 1., 0.} , { 1., 1., 1.} };
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) glXGetProcAddressARB((const GLubyte*)"glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC) glXGetProcAddressARB((const GLubyte*)"glBindBufferARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC) glXGetProcAddressARB((const GLubyte*)"glBufferDataARB");
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) glXGetProcAddressARB((const GLubyte*)"glDeleteBuffersARB");
if(glGenBuffersARB == NULL)
printf(" VBO extension not available
");
glGenBuffersARB(2, VBOid);
printf("
vertex buffer id : %8i
color buffer id : %8i
", VBOid[0], VBOid[1]);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOid[0] );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, 4*3*sizeof(float), vert, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VBOid[1] );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, 4*3*sizeof(float), col, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY); }
//////////////////////////////////////////////////////////////////////////////////////////
// //
// MAIN PROG //
// //
//////////////////////////////////////////////////////////////////////////////////////////
void main(int argc, char *argv[]) {
XSetWindowAttributes swa;
unsigned long cmask = CWColormap | CWBorderPixel | CWEventMask;
XEvent xev;
swa.colormap = cmap;
swa.event_mask = ExposureMask | ButtonPressMask;
swa.border_pixel = 0;
win = XCreateWindow(dpy, root, 0, 0, 500, 500, 0, vi->depth, 1, vi->visual, cmask, &swa);
glXMakeCurrent (dpy, win, glc);
XMapWindow(dpy, win);
XStoreName(dpy, win, "VBO TEST");
InitVBO();
while(true) {
XNextEvent(dpy, &xev);
if(xev.type == Expose) { // EXPOSE EVENT
ExposeFunc(); }
else if(xev.type == ButtonPress) { // EXIT ON MOUSE BUTTON CLICK
glDeleteBuffersARB(2, VBOid);
exit(0); } } }
//
// gcc -O3 -o vbo vbo.cc -lGL -lGLU -lX11 -lm -lstdc++
//