Jump to content
  • Advertisement
Sign in to follow this  
Decrius

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

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 FPS
IM: 25 FPS
DL: 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 this post


Link to post
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 FPS
IM: 25 FPS
DL: 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

//-----------------------------------------------------------------------------
// Globals
GLuint 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 this post


Link to post
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 this post


Link to post
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 :-/).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!