Related
I'm currently learning OpenGL in my free time and lately I have been facing an "error" I don't understand.
The thing is, I have no errors, only nothing appear on my screen. I'm using OpenGL with SFML.
Here is my code. Here is my method:
void CreateObjet(GLuint& vao, GLuint& vbo, GLuint& ebo, GLuint& textureLocation)
//I create my arrays here.. Don't worry they are fine.
CreateTexture(textureLocation);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glGenVertexArrays (1, &vao);
glBindVertexArray (vao); //On travaille dans le VAO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(0);
glBufferData (GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3* sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBufferData (GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
glVertexAttribPointer (2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6* sizeof(GLfloat)));
glEnableVertexAttribArray(2);
//EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indiceFinal), indiceFinal, GL_STATIC_DRAW);
glBindVertexArray(0);
I know my problem is not with my shaders because I receive no errors in my console with GlshaderRiv().
I would like to know if I'm doing the order properly.
I Create a VBO and a EBO
I Create a VAO
I bind the current VAO to modify it
I bind the current VBO inside the VAO
I bind my first array (Vertex Position vector3f) in my VBO and put them in the first pointer with the correct offset and stride.
I bind my second array (Color Position vector3f) in my VBO and put them in the first pointer with the correct offset and stride.
I bind my third array (Texture Position vector2f) in my VBO and put them in the first pointer with the correct offset and stride.
I bind a EBO within the VAO
I bind the EBO with my element position (Vector 3u).
I unbind the VAO from the memory because my drawing loop is quite later in the code and so, I don't want to use memory space for nothing. Don't worry, Before I draw I put glBindVertexArray(&vao);
That definitely does not look right. You're writing the values for all attributes to the same buffer, with each one overwriting the previous one:
glBufferData (GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), NULL);
glEnableVertexAttribArray(0);
glBufferData (GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
...
When you make the second glBufferData() call, it will overwrite the points data that you previously stored in the buffer with the colors data.
The misunderstanding is probably about what glVertexAttribPointer() does. It specifies which buffer the given attribute is sourced from, as well as the data layout (component count, type, etc). But it does not create a copy of the buffer data, or anything like that. The attribute data you want to use must still be stored in the buffer at the time of the draw call.
To fix this, you either have to use a different buffer for each attribute, or arrange the attribute data so that the values for all 3 attributes can be stored in the same buffer. The arguments of your glVertexAttribPointer() calls actually suggest that you were intending to store all attribute values interleaved in the same buffer. To get this working, you have to arrange the attribute values accordingly, and then store them in the buffer with a single glBufferData() call.
The memory arrangement you will need for this will have all the attribute values for the first vertex in sequence, followed by the values for the second vertex, etc. With pi the position of vertex i, ci the color, and ti the texture coordinates, the correct memory layout is:
p0x p0y p0z c0r c0g c0b t0s t0t
p1x p1y p1z c1r c1g c1b t1s t1t
p2x p2y p2z c2r c2g c2b t2s t2t
...
Ok after some timeout I am continuing my studies about OpenGL3.2+, now I am confused about how to optimize something like this:
// Verts
glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);
// Textures
glBindBuffer(GL_ARRAY_BUFFER, TexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texsize, tex, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(float) * TexCoords2D, 0);
//add light color info
glBindBuffer(GL_ARRAY_BUFFER, ColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colorsize, lightcolor, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(COLOR_ATTRIB);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(float) * ColorInfo, 0);
// Draw
glDrawArrays(GL_TRIANGLES, 0, size);
// Clean up
glDisableVertexAttribArray(VERTEX_COORD_ATTRIB);
glDisableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glDisableVertexAttribArray(COLOR_ATTRIB);
Lets assume this is done for a few meshes, currently each mesh is always pushed like this, bound, buffered and drawn. Needles to say that this is surely no effective approach.
Now when reading (many) tutorials, the one thing I always see is that it is suggested to use VAO to improve that, now my difficulty to understand is- each single tutorial seems to refer in that relation also to indexed drawing. While this method seems to be perfectly fine when using an example with something extremely simple like 2 quads, I am wondering now how one is supposed to create an index for a real complex mesh? Or is it just assumed that this is available (due to .obj file or something).
Also I am confused about if a VAO always needs an index or could it be used without? And if so, would it even make sense without, since I read that an optimization makes use of knowing the index?
You see there is a lot of confusion here yet and I realize this might be a silly question again :)
However, what I want to finally achieve is, instead of pushing each mesh like this, to buffer each mesh once in the memory of the graphics card and redraw it then from the buffer.
I don't know yet a VAO is even the right approach, but every tutorial I read seems to have VAO's as the next step.
First of all you should separate your GRAM writting with glBufferData() from your drawing calls with glDrawArrays(). This significantly drops your performance, because you are basicly copying your data from RAM to GRAM on every drawing call.
For this purpose you can use VAOs:
// setting up buffers
glBindVertexArray(VertexArrayIndex);
glBindBuffer(GL_ARRAY_BUFFER, VertBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, verts, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(VERTEX_COORD_ATTRIB);
glVertexAttribPointer(VERTEX_COORD_ATTRIB,3,GL_FLOAT, GL_FALSE, sizeof(float) * floatsPerVertex, 0);
// Textures
glBindBuffer(GL_ARRAY_BUFFER, TexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * texsize, tex, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(TEXTURE_COORD_ATTRIB);
glVertexAttribPointer(TEXTURE_COORD_ATTRIB, 2, GL_FLOAT, GL_FALSE, sizeof(float) * TexCoords2D, 0);
//add light color info
glBindBuffer(GL_ARRAY_BUFFER, ColorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colorsize, lightcolor, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(COLOR_ATTRIB);
glVertexAttribPointer(COLOR_ATTRIB, 4, GL_FLOAT, GL_FALSE, sizeof(float) * ColorInfo, 0);
glBindVertexArray(0);
// your drawing call
glBindVertexArray(VertexArrayIndex);
glDrawArrays(GL_TRIANGLES, 0, size);
glBindVertexArray(0);
If you want to draw really big meshes (their size is bigger than GRAM available on you graphic card) you should take interest in splitting your data into small chunks. Having all that data in one big array may cause some nasty memory allocation and rendering issues (believe me - I've been there ;)).
I suggest your next step should be to turn your vertex atrributes into a struct rather than separate arrays. That way, you're only using one array object, and GPUs much prefer this memory layout.
Beyond that:
Whether you go indexed or not depends heavily on your data; it's not a requirement for fast performance, but it can help; the other option is to use triangle strips, this also reduces the amount of vertex data. If you have multiple meshes in a single array object, you can simply change your vertex attrib pointers to start at a different location in the array object in order to draw a different mesh. Then you're not switching between array objects so much.
Most of these decisions should be driven by your constraints and by performance measurements!
I am studying the source code of an open source project and they have a use of the function glDrawElements which I don't understand. While being a programmer, I am quite new to the GL API so would appreciate if someone could tell me how this works.
Let's start with the drawing part. The code looks like this:
for (int i = 0; i < numObjs; i++) {
glDrawElements(GL_TRIANGLES, vboIndexSize(i), GL_UNSIGNED_INT, (void*)(UPTR)vboIndexOffset(i));
}
vboIndiexSize(i) returns the number of indices for the current object, and vboIndexOffset returns the offset in bytes, in a flat memory array in which vertex data AND the indices of the objects are stored.
The part I don't understand, is the (void*)(UPTR)vboIndexOffset(i)). I look at the code many times and the function vboIndexOffset returns a int32 and UPTR also cast the returned value to an int32. So how you can you cast a int32 to a void* and expect this to work? But let's assume I made a mistake there and that it actually returns a pointer to this variable instead. The 4th argument of the glDrawElements call is an offset in byte within a memory block. Here is how the data is actually stored on the GPU:
int ofs = m_vertices.getSize();
for (int i = 0; i < numObj; i++)
{
obj[i].ofsInVBO = ofs;
obj[i].sizeInVBO = obj[i].indices->getSize() * 3;
ofs += obj[i].indices->getNumBytes();
}
vbo.resizeDiscard(ofs);
memcpy(vbo.getMutablePtr(), vertices.getPtr(), vertices.getSize());
for (int i = 0; i < numObj; i++)
{
memcpy(
m_vbo.getMutablePtr(obj[i].ofsInVBO),
obj[i].indices->getPtr(),
obj[i].indices->getNumBytes());
}
So all they do is calculate the number of bytes needed to store the vertex data then add to this number the number of bytes needed to store the indices of all the objects we want to draw. Then they allocate memory of that size, and copy the data in this memory: first the vertex data and then the indices. One this is done they push it to the GPU using:
glGenBuffers(1, &glBuffer);
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
checkSize(size, sizeof(GLsizeiptr) * 8 - 1, "glBufferData");
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)size, data, GL_STATIC_DRAW);
What's interesting is that they store everything in the GL_ARRAY_BUFFER. They never store the vertex data in a GL_ARRAY_BUFFER and then the indices using a GL_ELEMENT_ARRAY_BUFFER.
But to go back to the code where the drawing is done, they first do the usual stuff to declare vertex attribute. For each attribute:
glBindBuffer(GL_ARRAY_BUFFER, glBuffer);
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, size, type, GL_FALSE, stride, pointer);
This makes sense and is just standard. And then the code I already mentioned:
for (int i = 0; i < numObjs; i++) {
glDrawElements(GL_TRIANGLES, vboIndexSize(i), GL_UNSIGNED_INT, (void*)(UPTR)vboIndexOffset(i));
}
So the question: even if (UPTR) actually returns the pointer to variable (the code doesn't indicate this but I may be mistaken, it's a large project), I didn't know it was possible to store all vertex and indices data with the same memory block using GL_ARRAY_BUFFER and then using glDrawElements and having the 4th argument being the offset to the first element of this index list for the current object from this memory block. I thought you needed to use GL_ARRAY_BUFFER and GL_ELEMENT_BUFFER to declare the vertex data and the indices separately. I didn't think you could declare all the data in one go using GL_ARRAY_BUFFER and can't get it to work on my side anyway.
Has anyone see this working before? I haven't got a chance to get it working as yet, and wonder if someone could just potentially tell me if there's something specific I need to be aware of to get it to work. I tested with a simple triangle with position, normal and texture coordinates data, thus I have 8 * 3 floats for the vertex data and I have an array of 3 integers for the indices, 0, 1, 2. I then copy everything in a memory block, initialize the glBufferData with this, then try to draw the triangle with:
int n = 96; // offset in bytes into the memory block, fist int in the index list
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(&n));
It doesn't crash but I can't see the triangle.
EDIT:
Adding the code that doesn't seem to work for me (crashes).
float vertices[] = {
0, 1, 0, // Vertex 1 (X, Y)
2, -1, 0, // Vertex 2 (X, Y)
-1, -1, 0, // Vertex 3 (X, Y)
3, 1, 0,
};
U8 *ptr = (U8*)malloc(4 * 3 * sizeof(float) + 6 * sizeof(unsigned int));
memcpy(ptr, vertices, 4 * 3 * sizeof(float));
unsigned int indices[6] = { 0, 1, 2, 0, 3, 1 };
memcpy(ptr + 4 * 3 * sizeof(float), indices, 6 * sizeof(unsigned int));
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 4 * 3 * sizeof(float) + 6 * sizeof(unsigned int), ptr, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
free(ptr);
Then when it comes to draw:
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// see stackoverflow.com/questions/8283714/what-is-the-result-of-null-int/
typedef void (*TFPTR_DrawElements)(GLenum, GLsizei, GLenum, uintptr_t);
TFPTR_DrawElements myGlDrawElements = (TFPTR_DrawElements)glDrawElements;
myGlDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, uintptr_t(4 * 3 * sizeof(float)));
This crashes the app.
see answer below for solution
This is due to OpenGL re-using fixed-function pipeline calls. When you bind a GL_ARRAY_BUFFER VBO, a subsequent call to glVertexAttribPointer expects an offset into the VBO (in bytes), which is then cast to a (void *). The GL_ARRAY_BUFFER binding remains in effect until another buffer is bound, just as the GL_ELEMENT_ARRAY_BUFFER binding remains in effect until another 'index' buffer is bound.
You can encapsulate the buffer binding and attribute pointer (offset) states using a Vertex Array Object.
The address in your example isn't valid. Cast offsets with: (void *) n
Thanks for the answers. I think though that (and after doing some research on the web),
first you should be using glGenVertexArray. It seems that this is THE standard now for OpenGL4.x so rather than calling glVertexAttribPointer before drawing the geometry, it seems like it's best practice to create a VAO when the data is pushed to the GPU buffers.
I (actually) was able to make combine the vertex data and the indices within the SAME buffer (a GL_ARRAY_BUFFER) and then draw the primitive using glDrawElements (see below). The standard way anyway is to push the vertex data to a GL_ARRAY_BUFFER and the indices to a GL_ELEMENT_ARRAY_BUFFER separately. So if that's the standard way of doing it, it's probably better not to try to be too smart and just use these functions.
Example:
glGenBuffers(1, &vbo);
// push the data using GL_ARRAY_BUFFER
glGenBuffers(1, &vio);
// push the indices using GL_ELEMENT_ARRAY_BUFFER
...
glGenVertexArrays(1, &vao);
// do calls to glVertexAttribPointer
...
Please correct me if I am wrong, but that seems the correct (and only) way to go.
EDIT:
However, it is actually possible to "pack" the vertex data and the indices together into an ARRAY_BUFFER as long as a call to glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo) is done prior to calling glDrawElements.
Working code (compared with code in original post):
float vertices[] = {
0, 1, 0, // Vertex 1 (X, Y)
2, -1, 0, // Vertex 2 (X, Y)
-1, -1, 0, // Vertex 3 (X, Y)
3, 1, 0,
};
U8 *ptr = (U8*)malloc(4 * 3 * sizeof(float) + 6 * sizeof(unsigned int));
memcpy(ptr, vertices, 4 * 3 * sizeof(float));
unsigned int indices[6] = { 0, 1, 2, 0, 3, 1 };
memcpy(ptr + 4 * 3 * sizeof(float), indices, 6 * sizeof(unsigned int));
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 4 * 3 * sizeof(float) + 6 * sizeof(unsigned int), ptr, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
free(ptr);
Then when it comes to draw:
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo); // << THIS IS ACTUALLY NOT NECESSARY
// VVVV THIS WILL MAKE IT WORK VVVV
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// see stackoverflow.com/questions/8283714/what-is-the-result-of-null-int/
typedef void (*TFPTR_DrawElements)(GLenum, GLsizei, GLenum, uintptr_t);
TFPTR_DrawElements myGlDrawElements = (TFPTR_DrawElements)glDrawElements;
myGlDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, uintptr_t(4 * 3 * sizeof(float)));
I've been trying to use Vertex Buffer Objects to save vertex data on the GPU and reduce the overhead, but I cannot get it to work. The code is below.
From what I understand you generate the buffer with glGenBuffers, then you bind the buffer with glBindBuffer so it's ready to be used, then you write data to it with glBufferData and its done and can be unbinded and ready for use later with simply binding it again.
However the last part is what I'm having trouble with, when I bind it after I have created and loaded data to it and try to draw using it, it gives me lots of GL Error: Out of Memory.
I doubt that I am running out of memory for my simple mesh, so I must be doing something very wrong.
Thanks.
EDIT 1: I call glGetError after every frame, but since this is the only OpenGL I do in the entire program it shouldn't be a problem
//when loading the mesh we create the VBO
void createBuffer()
{
GLuint buf;
glGenBuffers(1, &buf);
glBindBuffer(GL_ARRAY_BUFFER, buf);
glBufferData(GL_ARRAY_BUFFER, vertNormalBuffer->size() * sizeof(GLfloat), (GLvoid*) bufferData, GL_STATIC_DRAW);
//EDIT 1: forgot to show how I handle the buffer
model->vertexNormalBuffer = &buf;
//Unbinds it
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Fighter::doRedraw(GLuint shaderProgram)
{
glm::mat4 transformationMatrix = getTransform();
GLuint loc = glGetUniformLocation(shaderProgram,"modelviewMatrix");
glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*) &transformationMatrix);
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);
//If I uncomment this line below all works wonderfully, but isnt the purpose of VBO of not uploading the same data again and again?
//glBufferData(GL_ARRAY_BUFFER, model->vertAndNormalArraySize * sizeof(GLfloat), model->vertAndNormalArray, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
renderChild(model, model);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Fighter::renderChild(ModelObject* model, ModelObject* parent)
{
//Recursively render the mesh children
for(int i = 0; i < model->nChildren; i++)
{
renderChild( dynamic_cast<ModelObject*>(model->children[i]), parent);
}
//Vertex and normal data are interlieved
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat),(void*)(model- >vertexDataPosition*sizeof(GLfloat)));
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (void*)((model->vertexDataPosition + 4)*sizeof(GLfloat)));
//Draws using two sets of indices
glDrawElements(GL_QUADS, model->nQuads * 4, GL_UNSIGNED_INT,(void*) model->quadsIndices);
glDrawElements(GL_TRIANGLES, model->nTriangles * 3, GL_UNSIGNED_INT, (void*) model->trisIndices);
}
This is your problem:
model->vertexNormalBuffer = &buf;
/* ... */
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);
You're storing the address of your buf variable, rather than its contents, and then it falls out of scope when createBuffer returns, and is most likely overwritten with other data, so when you're later rendering, you're using an uninitialized buffer. Just store the contents of buf in your vertexNormalBuffer field instead.
I'll admit I don't know why OpenGL thinks it proper to say that it's "out of memory" just because of that, but perhaps you're just invoking undefined behavior. It does explain, however, why it starts working when you re-fill the buffer with data after you rebind it, because you then implicitly initialize the buffer that you just bound.
I am transferring over my vertex arrays functions to VBOs to increase the speed of my application.
Here was my original working vertex array rendering function:
void BSP::render()
{
glFrontFace(GL_CCW);
// Set up rendering states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].u);
// Draw
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, indices);
// End of rendering - disable states
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Worked great!
Now I am moving them into VBOs and my program actually caused my graphics card to stop responding. The setup on my vertices and indices are exactly the same.
New setup:
vboId is setup in the bsp.h like so: GLuint vboId[2];
I get no error when I just run the createVBO() function!
void BSP::createVBO()
{
// Generate buffers
glGenBuffers(2, vboId);
// Bind the first buffer (vertices)
glBindBuffer(GL_ARRAY_BUFFER, vboId[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Now save indices data in buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
}
And the rendering code for the VBOS. I am pretty sure it's in here. Just want to render whats in the VBO like I did in the vertex array.
Render:
void BSP::renderVBO()
{
glBindBuffer(GL_ARRAY_BUFFER, vboId[0]); // for vertex coordinates
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[1]); // for indices
// do same as vertex array except pointer
glEnableClientState(GL_VERTEX_ARRAY); // activate vertex coords array
glVertexPointer(3, GL_FLOAT, 0, 0); // last param is offset, not ptr
// draw the bsp area
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
glDisableClientState(GL_VERTEX_ARRAY); // deactivate vertex array
// bind with 0, so, switch back to normal pointer operation
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
Not sure what the error is but I am pretty sure I have my rendering function wrong. Wish there was a more unified tutorial on this as there are a bunch online but they are often contradicting eachother.
In addition what Miro said (the GL_UNSIGNED_BYTE should be GL_UNSIGNED_SHORT), I don't think you want to use numVertices but numIndices, like in your non-VBO call.
glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
Otherwise your code looks quite valid and if this doesn't fix your problem, maybe the error is somewhere else.
And by the way the BUFFER_OFFSET(i) thing is usuaully just a define for ((char*)0+(i)), so you can also just pass in the byte offset directly, especially when it's 0.
EDIT: Just spotted another one. If you use the exact data structures you use for the non-VBO version (which I assumed above), then you of course need to use sizeof(Vertex) as stride parameter in glVertexPointer.
If you are passing same data to glDrawElements when you aren't using VBO and same data to VBO buffer. Then parameters little differs, without FBO you've used GL_UNSIGNED_SHORT and with FBO you've used GL_UNSIGNED_BYTE. So i think VBO call should look like that:
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_SHORT, 0);
Also look at this tutorial, there are VBO buffers explained very well.
How do you declare vertices and indices?
The size parameter to glBufferData should be the size of the buffer in bytes and if you pass sizeof(vertices) it will return the total size of the declared array (not just what is allocated).
Try something like sizeof(Vertex)*numVertices and sizeof(indices[0])*numIndices instead.