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

Started by
7 comments, last by Decrius 15 years, 3 months ago
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?
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
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?
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
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.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
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
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
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.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);
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.
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//-----------------------------------------------------------------------------// 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.
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
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)
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 :-/).
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora

This topic is closed to new replies.

Advertisement