Poor VBO Performance?
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
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.
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.
@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.
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...
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).
Upload data into the VRAM, set the pointer before the object ist drawn and draw the object:
Thank you!
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:
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?
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
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
Popular Topics
Advertisement