I tried to draw a textured square using OpenGL and indexes. At first, I draw a simple white square using VAOs and VBOs. After that, I tried to create an index buffer object to draw the same simple white square but it doesn't draw anything and it throws error core GL_INVALID_ENUM (0x500). This error code is thrown after calling glDrawElements.
Here there are some parts of my code:
Function that creates Index Buffer Object, VAO, and VBO:
void Object::loadObject(const float *lpfVertices, size_t uVerticesSize, const char *lpbElementsList, size_t uNumElements) {
this->uNumElements = uNumElements;
glGenVertexArrays(1, &uVertexArrayID);
glBindVertexArray(uVertexArrayID);
glGenBuffers(1, &uVertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, uVertexBufferID);
glBufferData(GL_ARRAY_BUFFER, uVerticesSize, (void *)lpfVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, NULL);
glEnableVertexAttribArray(0);
glGenBuffers(1, &uElemetsListID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, uElemetsListID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, uNumElements, lpbElementsList, GL_STATIC_DRAW);
}
Function that render my object:
void Object::renderObject() {
glBindVertexArray(uVertexArrayID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, uElemetsListID);
glDrawElements(GL_TRIANGLES, uNumElements, GL_BYTE, NULL);
}
Part of the main code:
object.loadObject(lpfTriangleVertices, sizeof(lpfTriangleVertices), lpbElementsList, sizeof(lpbElementsList));
uProgID = loadShader("default.vs", "default.fs");
while(!glfwWindowShouldClose(lpstWndID)) {
glfwPollEvents();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(uProgID);
object.renderObject();
glfwSwapBuffers(lpstWndID);
}
glDrawElements(GL_TRIANGLES, uNumElements, GL_BYTE, NULL);
^^^^^^^
GL_BYTE is not a valid argument for type in glDrawElements():
type
Specifies the type of the values in indices. Must be one of GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT.
Related
I'm trying to load and render a 3D model i exported from blender to 3ds format.
I'm using Assimp to load the model and OpenGL (GLEW) to render it. for some reason some. in some of the models only parts of the model gets rendered.
for some this can be fixed by selecting all objects in blender and clicking join. But for others this does not solve the problem.
Here is the code Im using to load the models in:
(all of the "Array"s here are std::vector)
void Mesh::recursiveProcess(aiNode* node,const aiScene* scene) {
for(int i=0;i<node->mNumMeshes;i++) {
aiMesh* mesh=scene->mMeshes[node->mMeshes[i]];
processMesh(mesh, scene);
}
for(int i=0;i<node->mNumChildren;i++) {
recursiveProcess(node->mChildren[i], scene);
}
}
void Mesh::processMesh(aiMesh* m,const aiScene* scene) {
for(int i=0;i<m->mNumVertices;i++) {
vertexArray.push_back(m->mVertices[i].x);
vertexArray.push_back(m->mVertices[i].y);
vertexArray.push_back(m->mVertices[i].z);
if(m->mNormals!=NULL) {
normalArray.push_back(m->mNormals[i].x);
normalArray.push_back(m->mNormals[i].y);
normalArray.push_back(m->mNormals[i].z);
}
if(m->mTextureCoords[0]!=NULL) {
uvArray.push_back(m->mTextureCoords[0][i].x);
uvArray.push_back(m->mTextureCoords[0][i].y);
}
if(m->mTangents!=NULL) {
tangentArray.push_back(m->mTangents[i].x);
tangentArray.push_back(m->mTangents[i].y);
tangentArray.push_back(m->mTangents[i].z);
}
}
for(int i=0;i<m->mNumFaces;i++) {
aiFace face=m->mFaces[i];
for(int j=0;j<face.mNumIndices;j++) {
indexArray.push_back(face.mIndices[j]);
}
}
}
void Mesh::Load(string path) {
vertexArray.clear();
indexArray.clear();
normalArray.clear();
uvArray.clear();
tangentArray.clear();
const aiScene* scene=aiImportFile(path.c_str(),
aiProcess_GenSmoothNormals |
aiProcess_CalcTangentSpace |
aiProcess_Triangulate |
aiProcess_FindInvalidData);
const char* err = aiGetErrorString();
if(err!=NULL&&sizeof(err) > 4 && scene==NULL) {
cout << "The file wasn't successfuly opened " << path << " Because " << err;
return;
}
recursiveProcess(scene->mRootNode,scene);
if(uvArray.size()==0) uvArray.push_back(0);
if(normalArray.size()==0) normalArray.push_back(0);
if(tangentArray.size()==0) tangentArray.push_back(0);
}
and here is how I'm rendering them;
first i create the buffers. i do this once
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertexArray.size() * sizeof(float), vertexArray.data(), GL_STATIC_DRAW);
glGenBuffers(1, &indexbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexArray.size() * sizeof(unsigned int), indexArray.data(), GL_STATIC_DRAW);
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, uvArray.size() * sizeof(float), uvArray.data(), GL_STATIC_DRAW);
then I execute this in the main render loop
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void*)0);
camera.Update();
mvp = camera.getProjection() * camera.getView() * Model;
shader.SetUniformLocationMatrix4fv("MVP", &mvp[0][0]);
glBindTexture(GL_TEXTURE_2D, akm_tex);
glUseProgram(shader);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer);
glDrawElements(
GL_TRIANGLES, // mode
indexArray.size(), // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
here is how a model looks like in my program:
and here is how it look in blender
You missed to apply the transformations of the nodes to the vertex buffers you are rendering. Each assimp-node stores a local transformation which need to get applied to all its assigned meshes.
You can introduce in your shader a uniform-variable to represent the global transformation for the vertices. During rendering you need to multiply the local transformation with the global transformation and apply it via this uniform matrix.
Or you can just use glPushMAtrix and glPopMatrix and apply the local transformation of your current node as you can see here (recursive_render)
I have a sprite class to handle initializing a sprite and drawing it but i keep getting this error Exception thrown at 0x68ECC760 (nvoglv32.dll) this seems to be mainly because of _vboID and _vertNum I'm not exactly sure what is wrong with them though, here's the source code for it
void Sprite::init(int vertNum, float r, Shape shape) {
_vertNum = vertNum;
if (_vboID = 0) {
glGenBuffers(1, &_vboID);
}
std::vector<Vertex> vertexData(vertNum);
if (shape == Shape::CIRCLE) {
for (int i = 0; i < vertNum; i++) {
vertexData[i].setPosition(r*cos(i), r*sin(i));
}
}
for (int i = 0; i < _vertNum; i++) {
vertexData[i].setColor(1, 1, 1, 1);
}
glBindBuffer(GL_VERTEX_ARRAY, _vboID);
glBufferData(GL_VERTEX_ARRAY, sizeof(vertexData), vertexData.data(), GL_DYNAMIC_DRAW);
glBindBuffer(GL_VERTEX_ARRAY, 0);
}
void Sprite::draw() {
//bind buffer array
glBindBuffer(GL_VERTEX_ARRAY, _vboID);
//use first vertex attrib array
glEnableVertexAttribArray(0);
//pointer to vertices location
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
//pointer to vertices color
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, color));
//Draw the 6 vertices to the screen
glDrawArrays(GL_POLYGON, 0, _vertNum);
//Disable the vertex attrib array. This is not optional.
glDisableVertexAttribArray(0);
//Unbind the VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
GL_VERTEX_ARRAY is not a valid buffer binding target. What you are looking for is GL_ARRAY_BUFFER.
When you use GL_VERTEX_ARRAY in contexts where a buffer binding target is expected, you should only get a GL_INVALID_ENUM error, and the calls will have no further effect. As a result, you have no GL_ARRAY_BUFFER bound during your glVertexAttribPointer call, which in a legacy or core profile will result the GL in interpreting your pointers as pointers to client memory.
You should really add some error checks, or use a debug callback, so that such simple mistakes can be spotted early.
I am trying to draw part of my tile image but I am getting GL_INVALID_VALUE error when I call glDrawElements function. There is no problem when I change this function with glDrawArrays. The problem is that the indices count parameter is not negative number.
There is a code:
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
#define VERTEX_ATTR_PTR(loc, count, member, type) \
glEnableVertexAttribArray(loc); \
glVertexAttribPointer(loc, count, GL_FLOAT, GL_FALSE, sizeof(type), BUFFER_OFFSET(offsetof(struct type, member)))
// ---------- TextRenderer
void TextRenderer::setText(const string& text) {
vector<Vertex2f> vertex_buffer;
vector<GLuint> index_buffer;
GLfloat cursor = 0.f;
FPoint2D cell_size = font->getCellSize();
for (char c : text) {
TILE_ITER iter = font->getCharacter(c);
{
// UV
for (GLuint i = 0; i < 4; ++i) {
TILE_ITER _v = iter + i;
vertex_buffer.push_back( {
{
_v->pos[0] + cursor,
_v->pos[1],
_v->pos[2]
},
{ _v->uv[0], _v->uv[1] }
});
}
// Index
for (GLuint i = 0; i < 6; ++i)
index_buffer.push_back(
Tile::indices[i] + vertex_buffer.size() - 4);
}
cursor += cell_size.X;
}
vertices_count = vertex_buffer.size();
indices_count = index_buffer.size();
glBindVertexArray(vao);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
0,
indices_count * sizeof(GLuint),
&index_buffer[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferSubData(GL_ARRAY_BUFFER,
0,
vertices_count * sizeof(Vertex2f),
&vertex_buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glBindVertexArray(0);
}
void TextRenderer::create() {
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
{
indices = genGLBuffer( {
nullptr,
BUFFER_SIZE / 2 * sizeof(GLuint),
GL_ELEMENT_ARRAY_BUFFER
}, true, GL_DYNAMIC_DRAW);
vbo = genGLBuffer( {
nullptr,
BUFFER_SIZE * sizeof(Vertex2f),
GL_ARRAY_BUFFER
}, true, GL_DYNAMIC_DRAW);
VERTEX_ATTR_PTR(0, 3, pos, Vertex2f); // Vertex
VERTEX_ATTR_PTR(1, 2, uv, Vertex2f); // UV
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
setText("DUPA");
}
void TextRenderer::draw(MatrixStack& matrix, GLint) {
static Shader shader(
getFileContents("shaders/text_frag.glsl"),
getFileContents("shaders/text_vert.glsl"),
"");
shader.begin();
shader.setUniform(GL_TEXTURE_2D, "texture", 0,
font->getHandle());
shader.setUniform("matrix.mvp", matrix.vp_matrix * matrix.model);
shader.setUniform("col", col);
{
glBindVertexArray(vao);
//glDrawArrays(GL_LINE_STRIP, 0, vertices_count);
glDrawElements(GL_LINES, indices_count, GL_UNSIGNED_INT,
nullptr);
glBindVertexArray(0);
showGLErrors();
}
shader.end();
}
The problem is with the following (shortened) call sequence in your setText() method:
glBindVertexArray(vao);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
...
}
glBindVertexArray(0);
The binding of the GL_ELEMENT_ARRAY_BUFFER is part of the VAO state. So by making this call while the VAO is bound:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
you're setting the VAO state to have an element array buffer binding of 0. So when you later bind the VAO in your draw() method, you won't have a binding for GL_ELEMENT_ARRAY_BUFFER.
To avoid this, the simplest solution is to just remove that call. If you want to explicitly unbind it because you're worried that having it bound might have undesired side effects on other code, you need to move it after unbinding the VAO:
glBindVertexArray(vao);
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);
...
}
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Without seeing the whole code and knowing exact GL version, I will attempt to give you a correct answer.
First, if you're using ES2 then using index type as GL_UNSIGNED_INT is not supported by default, however I don't think that's your problem.
Your actual issue is that element arrays are actually not stored in your VAO object, only vertex data configuration. Therefore glDrawElements will give you this error as it will think no element array is bound and you passed NULL as indices argument to the function.
To solve this, bind the appropriate element array before you call glDrawElements
I'm trying to load a model into my project and I get an exception at glDrawElements.
I read the model file (.nfg), and retain the vertices and indices into vectors, and I use Vertex Buffer Object to bind my model.
I tried this:
I modified the fourth parameter from (GLvoid*)(sizeof(Vector3) * x)
to (GLvoid*)(offset(Vertex, attribute)), but didn't do anything (in the link, the problem was that he was sending memory address in the 4th parameter, and I thought maybe I was sending the wrong parameter to the wrong attribute, which still, would be a problem when actually showing the model).
I'm using OpenGL ES 2.0 and I'm not doing this project for neither Android or iOS; currently working in Visual Studio 2013 on Windows 8.1
The model loader:
void loadModelNfg(const std::string &filename,
GLuint &vbo, GLuint &ibo, GLuint &num, Shaders shaders){
// put here the verteces and indices from the file
std::vector<Vertex> vertices;
std::vector<GLushort> indices;
_loadModelNfg(filename, vertices, indices);
std::cout << "Mesh Loader: loaded file: " << filename << "\n";
// creates OpenGL objects necessary for drawing
GLuint gl_vertex_buffer_object, gl_index_buffer_object;
// vertex buffer object -> object in which to keep the vertices
glGenBuffers(1, &gl_vertex_buffer_object);
glBindBuffer(GL_ARRAY_BUFFER, gl_vertex_buffer_object);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex),
&vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// index buffer object -> object in which to keep the indices
glGenBuffers(1, &gl_index_buffer_object);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl_index_buffer_object);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort),
&indices[0], GL_STATIC_DRAW);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
vbo = gl_vertex_buffer_object;
ibo = gl_index_buffer_object;
num = indices.size();
}
Calling the previous function:
// for now, global variables:
GLuint vbo, ibo, num;
Shader myShaders;
int Init ( ESContext* esContext ) {
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
// this one works: tried with a triangle
int ret = myShaders.Init("../Resources/Shaders/TriangleShaderVS.vs",
"../Resources/Shaders/TriangleShaderFS.fs");
if (ret == 0)
loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);
return ret;
}
Drawing the model:
void Draw(ESContext* esContext) {
Matrix world;
world.SetIdentity();
Matrix view = c.getView();
Matrix persp = c.getPerspective();
Matrix trans = world * view *persp;
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(myShaders.program);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
if (myShaders.positionAttribute != -1) {
glEnableVertexAttribArray(myShaders.positionAttribute);
glVertexAttribPointer(myShaders.positionAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, pos)));
}
if (myShaders.normalAttribute != -1) {
glEnableVertexAttribArray(myShaders.normalAttribute);
glVertexAttribPointer(myShaders.normalAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, norm)));
}
if (myShaders.binormalAttribute != -1) {
glEnableVertexAttribArray(myShaders.binormalAttribute);
glVertexAttribPointer(myShaders.binormalAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, binorm)));
}
if (myShaders.tangentAttribute != -1) {
glEnableVertexAttribArray(myShaders.tangentAttribute);
glVertexAttribPointer(myShaders.tangentAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, tgt)));
}
if (myShaders.texcoordAttribute != -1) {
glEnableVertexAttribArray(myShaders.texcoordAttribute);
glVertexAttribPointer(myShaders.texcoordAttribute, 2, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, uv)));
}
if (myShaders.colorAttribute != -1) {
glEnableVertexAttribArray(myShaders.colorAttribute);
glVertexAttribPointer(myShaders.colorAttribute, 3, GL_FLOAT,
GL_FALSE, sizeof(Vertex), (GLvoid*)(offsetof(Vertex, col)));
}
if (myShaders.MVPuniform != -1) {
glUniformMatrix4fv(myShaders.MVPuniform, 1, GL_FALSE, (GLfloat*) trans.m);
}
// HERE GETS EXCEPTION
glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*) 0);
eglSwapBuffers (esContext->eglDisplay, esContext->eglSurface);
}
I am not sure that I am correctly binding the buffers in the loadModelNfg() function.
From what can this problem come and how can it be resolved?
EDIT:
GL_VENDOR: Imagination Technologies (Host GL: 'Intel');
GL_RENDERER: PowerVR PVRVFrame 4.2SGX 530 (Host 'Intel(R) HD Graphics 400');
GL_VERSION: OpenGL ES 2.0 (SDK build: 2.04.24.0809)
EDIT:
I surrounded the function with try-catch statement, but it still breaks when calling it:
try {
glDrawElements(GL_TRIANGLES, num, GL_UNSIGNED_SHORT, (GLvoid*)0);
}
catch (const std::exception& e) {
std::cout << e.what() << "\n";
}
I forgot to mention that the project/solution builds successful (after cleaning, or by rebuild).
After learning that OpenGL doesn't throw exceptions, I started looking how it handles errors. I found out that it "returns" error codes (or 0 if success), which can be found with glGetError().
Going withglGetError() through the code, I found out that the error was caused by glUseProgram(myShaders.program);.
Knowing that, I went through the functions which used myShaders variable, and I found that, after calling loadModelNfg("../../ResourcesPacket/Models/Bila.nfg", vbo, ibo, num, myShaders);, the variable got change.
Remembering that I don't use it anymore, I just removed it, and everything was fine.
What is strange is that I didn't modified the myShaders variable anywhere in that function (the code in the question is the final one). The problem, I think, is that I didn't declared the parameter const Shaders shaders.
So, the conclusion:
use glGetError() and breakpoints in code to find the real problem. It may not be the where it breaks!
PS: I hope it's ok that I put this as an answer. If it's not, I'll update the question.
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.