# VBO's - also the way to go for lower vertice counts?

This topic is 3316 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey, I've been testing with VBO's. Basically, I drew 100 triangles (2f) with colours (3f), and the results were about this: VBO: 1000 FPS IM: 25 FPS DL: 25 FPS Now, I want to use VBO's for rendering text for sure, however, I was wondering if using VBO's is a good option for small number of triangles / quads as well? Basically, it's a GUI system, and I thought speed could be higher if I'd use a VBO per element, to avoid passing the same data over and over again. So every button has an VBO...and perhaps in the end I could put the whole GUI in one VBO! The latter sounds attractive, but how well does it work to have lots of VBO's, where each VBO's has a couple of vertices?

##### Share on other sites
So, I've been thinking.

Beforehand I don't know how many elements will need to be stored in the VBO, so I guess I'll be having a new VBO per element (which always is a quad or two). How well does this work?

##### Share on other sites
It won't perform well if you will have lots of objects to render and each one is in a separate VBO.
Make one large VBO, but not too large. 1MB to 8MB should be ok for the driver. Don't make gigantic VBOs (200MB) or else the driver might give a GL_OUT_OF_MEMORY.

##### Share on other sites
Okay thanks, would I need to reallocate and copy the old data whenever I need to add something to the VBO? The diversity between elements is quite big (one would use colours, the other a texture, etc)...I can't see how this can be done with a few arrays. Seems a bit complicated :S

##### Share on other sites
If you have objects with different vertex attribute, example : vertex, normals
and some other with vertex, texcoord normals, you could make 2 VBOs.
That's what I do.
In total, perhaps I have 5 VBOs for each type. If one VBO becomes full, I allocate another.

For update a subsection of a VBO, use glBufferSubData.

##### Share on other sites
Quote:
 I've been testing with VBO's. Basically, I drew 100 triangles (2f) with colours (3f), and the results were about this:VBO: 1000 FPSIM: 25 FPSDL: 25 FPS

then something is majorly buggered with your program, for that data there should be practically zero difference in framerate between VBO/IM/DLs.

##### Share on other sites
Quote:
Original post by zedz
Quote:
 I've been testing with VBO's. Basically, I drew 100 triangles (2f) with colours (3f), and the results were about this:VBO: 1000 FPSIM: 25 FPSDL: 25 FPS

then something is majorly buggered with your program, for that data there should be practically zero difference in framerate between VBO/IM/DLs.

Yes, I was surprised DL's did so bad, here's the code:

//-----------------------------------------------------------------------------// Shogun3D's basic vertex buffer object example.//// Disclamer:  Use this code as you see fit, for both personal and/or commercial//			   usages.  You don't exactly have to give me credit for using this//			   code in your own projects (although I would appreciate it if you//			   did), but you could at let me know that this has benefited you//			   in one way or another, because I didn't write this code just for//			   myself you know ^^//// File:	main.cpp// Desc:	Basic code for using and rendering geometry with using vertex buffer//			objects (GL_ARB_vertex_buffer_object).// Date:	August 2, 2008//-----------------------------------------------------------------------------#include <windows.h>#include "window.hpp"#include <stdio.h>#include <gl\gl.h>#include <gl\glu.h>#include <gl\glext.h>//#include <gl\wglext.h>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);#define MAX 1000//-----------------------------------------------------------------------------// GlobalsGLuint uTriangleBuffer;GLfloat vertices[6 * MAX];GLubyte colors[9 * MAX];PFNGLGENBUFFERSPROC glGenBuffersARB;PFNGLDELETEBUFFERSPROC glDeleteBuffersARB;PFNGLBINDBUFFERPROC glBindBufferARB;PFNGLBUFFERDATAPROC glBufferDataARB;PFNGLBUFFERSUBDATAPROC glBufferSubDataARB;#define BUFFER_OFFSET(i) (void*)(NULL + (i))//-----------------------------------------------------------------------------// Name: glh_extension_supported// Desc: Checks the list of OpenGL extensions supported by this videocard/driver//		 to see if it's supported.  This function was borrowed from the NVIDIA//		 SDK (v9.5).  I was too lazy to write my own extension checking function :)//		 See glh_extensions.h//-----------------------------------------------------------------------------int glh_extension_supported( const char *extension ){    static const GLubyte *extensions = NULL;    const GLubyte *start;    GLubyte *where, *terminator;    // Extension names should not have spaces.    where = (GLubyte *) strchr( extension, ' ');    if ( where || *extension == '\0')      return 0;    if ( !extensions )      extensions = glGetString( GL_EXTENSIONS );    // It takes a bit of care to be fool-proof about parsing the    // OpenGL extensions string.  Don't be fooled by sub-strings,    // etc.    start = extensions;    for (;;)    {        where = (GLubyte *) strstr( (const char *) start, extension );        if ( !where )            break;        terminator = where + strlen( extension );        if ( where == start || *(where - 1) == ' ' )        {            if ( *terminator == ' ' || *terminator == '\0' )            {                return 1;            }        }        start = terminator;    }    return 0;}GLuint list;void InitScene( void ){	// Enable perspective correction and polygon smoothing	glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );	glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );	// Enable client states for vertices and colors	glEnableClientState( GL_COLOR_ARRAY );	glEnableClientState( GL_VERTEX_ARRAY );	// Check extension registery for VBO support	if( !glh_extension_supported( "GL_ARB_vertex_buffer_object" ) )	{		printf( "ERROR: GL_ARB_vertex_buffer_object not found!\n\n" );		exit(1);	}	// print the list of supported extensions	//printf( "%s\n", glGetString( GL_EXTENSIONS ) );	// Now we can initialize the extension's functions we plan on using.	// Since this is a simple static VBO, we'll only need 5 of these	// functions for now.	glGenBuffersARB = (PFNGLGENBUFFERSPROC) wglGetProcAddress( "glGenBuffersARB" );	glDeleteBuffersARB = (PFNGLDELETEBUFFERSPROC) wglGetProcAddress( "glDeleteBuffersARB" );	glBindBufferARB = (PFNGLBINDBUFFERPROC) wglGetProcAddress( "glBindBufferARB" );	glBufferDataARB = (PFNGLBUFFERDATAPROC) wglGetProcAddress( "glBufferDataARB" );	glBufferSubDataARB = (PFNGLBUFFERSUBDATAPROC) wglGetProcAddress( "glBufferSubDataARB" );	// If VBOs are supported on this OpenGL implimentation, generate	// a single buffer to store vertex data for one triangle.  This	// VBO will be static for now.	for (int i = 0; i < MAX; i++)    {        vertices[(i * 6) + 0] = vertices[(i * 6) + 4] = 1024;        vertices[(i * 6) + 1] = vertices[(i * 6) + 2] = 0;        vertices[(i * 6) + 3] = vertices[(i * 6) + 5] = 768;        colors[(i * 9) + 0] = colors[(i * 9) + 4] = colors[(i * 9) + 8] = 255;        colors[(i * 9) + 1] = colors[(i * 9) + 2] = colors[(i * 9) + 3] = 0;        colors[(i * 9) + 5] = colors[(i * 9) + 6] = colors[(i * 9) + 7] = 0;    }	// Generate buffer	glGenBuffersARB( 1, &uTriangleBuffer );	// Tell OpenGL that this is the currently active buffer	glBindBufferARB( GL_ARRAY_BUFFER, uTriangleBuffer );	// Initialize the buffer for the first time.  Make it large enough to hold	// 9 floats and 9 bytes.  Leave the buffer data uninitialized for now.	glBufferDataARB( GL_ARRAY_BUFFER,							// Buffer type					9 * (sizeof(GLfloat) + sizeof(GLubyte)),	// Buffer size					NULL,										// Set actual buffer data to NULL					GL_STATIC_DRAW );							// Create static buffer	// Set the vertex data	glBufferSubDataARB( GL_ARRAY_BUFFER,		// Buffer type						0,						// Location as to where to start writing data (0 = beginning)						9 * sizeof( GLfloat ),	// The amount of data being written						vertices );				// Buffer data to be written at the previously specified location	// Set the color data for each vertex	glBufferSubDataARB( GL_ARRAY_BUFFER,						9 * sizeof( GLfloat ),						9 * sizeof( GLubyte ),						colors );    list = glGenLists(1);    glNewList(list, GL_COMPILE);        glBegin(GL_TRIANGLES);            for (int i = 0; i < MAX; i++)            {                glColor3f(255, 0, 63); glVertex2f(1024, 0);                glColor3f(63, 255, 0); glVertex2f(0, 768);                glColor3f(63, 0, 255); glVertex2f(1024, 768);            }        glEnd();    glEndList();}int main( int argc, char* argv[] ){    int width = 1024;    int height = 768;    Window::initialise("VBO", width, height, false, 0);    glViewport(0, 0, width, height);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);    glMatrixMode(GL_MODELVIEW);    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);	InitScene();	bool active = true;	unsigned int type = 0;    while (active)    {        SDL_Event sdl_event;        while (SDL_PollEvent(&sdl_event))        {            if (sdl_event.type == SDL_QUIT || (sdl_event.type == SDL_KEYDOWN && sdl_event.key.keysym.sym == SDLK_ESCAPE))            {                active = false;            }            if (sdl_event.type == SDL_KEYDOWN && sdl_event.key.keysym.sym == SDLK_RETURN)            {                type++;                if (type == 3)                {                    type = 0;                }            }        }        Window::pre_frame();        if (!type)        {            // Set the VBO to current            glBindBufferARB( GL_ARRAY_BUFFER, uTriangleBuffer );            // Specify the vertex and color attributes            glVertexPointer( 2, GL_FLOAT, 0, 0 );            glColorPointer( 3, GL_UNSIGNED_BYTE, 0, BUFFER_OFFSET( 9*sizeof(GLfloat) ) );            // Render the VBO            glDrawArrays( GL_TRIANGLES, 0, 3 );        }        else if (type == 1)        {            glBegin(GL_TRIANGLES);                for (int i = 0; i < MAX; i++)                {                    glColor3f(255, 63, 0); glVertex2f(1024, 0);                    glColor3f(0, 255, 63); glVertex2f(0, 768);                    glColor3f(0, 63, 255); glVertex2f(1024, 768);                }            glEnd();        }        else        {            glCallList(list);        }        Window::post_frame();        Window::caption_fps();    }    glDeleteLists(list, 1);	glDeleteBuffersARB( 1, &uTriangleBuffer );	Window::shutdown();	return 0;}

Sorry for the ugly code, it was a quick test to get VBO's working.

##### Share on other sites
I assumed you tested it :)
now from my quick look, it looks like youre drawing completely different things with VBO's then u are with DL/IM.
hence the difference in framerate.

Its a bit hard to see what youre actually doing but it looks like youre drawing 1 triangle with the VBO yet 100 with DL/IM.

but anyways what youre testing is not vertex rate but fillrate, drawing 100 largish triangles will result in the same frame in immeditae mode as it will with DL or VBO.
try making your window smaller the framerate improves, right? in that case VBO/DL/IM arent the issue

if u really want to see a large difference between immediate vs VBO/DL then u need >10,000 small triangles. (test in a window of 320x240)

##### Share on other sites
There must be something wrong, but I think I got the VBO filled up:

for (int i = 0; i < MAX; i++)    {        vertices[(i * 6) + 0] = vertices[(i * 6) + 4] = 1024;        vertices[(i * 6) + 1] = vertices[(i * 6) + 2] = 0;        vertices[(i * 6) + 3] = vertices[(i * 6) + 5] = 768;        colors[(i * 9) + 0] = colors[(i * 9) + 4] = colors[(i * 9) + 8] = 255;        colors[(i * 9) + 1] = colors[(i * 9) + 2] = colors[(i * 9) + 3] = 0;        colors[(i * 9) + 5] = colors[(i * 9) + 6] = colors[(i * 9) + 7] = 0;    }

Anyways, 100 triangles were giving low FPS in IM, so wasn't even considering 10.000 ^^. Thanks for the info, I will retry this.

EDIT:
You were right, the buffer initialisation didn't have the appropriate size. The buffer only drew one triangle, as you said. Thanks! Will be fixing this as soon as I know how VBO's really work (this was just copy-paste work :-/).