Jump to content


VertexBufferObjects problem.


9 replies to this topic

#1 eddie

    Senior Member

  • Members
  • PipPipPipPip
  • 751 posts

Posted 25 July 2006 - 03:02 PM

Hey.

So, I'm relatively new to graphics programming, as I'm mostly a tools guy by trade. I'm trying to play around with VertexBufferObjects/DrawArrays (are they synonyms? Seems like it, or at least they go hand in hand), but I'm not having any luck.

I've basically used Luke Philpot's code from the DevMaster wiki, with some modification in parts (it's not really correct and doesn't compile straight-away), but for some odd reason nothing shows up. My coordinates seem to be OK (if I use a standard glBegin()/glEnd(), I get a nice shiny triangle), but nothing shows up!

I've tried making a colour buffer, tried putting glEnable/DisableClientState() calls at the beginning/end of every frame, and various other things, but to no avail.

Can anyone see what I don't? All the tutorials I'm finding are so mixed up with other things I don't want to confuse myself with, I can't find a simple VBO-only tutorial.

Cheers.


// Framework

// (c) 2003 Luke Philpot.


#define BUFFER_OFFSET(i) ((char *)NULL + (i))


#define win32 // comment out for non win32


#ifdef win32

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#endif


#include <SDL/SDL.h>

#include <GL/gl.h>

#include <GL/glu.h>

#include "glext.h"


// VBO Extension Definitions, From glext.h

#define GL_ARRAY_BUFFER_ARB 0x8892

#define GL_STATIC_DRAW_ARB 0x88E4

typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);

typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);

typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);

typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);


// 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


int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nshow)

{

	SDL_Event e; // for input


	// init window


	SDL_Init(SDL_INIT_VIDEO);

	SDL_SetVideoMode(640, 480, 32, 2);


	// set up OpenGL

	glMatrixMode(GL_PROJECTION);					

	glLoadIdentity();


	gluPerspective(45, (float) 640 / (float) 480, 1, 512);


	glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");

	glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");

	glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");


	// enable depth testing

	glEnable(GL_DEPTH_TEST);

	glDepthFunc(GL_LEQUAL);


	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);


	GLfloat vertexData[] =	{  0.f,  1.f, 0.f

							, -1.f, -1.f, 0.f

							,  1.f, -1.f, 0.f

							};


	GLuint vertexBuffer = 0;


	glGenBuffersARB(1, &vertexBuffer);

	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData, GL_STATIC_DRAW_ARB);


	glEnableClientState(GL_VERTEX_ARRAY);


	while (!SDL_PollEvent(&e) || e.key.keysym.sym != SDLK_ESCAPE) // check whether esc has been pressed

	{

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


			glMatrixMode(GL_MODELVIEW);

			glLoadIdentity();


			glTranslatef(0, 0, -5);


			glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);


			glVertexPointer(3, GL_FLOAT, 0, 0);


			glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);


		SDL_GL_SwapBuffers();

	}

	

	glDisableClientState( GL_VERTEX_ARRAY );


	return 0;

}




#2 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 939 posts

Posted 25 July 2006 - 04:03 PM

After your 'glGenBuffersARB(1, &vertexBuffer);', change the line to 'glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);'. The zero you provide means that no buffer is bound, hence no data is uploaded.
"Stupid bug! You go squish now!!" - Homer Simpson

#3 eddie

    Senior Member

  • Members
  • PipPipPipPip
  • 751 posts

Posted 25 July 2006 - 05:05 PM

Wow, that's embarrasing.

Luckily for me, that code is part of the original demo, found here:.

Can anyone update it? I don't seem to have access.

Code that seems to work for me:

// Framework
// (c) 2003 Luke Philpot.

#define BUFFER_OFFSET(i) ((char *)NULL + (i))

#define win32 // comment out for non win32

#ifdef win32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

#include <SDL/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>

// VBO Extension Definitions, From glext.h
#define GL_ARRAY_BUFFER_ARB 0x8892
#define GL_STATIC_DRAW_ARB 0x88E4
typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);

// 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

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nshow)
{
	SDL_Event e; // for input

	// init window

	SDL_Init(SDL_INIT_VIDEO);
	SDL_SetVideoMode(640, 480, 32, 2);

	// set up OpenGL
	glMatrixMode(GL_PROJECTION);					
	glLoadIdentity();

	gluPerspective(45, (float) 640 / (float) 480, 1, 512);

	glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
	glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
	glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");

	// enable depth testing
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);

	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

	GLfloat vertexData[] =	{  0.f,  1.f, 0.f
							, -1.f, -1.f, 0.f
							,  1.f, -1.f, 0.f
							};

	GLuint vertexBuffer = 0;

	glGenBuffersARB(1, &vertexBuffer);
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertexData), vertexData, GL_STATIC_DRAW_ARB);

	glEnableClientState(GL_VERTEX_ARRAY);

	while (!SDL_PollEvent(&e) || e.key.keysym.sym != SDLK_ESCAPE) // check whether esc has been pressed
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();

			glTranslatef(0, 0, -5);

			glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);

			glVertexPointer(3, GL_FLOAT, 0, 0);

			glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);

		SDL_GL_SwapBuffers();
	}
	
	glDisableClientState( GL_VERTEX_ARRAY );

	return 0;
}


#4 eddie

    Senior Member

  • Members
  • PipPipPipPip
  • 751 posts

Posted 25 July 2006 - 07:31 PM

I took a little bit of time and polished up my demo a bit, and I've posted it on my site as a demo . I'd be willing to submit it to DevMaster if people want it.

#5 TheNut

    Senior Member

  • Moderators
  • 1718 posts
  • LocationCyberspace

Posted 26 July 2006 - 10:40 PM

What?! No fancy 10 million polygonal heightmap? No super high-resolution models? Pffft…

Tease =)

Here are some performance tips about your code. You won’t see anything significant with a simple triangle, but with complex scenes it can make a difference.

1) 156. glMatrixMode(GL_MODELVIEW);
You need only call this once as OpenGL will save the last state. Move it outside the loop

2) 160. glTranslatef(0, 0, -5);
You can just set the Z-coordinate of the triangle in the vertexData[] array if this is supposed to be static geometry.

3) 173. glColorPointer (3, GL_FLOAT, 0, 0);
It’s slightly faster to represent colours as GL_BYTE (ie: 0 – 255) and there’s virtually no quality difference.


It’s always best to illustrate VBOs with high polygonal geometry. You can create a random heightmap very simply in software with just two loops. BTW, VBOs use to be called "Vertex Array Range" and was an nVidia specific implementation back in the old days.
http://www.nutty.ca - Being a nut has its advantages.

#6 eddie

    Senior Member

  • Members
  • PipPipPipPip
  • 751 posts

Posted 27 July 2006 - 12:04 AM

Hey TheNut!

Thanks for the pointers. Yeah, it's pretty basic so far, but that's the idea. I'm going to use it to build off of it and see what I can come up with. :)

My next big 'task' is to see if I can interleave it (as I understand that can give you a performance gain due to reduced cache misses) and wrap it all in a loving C++ wrapper to make it easy to use.

The only thing I'm having issues with right now is trying to undertand if I should be 'interleaving' it by putting coordinates in as { [X], [R], [Y], [G], [Z], [B], [W], [A] }, and setting the stride to 1, or if I'm to do things as { [X], [Y], [Z], [W], [R], [G], [B], [A]} and adjusting the third parameter to gl*Pointer accordingly.

Except I can't seem to get gl*Pointer to take a third parameter (for some reason only 0 works)! Sigh. One day I'll understand all this.

Thanks for clearing up the VBO vs. VAR thing, by the way.

#7 eddie

    Senior Member

  • Members
  • PipPipPipPip
  • 751 posts

Posted 27 July 2006 - 12:46 AM

Ah, OK, so I got it. I was confused because I thought I needed the third parameter to be a void* pointer to memory to start off of. From what I understand, the VBO extension overrides that and makes the last parameter actually a float that it uses to calculate the starting offset.... Not that I could find any documentation that told me this.

Anyhow, that appears to work! And I hear that's the "optimal" way of doing it, so huzzah!

Thanks. ;) Maybe I'll mark that up in a second tutorial, after I take TheNut's points and merge them into my first. Yay, basic VBO's will work now.

#8 Reedbeta

    DevMaster Staff

  • Administrators
  • 5340 posts
  • LocationSanta Clara, CA

Posted 27 July 2006 - 12:55 AM

eddie said:

The only thing I'm having issues with right now is trying to undertand if I should be 'interleaving' it by putting coordinates in as { [X], [R], [Y], [G], [Z], , [W], [A] }, and setting the stride to 1, or if I'm to do things as { [X], [Y], [Z], [W], [R], [G], [B], [A]} and adjusting the third parameter to gl*Pointer accordingly.

Do the second. Keep the position parts together and the color parts together. That's how the gl*Pointer functions will expect the data, you can't have separate streams for X, Y, Z, and W components - only a stream for vertex positions. Accordingly keep all the data for a single vertex together. If you use one of the 'standard' formats, you can use glInterleavedArrays to set up all the applicable pointers at once, but this is just a shortcut and doesn't let you do anything you couldn't do with the gl*Pointer functions.

Quote

Except I can't seem to get gl*Pointer to take a third parameter (for some reason only 0 works)!

That's odd. You should set the third parameter to the size of your vertex struct.

[b]Edit:
You meant the 4th parameter, I guess, which is the pointer parameter.

Quote

Not that I could find any documentation that told me this.

http://oss.sgi.com/p...ffer_object.txt explains it in all the gory detail. ;)
reedbeta.com - developer blog, OpenGL demos, and other projects

#9 eddie

    Senior Member

  • Members
  • PipPipPipPip
  • 751 posts

Posted 27 July 2006 - 02:14 PM

Right, sorry I meant the 4th. My bad.

Wow, thanks for that link Reedbeta. I didn't find that in any of my searches. Very tasty.

#10 Reedbeta

    DevMaster Staff

  • Administrators
  • 5340 posts
  • LocationSanta Clara, CA

Posted 27 July 2006 - 11:34 PM

http://oss.sgi.com/p...ample/registry/ has the official ARB/vendor specs on all the published extensions. There's noplace else I go for extension documentation. ;)
reedbeta.com - developer blog, OpenGL demos, and other projects





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users