PDA

View Full Version : Vertex Buffer Objects



ToddAtWSU
02-20-2006, 08:02 AM
I am trying to draw an object using vertex buffer objects. I read the vertices from a file into an array of GLdouble and the indices into an array of GLuint.



--------------------Configuration: proj2 - Win32 Debug--------------------
Compiling...
proj2.cpp
C:\Documents and Settings\Administrator\My Documents\CEG477\proj2.cpp(336) : error C2065: 'glGenBuffers' : undeclared identifier
C:\Documents and Settings\Administrator\My Documents\CEG477\proj2.cpp(338) : error C2065: 'glBindBuffer' : undeclared identifier
C:\Documents and Settings\Administrator\My Documents\CEG477\proj2.cpp(338) : error C2065: 'GL_ARRAY_BUFFER' : undeclared identifier
C:\Documents and Settings\Administrator\My Documents\CEG477\proj2.cpp(339) : error C2065: 'glBufferData' : undeclared identifier
C:\Documents and Settings\Administrator\My Documents\CEG477\proj2.cpp(339) : error C2065: 'GL_STATIC_DRAW' : undeclared identifier
C:\Documents and Settings\Administrator\My Documents\CEG477\proj2.cpp(343) : error C2065: 'GL_ELEMENT_ARRAY_BUFFER' : undeclared identifier
Error executing cl.exe.

proj2.exe - 6 error(s), 0 warning(s)

Anybody have any ideas why I am getting these errors? I can draw objects using display lists and vertex arrays, but when I try to make the VBO function calls, I get these errors. Do I need to include something else? Or am I making some very bad function calls? Also, how do I know if I can handle VBOs? I have a GeForce 6800 GT with 512 MB memory and have driver 8.1.9.8 dated 12/10/2005. Will all this work for VBOs? Thanks for all your help!

Zengar
02-20-2006, 08:27 AM
You know, this all indicates how spoiled C++ programmers are :-/ I don't meen to offend you, this is just a common observation. People start advanced programming but ignore the most basic things like language design, libraries, linking etc. It's like you learn driving but don't know that you must fuel the car first.

Now to your problem: the errors you get simply show that the identifiers you use are not declared anywhere. If you use C++, you should include the glext.h, which can be downloaded here (http://oss.sgi.com/projects/ogl-sample/ABI/glext.h)
The glext.h defines the tokens you need and the function prototypes for all the extensions. If you don't know how to use the extensions in GL, google for it or look up the nehe pages, there are plenty of the tutorials.

Edit: just saw it. Don't use 0 as a buffer handle(as you do in VERTICES). The 0 has a special meaning of disabling the buffer object.

songho
02-20-2006, 09:31 AM
ToddAtWSU,
I have a personal note about VBO. Check it out:
VBO (http://www.songho.ca/opengl/gl_vbo.html)

There is an example program at the bottom of the page. Hope it helps.

ToddAtWSU
02-20-2006, 09:32 AM
No offense taken, but I have been programming with C++ for the last 4 years or so. I am just finishing up my college degree in computer science in a couple months so I know about linking and that sort of thing but am new to OpenGL. Anyways, I didn't realize I needed to add another .h file since this was all described in the Red Book and it never mentioned needing another .h file. Why is this? Thanks!

Zengar
02-20-2006, 12:52 PM
gl.h only defines the version 1.1 core and some small extensions. The above versions are treated like extensions and are placed in the corresponding header. The primary reason is that 1.1 is the lowest verion you can expect, and that on windows all entries above must be queried explicitely.

Sorry for flaming; i recently tried to port my library from pascal to C but it drived me mad so I quit ;-) I have no idea how you guys can work with it.

CrazyButcher
02-20-2006, 01:14 PM
look for those extension wrangling libs, like glew, glee ..., then you include their lib/header and they will handle all the extension stuff.

you need another header, as there is a difference between core gl functions and the ones you get thru extensions such as VBOs. the libs mentioned above, will check if driver supports the extension, and register the proper functionnames.

ToddAtWSU
02-20-2006, 08:01 PM
After I call glGenBuffersARB( 2, buffers ) so I can create a buffer to hold my vertices and one to hold the indices, I get an error that reads:

---------------------------
Microsoft Visual C++
---------------------------
Unhandled exception in proj2.exe: 0xC0000005: Access Violation.
---------------------------
OK
---------------------------

Any ideas what this error is from? Couldit be that my graphics card isn't set up to handle VBOs? If that is the case, how do I set it up? Thanks!

jide
02-20-2006, 09:34 PM
Did you load the VBO extensions correctly ? Did you setup all the vertex pointer correctly ? Check the extension registry about VBOs. And post your code (entire about VBO).

ToddAtWSU
02-21-2006, 05:21 AM
Here is my code that is dealing with VBOs:



#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <fstream>
#include <ctime>
#include <cmath>
#include "zpr.h"
#include "glext.h"

using namespace std;

#define BUFFER_OFFSET( bytes ) ( (GLubyte*) NULL + ( bytes ) )
#define VERTICES 1
#define INDICES 2
#define NUM_BUFFERS 2

// VBO Extension Function Pointers
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL; // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL; // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL; // VBO Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL; // VBO Deletion Procedure

GLdouble *vertices = NULL;
GLfloat *colors = NULL;
GLuint *indices = NULL;
GLuint buffers[NUM_BUFFERS];

void init( )
{
glClearColor ( 1.0, 1.0, 1.0, 0.0 );
glEnable( GL_CULL_FACE ); //Discard the back faces
glShadeModel( GL_FLAT );

// Variables from file I read in
numVertices = vertexnum;
numPolygons = facenum;
numPoints = face;

// Set up the vertex arrays in buffer objects
glGenBuffersARB( NUM_BUFFERS, buffers );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffers[VERTICES] );
glBufferDataARB( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW_ARB );

glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER, buffers[INDICES] );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW_ARB );
}

int main( int argc, char** argv )
{
readply( ); // Function to read the ply file
glutInit( &amp;argc, argv );
glutInitDisplayMode ( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
glutInitWindowSize ( 500,500 );
glutInitWindowPosition ( ( 0 ), ( 0 ) );
glutCreateWindow ( "CEG477 -- Project 1" );

init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
zprInit( );
glutMainLoop( );
return 0;
}
I didn't include all the functions that do not deal with the VBOs. I know the vertex and index arrays are filling in fine because I use the same code and can draw the objects witrh Vertex Arrays or Display Lists. Does this help any? If you need something else, please let me know. The call to glGenBuffersARB is where I get that error. Thanks!

Komat
02-21-2006, 06:08 AM
The call to glGenBuffersARB is where I get that error.You have not initialized the glGenBuffersARB pointer (and other VBO pointers as well) with the address of the corresponding function so, when you attempt to call it, it will cause a crash.

Also you are passing incorrect parameters to the glBufferDataARB function. Second parameter is size of the data however sizeof( indices ) where indices is defined as GLuint * will return size of the pointer not the size of the pointed data.

And finally the drawing loop from you first post calculates incorrect offset because DrawElements expects offset in bytes and your indices are uints.

Komat
02-21-2006, 06:14 AM
One more thing. Arrays in C/C++ are zero based so your INDICES index references beyond the end of the buffers array and so it references a random value.

ToddAtWSU
02-21-2006, 06:24 AM
You have not initialized the glGenBuffersARB pointer (and other VBO pointers as well) with the address of the corresponding function so, when you attempt to call it, it will cause a crash. How do I go about doing this? I have not seen anything talking about this.


Arrays in C/C++ are zero based so your INDICES index references beyond the end of the buffers array and so it references a random value. That's what I thought but when Zengar said
Edit: just saw it. Don't use 0 as a buffer handle(as you do in VERTICES). The 0 has a special meaning of disabling the buffer object. I changed what I had. Thanks for your help once again!!!

ToddAtWSU
02-21-2006, 06:27 AM
So for the size of the vertices I would need to do something like sizeof( glDouble ) * numVertices * 3? Since there are 3 values for each vertex. Or do I not need the sizeof( ) call and just do numVertices * 3? Thanks!

Komat
02-21-2006, 06:37 AM
You have not initialized the glGenBuffersARB pointer (and other VBO pointers as well) with the address of the corresponding function so, when you attempt to call it, it will cause a crash. How do I go about doing this? I have not seen anything talking about this.
On Windows look for description of function wglGetProcAddress. This function expects string with the name of the function and returns pointer to that function.


That's what I thought but when Zengar said
Edit: just saw it. Don't use 0 as a buffer handle(as you do in VERTICES). The 0 has a special meaning of disabling the buffer object. I changed what I had.He probably assumed that you are using VERTICES directly as handle not as index into array of handles generated by glGenBuffers.

Komat
02-21-2006, 06:42 AM
Originally posted by ToddAtWSU:
So for the size of the vertices I would need to do something like sizeof( glDouble ) * numVertices * 3? Since there are 3 values for each vertex. Or do I not need the sizeof( ) call and just do numVertices * 3? Thanks!The size is specified in bytes so you must use the sizeof(GLdouble) if you have three doubles per vertex. Side note: The double format is not natively supported by some HW so you will likely have massive performance penalty if you use that format from VBO.

songho
02-21-2006, 06:43 AM
Originally posted by ToddAtWSU:

You have not initialized the glGenBuffersARB pointer (and other VBO pointers as well) with the address of the corresponding function so, when you attempt to call it, it will cause a crash. How do I go about doing this? I have not seen anything talking about this.You need to get a function pointer from Windows ICD OpenGL driver by using wglGetProcAddress(). And check if the returned pointer holds a valid value, not NULL. Please look at my example code in the previous post for more details.


That's what I thought but when Zengar said I changed what I had. Thanks for your help once again!!!I guess Zengar said that binding a VBO with 0 causes releasing VBO operation. So normal vertex array operation will be re-activated.
==song==

ToddAtWSU
02-21-2006, 12:45 PM
And finally the drawing loop from you first post calculates incorrect offset because DrawElements expects offset in bytes and your indices are uints. I have changed things to



#define BUFFER_OFFSET( bytes ) ( (GLuint*) NULL + ( bytes ) )

glPushMatrix( );
for( int i = 0 ; i < ( numPoints * numPolygons ) ; i += numPoints )
{
glDrawElements( GL_POLYGON, numPoints, GL_UNSIGNED_INT, BUFFER_OFFSET( i ) );
}
glPopMatrix( );
How does this offset work? Does it work like just any other glDrawElements, like if there are six points per polygon, I should increase i by 6 each time? Thanks again for all your help! It doesn't crash out when I use that wglGetProcAddress function!

ToddAtWSU
02-22-2006, 10:29 PM
I got stuff figured out and I can draw from VBOs. My problem was I was having the INDEX_ARRAY point to the ELEMENT_ARRAY_BUFFER and this seemed to be causing some problems. The only thing that I cannot figure out is how to get my color array to work with VBOs. I Call it like this:



glEnableClientState( GL_VERTEX_ARRAY );


glGenBuffersARB( NUM_BUFFERS, buffers );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffers[VERTICES] );
glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, ( sizeof( GLfloat ) * numVertices * 3 ), vertices, GL_STATIC_DRAW_ARB );

glEnableClientState( GL_COLOR_ARRAY );

glBindBufferARB( GL_ARRAY_BUFFER_ARB, buffers[COLORS] );
glColorPointer( 3, GL_FLOAT, 0, (char*) NULL );
glBufferDataARB( GL_ARRAY_BUFFER_ARB, ( sizeof( GLfloat ) * numVertices * 3 ), colors, GL_STATIC_DRAW_ARB );

glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, buffers[INDICES] );
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, ( sizeof( GLuint ) * numPolygons * numPoints ), indices, GL_STATIC_DRAW_ARB );
My code crashes when I try to draw it if this line: glEnableClientState( GL_COLOR_ARRAY );
is uncommented. If I comment it then I get a white object. Any ideas what I am doing wrong to not get color? My drawing code is this:



glPushMatrix( );
for( int i = 0 ; i < ( numPoints * numPolygons ) ; i += numPoints )
{
glDrawElements( GL_POLYGON, numPoints, GL_UNSIGNED_INT, (GLuint*) 0 + i );
}
glPopMatrix( );
Thanks for your help again!!

Komat
02-22-2006, 11:55 PM
Are you allocating correct number of buffers? If buffers[COLORS] is zero then VBO is not used for color buffer and ordinary array starting from address NULL will be used instead which may result in crash.

When you developing something in OGL it is usefull to define macro (so you can simply disable it latter) that will check result of glGetError() to find out if there was an error reported.

ToddAtWSU
02-23-2006, 05:59 AM
That was it, I accidently had COLORS value as 3 when NUM_BUFFERS was 3. COLORS was supposed to be 2 and once I changed that it worked fine. Sucha stupid mistake. Thanks again for all your help!!!