Hello all,
I’m learning how to use VBOs but I have a problem. I have a model that is about 10k triangles and I can render it using vertex arrays or VBOs. With vertex arrays I get about 75fps but if I switch to VBOs I get about 0.003fps… so I must be doing something wrong.
My code looks like this
void InitializeVBOs()
{
int
totalVerticesSize = 0,
totalNormalsSize = 0,
totalTxCoordsSize = 0,
numTextures = 0,
numVertices = 0,
totalVBOSize = 0;
if(
( m_VBOsSupported ) &&
( m_pGeometry[ 0 ] != NULL ) &&
( m_pGeometry[ 0 ]->Get_NumVertices() > 0 )
)
{
numVertices = m_pGeometry[ 0 ]->Get_NumVertices();
numTextures = m_pGeometry[ 0 ]->GetNumTextures();
totalVerticesSize = ( sizeof(float) * 3 ) * numVertices; // for vertices
totalNormalsSize = ( sizeof(float) * 3 ) * numVertices; // for normals
totalTxCoordsSize =
( sizeof(float) * 3 ) * numVertices * numTextures; // for tx coords
totalVBOSize = totalVerticesSize + totalNormalsSize + totalTxCoordsSize;
glGenBuffersARB( 1, &m_GPUVertexBufferID );
glGenBuffersARB( 1, &m_GPUIndexBufferID );
// Bind the vertex data vbo.
glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_GPUVertexBufferID );
// Create a data store big enough for vertices, normals, and texture coords.
glBufferDataARB( GL_ARRAY_BUFFER_ARB, totalVBOSize, NULL, GL_STATIC_DRAW_ARB );
// Load vertices
glBufferSubDataARB(
GL_ARRAY_BUFFER_ARB,// target
0, // start from
totalVerticesSize, // total bytes of data
m_pGeometry[0]->m_vertices // data
);
// Load normals
glBufferSubDataARB(
GL_ARRAY_BUFFER_ARB,// target
totalVerticesSize, // start from
totalNormalsSize, // total bytes of data
m_pGeometry[0]->m_vertexNormals // data
);
// Load texture coordinates
glBufferSubDataARB(
GL_ARRAY_BUFFER_ARB,// target
totalVerticesSize + totalNormalsSize, // start from
totalTxCoordsSize, // total bytes of data
m_pGeometry[0]->m_txCoords // data
);
// Load the indices
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_GPUIndexBufferID );
glBufferDataARB(
GL_ELEMENT_ARRAY_BUFFER, // target
m_numIndices * sizeof(unsigned short), // total size
m_pGeometry[0]->m_indices, // data
GL_STATIC_DRAW_ARB
);
}
}
// ---
void Render()
{
int
totalVerticesSize = 0,
totalNormalsSize = 0,
numvertices = 0,
numtextures = 0;
//...
//...
if( m_pGeometry[0] != NULL )
{
numvertices = m_pGeometry[0]->Get_NumVertices();
numtextures = m_pGeometry[0]->GetNumTextures();
totalVerticesSize = ( sizeof(float) * 3 ) * numvertices;
totalNormalsSize = ( sizeof(float) * 3 ) * numvertices;
// If VBOs are supported and we have valid buffers
if(
m_VBOsSupported &&
( m_GPUVertexBufferID > 0 ) &&
( m_GPUIndexBufferID > 0 )
)
{
// Bind the data buffer
glBindBufferARB( GL_ARRAY_BUFFER_ARB, m_GPUVertexBufferID );
// Bind the element buffer
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, m_GPUIndexBufferID );
// Setup pointers
glVertexPointer(
3, // coords
GL_FLOAT, // floats
0, // stride is 0, vertices are contiguous
0 // offset is 0, vertices are at the start of the buffer
);
glNormalPointer(
GL_FLOAT, // floats
0, // stride is 0, normals are contiguous
BUFFER_OFFSET( totalVerticesSize ) // offset is (total size of vertices)
);
/*
glTexCoordPointer(
2, // 2 coordinates
GL_FLOAT, // floats
sizeof(float), // stride is one float
BUFFER_OFFSET( totalVerticesSize + totalNormalsSize ) // offset into the buffer
);
*/
}
else
{
// SET VERTEX AND NORMAL POINTER
glVertexPointer(3, GL_FLOAT, 0, m_pGeometry[0]->m_vertices);
glNormalPointer(GL_FLOAT, 0, m_pGeometry[0]->m_vertexNormals);
/*glTexCoordPointer( 3, GL_FLOAT, sizeof(float), m_pGeometry[0]->m_txCoords ); */
}
groupIndices = m_pGeometry[0]->Get_NumIndices();
if( m_VBOsSupported )
{
start_time = timeGetTime() / 1000.0f;
glDrawElements(
GL_TRIANGLES,
groupIndices,
GL_UNSIGNED_SHORT,
0
);
end_time = timeGetTime() / 1000.0f;
sprintf(tmpStr, "VBO CALL = %f", end_time - start_time);
MessageBox(NULL, tmpStr, "VBO CALL", MB_OK );
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
}
else
{
start_time = timeGetTime() / 1000.0f;
glDrawElements(
GL_TRIANGLES,
groupIndices,
GL_UNSIGNED_SHORT,
m_pGeometry[0]->m_indices
);
end_time = timeGetTime() / 1000.0f;
sprintf(tmpStr, "VA CALL = %f", end_time - start_time);
MessageBox(NULL, tmpStr, "VA CALL", MB_OK );
}
}
}
With the message box calls I could see the problem seems to be with glDrawElements. For VBOs, the call takes about 1.3 seconds.
Any ideas what could be wrong ??
Also, I downloaded a demo from Delphi3D that renders a terrain using VBOs. The demo renders about 2 million triangles and I get about 9fps. The only difference is that the demo uses an interleaved array for vertices/colors.
Is there anything wrong with the way I setup the data in the VBOs?
Thanks for any help!