Poor VBO Performance?

Started by
15 comments, last by Mantear 18 years, 7 months ago
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
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.
- relpats_eht
you are probably uploading the data every frame
[size="1"]
If you use a feature that your video card doesnt support, doesnt openGL switch into software mode?
post. code.

@BleedingBlue
For that feature, maybe, it depends how the drivers handle it.
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.
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 Objectsclass 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!
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).
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?
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

This topic is closed to new replies.

Advertisement