VBO's - also the way to go for lower vertice counts?
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?
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?
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?
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.
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.
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
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.
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.
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 zedzQuote: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.
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)
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:
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 :-/).
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 :-/).
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement