Jump to content
  • Advertisement
Sign in to follow this  
ZMaster

Poor VBO Performance?

This topic is 4815 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

Hi, I ran into a problem when I tried to render models in my engine with the help of VBOs to give it some extra performance. I load the model data from a 3DS file. I have information about vertex coordinates, vertex normals and texture coordinates, which I do upload into the VRAM using ARB_vertex_buffer_object. When it comes to rendering the model, I just bind the data in the VRAM, set the appopriate pointer and start drawing using glDrawElements. I draw several instances of the same model. But compared to drawing vertex arrays without using the VBOs the VBO solution comes up with around 1-2 fps against 75 fps. Any known problems with VBOs that might cause the performance drop here? Thanks, ZMaster

Share this post


Link to post
Share on other sites
Advertisement
I think (though I'm not sure) that if you try to use VBO's on a card that does not support them, they are emulated by storing them in system memory, which could cause a performance hit, though I am not sure that this information is accurate.

Share this post


Link to post
Share on other sites
What hardware is this on?

In our driver's VBO implementation, there are some situations in which we have to internally revert to vertex arrays. When doing this, the performance is virtually identical to the user using VAs in the first place. Since this behavior wasn't difficult to implement, I'd be surprised if this is merely a case of the driver not properly supporting VBOs.

Share this post


Link to post
Share on other sites
I have ATI Radeon 9800 Pro which should support VBOs in Hardware. Newest driver software, everything else works quite well...
I don't upload it every frame, I just triple checked that, I load from outside the rendering loop when the scene is initialized...

Quote:
Original post by phantom
post. code.



I appreciate it if you'd go through my code. I don't expect this from people and this is why I didn't post any in the first place.

The ModelObject class. Every Model is build up from one or more ModelObjects and one or more ModelMaterials (I'll leave materials out).
//Model Objects
class ModelObject
{
public:
void Draw(float fFrame, float fMasterScale);
bool CreateVBO(void);

//Manage the material
int GetMaterial(void) { return nMaterialIdx; }
void SetMaterial(int nMat) { nMaterialIdx = nMat; }

char szName[256]; //Object name

int nMaterialIdx; //Index into the material array
bool bHasTexture; //Is this object textured?

int numOfVertices; //Number of vertices/normals
int numOfNormals; //Number of normals
int numOfTexCoords; //Number of texture coordinates
int numOfFaces; //Number of faces

int numOfPosFrames; //Number of position key frames
int numOfRotFrames; //Number of rotation key frames
int numOfScaleFrames; //Number of scale key frames

Vector3f *pVertices; //Vertex array
Vector3f *pNormals; //Normal array
Vector2f *pTexCoords; //Texture coordinate array
ModelFace *pFaces; //Face array

bool bVBOUsed;
unsigned int nVertexVBO;
unsigned int nNormalVBO;
unsigned int nTexCoordVBO;

int *pPosFrameNum; //Stores position key frames
int *pRotFrameNum; //Stores rotation key frames
int *pScaleFrameNum;//Stores scale key frames
Vector3f *pPos; //Position values
Vector3f *pRotAxis; //Rotation axis values
float *pRotDegree; //Rotation degree values (rad)
Vector3f *pScale; //Scale values

Vector3f vPivot; //The object's pivot point

Matrix4x4 mAnimation; //The object's animation matrix

void ApplyPosition(float fFrame);
void ApplyRotation(float fFrame);
void ApplyScale(float fFrame);

private:
void SetArrayPointers(void);

Vector3f lerp(Vector3f v1, Vector3f v2, float i); //linear interpolation
float lerp(float f1, float f2, float i); //linear interpolation

};



Upload data into the VRAM, set the pointer before the object ist drawn and draw the object:
bool ModelObject::CreateVBO(void)
{
if(bVBOUsed)
return false;

if(!glGenBuffersARB)
return false;

if(!pVertices || !pNormals || !pTexCoords)
return false;

//Vertex Buffer
glGenBuffersARB(1, &nVertexVBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVertexVBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, numOfVertices * sizeof(Vector3f), pVertices, GL_STATIC_DRAW_ARB);

//Normal Buffer
glGenBuffersARB(1, &nNormalVBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nNormalVBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, numOfVertices * sizeof(Vector3f), pNormals, GL_STATIC_DRAW_ARB);

//Tex Coord Buffer
glGenBuffersARB(1, &nTexCoordVBO);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nTexCoordVBO);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, numOfTexCoords * sizeof(Vector2f), pTexCoords, GL_STATIC_DRAW_ARB);

glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

bVBOUsed = true;
return bVBOUsed;
}


///////////// Set the vertex array pointers /////////////////
void ModelObject::SetArrayPointers(void)
{
if(pVertices)
{
if(!bVBOUsed)
{
glVertexPointer(3, GL_FLOAT, 0, pVertices);
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nVertexVBO);
glVertexPointer(3, GL_FLOAT, 0, NULL);
}

glEnableClientState(GL_VERTEX_ARRAY);
}

if(pTexCoords)
{
if(!bVBOUsed)
{
glTexCoordPointer(2, GL_FLOAT, 0, pTexCoords);
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nTexCoordVBO);
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
}

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

if(pNormals)
{
if(!bVBOUsed)
{
glNormalPointer(GL_FLOAT, 0, pNormals);
}
else
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nNormalVBO);
glNormalPointer(GL_FLOAT, 0, NULL);
}

glEnableClientState(GL_NORMAL_ARRAY);
}
}


///////////// Draw an object ////////////////////////////////
void ModelObject::Draw(float fFrame, float fMasterScale)
{
if(!pVertices || numOfVertices <= 0)
return;

//Initialize the array pointers
SetArrayPointers();

//Initialize the animation matrix
mAnimation.LoadIdentity();
//Set the animation values
ApplyPosition(fFrame);
ApplyRotation(fFrame);
//ApplyScale(fFrame);

//Draw the object
glPushMatrix();
mAnimation.Scale(fMasterScale);
mAnimation.Apply();
glDrawElements(GL_TRIANGLES, numOfFaces * 3, GL_UNSIGNED_INT, pFaces);
glPopMatrix();

//Disable the array pointers
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

if(bVBOUsed) glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}


Thank you!

Share this post


Link to post
Share on other sites
I noticed that you're binding your VBO buffers, and THEN enabling the client state. You also disable the client state at the end of drawing each frame. I'm not 100% sure that it matters, but I would first try enabling the client state before binding the buffer. Second, you don't need to keep enabling/disabling the client states. Just enable them once at the beginning (unless you have another reason to be disabling them).

Share this post


Link to post
Share on other sites
I just read the following excerpt on a website:

Quote:
As a result, feedback and selection may not perform well when combined with vertex buffer objects. Additionally, building display lists from data in a vertex buffer object or using glArrayElement() with vertex buffer objects will typically be highly inefficient.


After disabling selections for my models it turns out to give the desired performance boost, though it won't help me much without selection support.
I'm sorry, selection mode simply didn't come to my mind. Though I really don't understand why it is performed on the CPU. I always thought it draws the object with a unique value into the framebuffer and THEN reads back the appropriate value from the framebuffer. But it seems like the whole thing is performed on the CPU?!?

I have to find some way combine fast drawing and selection, maybe with some hybrid approach with VAs for selection mode and VBOs for drawing. Or I try out to only use AABBs for selection mode though I expect this to be a little to inaccurate. Don't know yet.

PS: Does uploading the indices into the vertex array, which are used to draw the model's faces, to the VRAM give more performance?

Share this post


Link to post
Share on other sites
selection picks all objects within the region/ray (not just the closest).
the best/fastest way is to do your own ray->object test with the cpu. selection is useful if u just want an answer and dont want to spend time coding up something optimal

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!