I am drawing a lot of triangles quite fast using Vertex Array:
void initializeGL() {
...
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, colors);
}
void paintGL() {
...
glDrawElements(GL_TRIANGLES, 3*numTriangles, GL_UNSIGNED_INT, indices);
}
However I want my rendering to go even faster by using Vertex Buffer Objects (VBO).
Am I right in my understanding that the glVertexPointer() tells the GPU where in the CPU it can fetch the vertices data and then the GPU copy it from this location in the CPU for each paintGL()?
And that using VBO would improve on this by writing the vertices data to the GPU only once?
SInce I am using Qt I try to use the QGLBuffer class:
void GLWidget::initializeGL() {
...
vertexBuffer = new QGLBuffer(QGLBuffer::VertexBuffer);
vertexBuffer->create();
vertexBuffer->bind();
vertexBuffer->setUsagePattern(QGLBuffer::StaticDraw);
vertexBuffer->allocate(vertices, 3*numVertices*sizeof(float)); // copies vertices to GPU?
vertexBuffer->release();
#define BUFFER_OFFSET(bytes) ((GLubyte*) NULL + (bytes))
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
glColorPointer(3, GL_FLOAT, 0, colors);
}
When I run this it hangs for a long time before crashing :-(.
If I comment out the vertexBuffer->release(); line it displays nothing at all but do not crash.
What am I doing wrong here?
Also: how can I likewise send my colors to the GPU only once?
There is no QGLBuffer::ColorBuffer type!?
EDIT:
I included GLee.[h/c] in my project and replaced the QGLBuffer calls by:
unsigned int vbufferid;
glGenBuffers(1, &vbufferid);
glBindBuffer(GL_ARRAY_BUFFER, vbufferid);
int size = 3*numVertices*sizeof(float);
glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);
but the code still does not draw anything!?
The vbufferid is assigned the value 1 by the glGenBuffers call so I do not think that the problem is my graphics card.
EDIT 2:
I found that if I comment out the glEnableClientState(GL_COLOR_ARRAY); line the triangles are being displayed with VBO (but no color)!
So how do I transfer the color to the GPU when using VBO for vertices?
There is no GL_COLOR_BUFFER type !?
That’s about the general idea, though the actual execution (you don’t have to care about) is a bit tricker.
One common misconception you fell for: OpenGL is not “initialized”. You can upload certain resources to OpenGL in a initial phase, of course, but as a state machine OpenGL needs to be put into the required state right before you need it.
And then there’s your real problem: Your vertex positions are in a buffer object. Your colors however are not. But you’re giving OpenGL a pointer, which it misinterprets as a offset into the vertex buffer.
So I suggest you move the following lines right before the
glDrawElementscall:And take note, that the buffer is explicitly bound before doing the calls to glVertexPointer and unbound before the color pointer.
But, having some of the attributes in a VBO, and some not defeats the purpose. I hence suggest you move all your vertex attributes into VBOs, preferrably a single VBO, either one array after another (stride 0 and with offset between them) or interleaved (stride= the size of a whole attribute vector, with offset being the offset into the first attribute vector).
Update Code example:
Uploading to VBO
Drawing with combined VBO