Why are my VBO's going so slooooowwww?

Ok, I basically followed the vertex buffer object tutorial on nehe.gamedev.net for a terrain engine that I’m writing.

The engine basically generates an array of heightpoints, which is then uses to create a mesh. The mesh is rendered using triangle strips, and in order to conserve memory, I used glDrawElements, as opposed to glDrawArrays. This allowed me to only store each vertex in memory once, rather than repeating it.

When I run the nehe code, it runs at about 90fps on a radeon 7500. However, random rows of polygons go straight across the top of the terrain, leaving triangular holes and long triangle stips going across the screen. He also textures his terrain, and chose not to conserve memory by using glDrawArrays.

The thing is, my terrain engine runs at about .5fps on a radeon 7500. I made sure that the radeon 7500 did have VBO’s first, by installing the latest driver. In my code, you will see that I didn’t do much checking to see if the extension exists, mainly because I’m at the testing stage right now and I’m only concerned with getting the code to run fast. My engine doesn’t even do any texturing, and when rendering a map of the same size, mine slows down alot. I’ve tried doing just a vertex array, without color, and I saw no performance increase. I tried using glDrawArrays and taking up more memory, and saw no performance gain. And by doing that, I even got the same strange artifacts as Nehe got.

The thing is, my code runs just fine on a GeForce 2MX and pentium II at 300mhz. On a pentium 4 at 2ghz and radeon 7500, though, it lags a bunch (.5fps). Nehe’s code, on the other hand, runs at 90fps and 60fps respectively, with the same sized map. He uses a 512x512 one, but scales it down to like 256x256. I use a 256x256 one, and have tried lowering but not much happens in the way of performance increase until I get down to like 64x64, which is totally unacceptable on a radeon 7500, even though it is a pretty crappy graphics card.

So can anyone figure out why my code runs so much slower than Nehe’s, when I use a triangle strip to render and don’t texture, and he textures and uses normal triangles? I’m open to any suggestions as this point.

Thankyou for your help if you took the time to read this or look at my code. My code isn’t the prettiest right now, but that’s not what I’m concerned with at this point.

#define WIN32_LEAN_AND_MEAN
#include <allegro.h>
#include <winalleg.h>
#include <windows.h>
#include <alleggl.h>
#include <math.h>
#include <process.h>
#include
#include
#include
using namespace std;
#include <gl/glu.h>
#include <math.h>
#include <assert.h>
#include
#include “cmText/cmText.cpp”
#include “cmTimer/cmTimer.cpp”
#include “HillTerrain/rfHillTerrain.cpp”
using namespace RobotFrog;
using namespace std;

#define MAP_SCALE 4.0f
#define CLM_FAILED false
#define CLM_PASSED true
#define MOVEMENT_SIZE 4.0f
#define COLOR_CHANGE .90f
#define MAX_HEIGHT 255

#define RAD(n)(n/180.0f*3.14159)

int mousedx,mousedy;

unsigned int vb_name;
unsigned int vbc_name;

float xpos=0,ypos=-400,zpos=0;
float hangle=90.0f,vangle=0;
int mapx=0,mapy=0;

float *terrain_vertexes=NULL;
float *terrain_colors=NULL;

unsigned int *vertex_indexes=NULL;
int offset=0;

cmTEXTID myID;

bool Initialize();
void CreateWave();
void Render();
void CleanUp();
void UserInput();

int main()
{
bool done=false;
if (!Initialize())
return 0;
while (!done)
{
UserInput();
if (key[KEY_ESC])
done=true;
if (!done)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
Render();
allegro_gl_flip();
}
}
CleanUp();
return 0;
}
END_OF_MAIN();

bool Initialize()
{
allegro_init();
install_allegro_gl();
install_keyboard();
install_mouse();

allegro_gl_set(AGL_Z_DEPTH, 8);
allegro_gl_set(AGL_COLOR_DEPTH, 16);
allegro_gl_set(AGL_SUGGEST, AGL_Z_DEPTH | AGL_COLOR_DEPTH);
const int resx=1024,resy=768;
set_gfx_mode(GFX_OPENGL_FULLSCREEN, resx, resy, 0, 0);
scare_mouse();

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)resx/(GLfloat)resy,1.0f,5000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//glPolygonMode(GL_FRONT,GL_LINE);
//glPolygonMode(GL_BACK,GL_LINE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
glShadeModel(GL_SMOOTH);

mapx=256;
mapy=mapx;
terrain_vertexes=(float )malloc(sizeof(float)mapxmapy3);
terrain_colors=(float )malloc(sizeof(float)mapxmapy3);
if (!terrain_vertexes| |!terrain_colors)
return CLM_FAILED;

HillTerrain my_terrain(mapx,0.0,40.0f,200,1,false,1234);
my_terrain.Generate();
for (int x=0;x<my_terrain.GetSize()3;x+=3)
{
for (int y=0;y<my_terrain.GetSize();y++)
{
terrain_vertexes[x+y
mapx3]=(x/3)(int)MAP_SCALE;
terrain_vertexes[1+x+ymapx3]=(float)(my_terrain.GetCell(x/3,y)MAX_HEIGHT);
terrain_vertexes[2+x+y
mapx3]=-y(int)MAP_SCALE;

     terrain_colors[0+x+y*mapx*3]=0.0f;
     terrain_colors[1+x+y*mapx*3]=(float)(my_terrain.GetCell(x/3,y)*MAX_HEIGHT)/255.0f*COLOR_CHANGE+(1-COLOR_CHANGE);
     terrain_colors[2+x+y*mapx*3]=0.0f;  
  }  

}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

unsigned int cur_index=0;
vertex_indexes=(unsigned int )malloc(sizeof(unsigned int)2mapx(mapy-1));

if (!vertex_indexes)
return CLM_FAILED;

cur_index=0;

for (int y=0;y<mapy-1;y++)
{
vertex_indexes[cur_index++]=ymapx;
vertex_indexes[cur_index++]=(y+1)mapx;
for (int x=1;x<mapx;x++)
{
vertex_indexes[cur_index++]=x+y
mapx;
vertex_indexes[cur_index++]=x+(y+1)mapx;
}
}
glGenBuffersARB( 1, &vb_name );
glBindBufferARB( GL_ARRAY_BUFFER_ARB,vb_name);
glBufferDataARB( GL_ARRAY_BUFFER_ARB, mapx
mapy
sizeof(float)3, terrain_vertexes, GL_STATIC_DRAW_ARB );
//glVertexPointer(3,GL_FLOAT,0,(char
)NULL);

glGenBuffersARB(1,&vbc_name);
glBindBufferARB(GL_ARRAY_BUFFER_ARB,vbc_name);
glBufferDataARB(GL_ARRAY_BUFFER_ARB,sizeof(float)mapxmapy3,terrain_colors,GL_STATIC_DRAW_ARB);
//glColorPointer(3,GL_FLOAT,0,(char
)NULL);

return CLM_PASSED;
}

void CreateWave()
{
}

void Render()
{
/*
glRotatef(vangle,1.0f,0.0f,0.0f);
glRotatef(hangle-90.0f,0.0f,1.0f,0.0f);
glTranslatef(xpos,ypos,zpos);
/
glRotatef(25.0f,1.0f,0.0f,0.0f);
glRotatef(45.0f,0.0f,1.0f,0.0f);
glTranslatef(1.2
MAP_SCALE*(mapx-1)/2,0.0f,1.2*-MAP_SCALE*(mapy-1)/2);
glRotatef(hangle,0.0f,1.0f,0.0f);
glTranslatef(-MAP_SCALE*(mapx-1)/2,ypos,MAP_SCALE*(mapy-1)/2);

glBindBufferARB(GL_ARRAY_BUFFER,vb_name);
glVertexPointer(3,GL_FLOAT,0,(char*)NULL);
glBindBufferARB(GL_ARRAY_BUFFER,vbc_name);
glColorPointer(3,GL_FLOAT,0,(char*)NULL);

glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);

for (int y=0;y<mapy-1;y++)
glDrawElements(GL_TRIANGLE_STRIP,mapx2,GL_UNSIGNED_INT,(vertex_indexes+ymapx*2));
}

void CleanUp()
{
unsigned int nBuffers[2] = { vb_name, vbc_name };
glDeleteBuffersARB( 2, nBuffers );
free (terrain_vertexes);
free (terrain_colors);
free (vertex_indexes);
remove_keyboard();
remove_mouse();
}

void UserInput()
{
poll_keyboard();
poll_mouse();
get_mouse_mickeys(&mousedx,&mousedy);
hangle+=mousedx;
vangle+=mousedy;
if (hangle>360.0f)
hangle-=360.0f;
if (hangle<=0.0f)
hangle+=360.0f;
if (key[KEY_LEFT]| |key[KEY_A])
{
xpos+=MOVEMENT_SIZEsin(RAD(hangle));
zpos-=MOVEMENT_SIZE
cos(RAD(hangle));
}
if (key[KEY_RIGHT]| |key[KEY_D])
{
xpos-=MOVEMENT_SIZEsin(RAD(hangle));
zpos+=MOVEMENT_SIZE
cos(RAD(hangle));
}
if (key[KEY_UP]| |key[KEY_W])
{
xpos+=MOVEMENT_SIZEcos(RAD(hangle))cos(RAD(vangle));
zpos+=MOVEMENT_SIZE
sin(RAD(hangle))cos(RAD(vangle));
ypos+=MOVEMENT_SIZE
sin(RAD(vangle));
}
if (key[KEY_DOWN]| |key[KEY_S])
{
xpos-=MOVEMENT_SIZE
cos(RAD(hangle))cos(RAD(vangle));
zpos-=MOVEMENT_SIZE
sin(RAD(hangle))cos(RAD(vangle));
ypos-=MOVEMENT_SIZE
sin(RAD(vangle));
}
}

Try not using trianglestrips… I think that might give you the lightning fast performance gain you are asking for.

The question was already answered here .