VBO error

Started by
13 comments, last by MrSimon 11 years, 11 months ago
Can someone please tell me why this piece of code is not working? I've been messing around with it for days.

If I enter the vertex data in immediate mode (glBegin/glEnd) it renders with no problems.

So what am I dong wrong?


float Vertices[9] =
{
300.0f, 200.0f, -1.0f,

350.0f, 150.0f, -1.0f,

250.0f, 150.0f, -1.0f
};
void DrawTriangle(int numVertices, float Vertices[])
{
GLuint VBOID;

glGenBuffers(1, &VBOID);

glBindBuffer(GL_ARRAY_BUFFER, VBOID);

glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(float), &Vertices[0], GL_STATIC_DRAW);

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, 0);

glDrawElements(GL_TRIANGLES, 9, GL_FLOAT, &Vertices[0]);

glDisableClientState(GL_VERTEX_ARRAY);

glDeleteBuffers(1, &VBOID);
};


This is ultimately going to go back into the class it's failing to work in. It took me a day to wok out that the this bit of code is what is wrong with it. It was a long day.

Thanks.
Advertisement
Hi!

The draw call glDrawElements is used, when you additionaly use an index buffer (GL_ELEMENT_ARRAY_BUFFER). In your case, you’d rather use
glDrawArrays(GL_TRIANGLES, 0, numVertices);

You probably did it to shorten the code you show us, but in practice it’s better to create resources once at startup (glGenBuffers), not every draw call.

Hope it helps! smile.png
Best regards
That did it!

Thank you so much.


You probably did it to shorten the code you show us, but in practice it’s better to create resources once at startup (glGenBuffers), not every draw call.


I do normally. It was all nicely arranged in a good long class, which I then had to butcher whilst trying to find what was wrong!

Thank you again.
One other problem.

numVertices is probably 3 coming in here, as you have 3 verts (each of which is 3 floats), so you're not allocating enough buffer storage for them. The data parameter to glBufferData is a total size in bytes, so you need numVertices * 3 * sizeof (float) instead. It's probably better to use a struct for your vertex type rather than a raw array of floats as it can help catch this kind of thing.

If numVertices is actually 9 then this is the wrong value to use for glDrawArrays - you need to be using 3 instead. Again, using a struct will make this clearer and easier.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.


One other problem.

numVertices is probably 3 coming in here, as you have 3 verts (each of which is 3 floats), so you're not allocating enough buffer storage for them. The data parameter to glBufferData is a total size in bytes, so you need numVertices * 3 * sizeof (float) instead. It's probably better to use a struct for your vertex type rather than a raw array of floats as it can help catch this kind of thing.

If numVertices is actually 9 then this is the wrong value to use for glDrawArrays - you need to be using 3 instead. Again, using a struct will make this clearer and easier.


It is the second case. I'm working on the structs, but I'm not so good with them. Hopefully a little more practice...
Ok. Would anyone mind to give me a hand with my structs.

I created the following structs:


struct float3

{

float x, y, z;

};

struct sVertex

{

float3 Position;

};



I made the struct 'Vertices' and filled it in:



sVertex Vertices[3] =

{

300.0f, 200.0f, -1.0f,

350.0f, 150.0f, -1.0f,

250.0f, 150.0f, -1.0f

};



In my class cModels, I have the constructor as follows:


cModel::cModel(int numVertices, sVertex Vertices[], int numPolygons, sPolygons Polygons[])

{

nVertices = numVertices;

glGenBuffers(1, &VBOID);

glBindBuffer(GL_ARRAY_BUFFER, VBOID);

glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(sVertex), &Vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);

};



And the render function:



void cModel::Render()

{

glBindBuffer(GL_ARRAY_BUFFER, VBOID);

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(3, GL_FLOAT, 0, 0);

glDrawArrays(GL_TRIANGLES, 0, nVertices);

glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);

};



And nothing happens.

If I remove the structs and enter the information as I did in the opening post, it works and I get a little grey triangle. I am assuming the problem is with the structs, or with my trying to get the information from the struct into the buffer.

Would I have to take the vertex information out of the struct, and put it into an array within the class before putting it into the buffer? That seems a bit excessive, but I guess the glVertexArray may be having a problem with being given an array of structs, each of which contains another struct.

Any ideas? All help is appreciated.

Edit: OK. For a start, I think I'm initialising the array of structs wrong. I'll have a look and see what that does later.
Wow. I fixed it.

If I initialise the struct better:



sVertex Vertices[3] =

{

{300.0f, 200.0f, -1.0f},

{350.0f, 150.0f, -1.0f},

{250.0f, 150.0f, -1.0f}

};



And change:



glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(sVertex), &Vertices, GL_STATIC_DRAW);




to:



glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(sVertex), Vertices, GL_STATIC_DRAW);



It works! Yay.

But I'm sure there are about a million other things wrong. I', open to any and all advice regarding the better way of doing what I'm doing.

Thanks everyone.
So far so good.

I'm expanding my structs now, and adding colours the vertices. But, naturally (tongue.png ), I'm having some difficulties.

This is the new struct form for sVertex:



struct sVertex

{

float3 Position, colours, normals;

float2 Texture;

};



And here is the data:



sVertex Vertices[3] =

{

{300.0f, 200.0f, -1.0f, 0.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},

{350.0f, 150.0f, -1.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},

{250.0f, 150.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}

};



The colorpointer is defined as:



glColorPointer(3, GL_FLOAT, 11*sizeof(float), (char*)NULL+3*sizeof(float));



What should(?) happen is that each vertices should be a different colour.

What is happening, is that the whole triangle renders black. If I shift the stride and offset values I can get one corner blue or one corner yellow, or one corner red, or one corner green.

Any ideas? I thought I was doing well!
Ok. I got this one too.

Turns out I am an idiot, and got the colour values wrong. The values written as 0.1f should have been 1.0f.

I do, however, have yet another difficulty. My IBO is not working.


struct float3

{

float x, y, z;

};

struct sVertex

{

float3 Position, colours, normals;

float2 Texture;

};

struct sPolygons

{

int x, y, z;

//float Normal;

};

sVertex Vertices[3] =

{

{{300.0f, 200.0f, -1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},

{{350.0f, 150.0f, -1.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},

{{250.0f, 150.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}

};

sPolygons Array2 =

{

2, 1, 0

};

cModel::cModel(int numVertices, sVertex Vertices[], int numPolygons, sPolygons Polygons[])

{

nVertices = numVertices;

nPolygons = numPolygons;

glGenBuffers(1, &VBOID);

glGenBuffers(1, &IBOID);

glBindBuffer(GL_ARRAY_BUFFER, VBOID);

glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(sVertex), Vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOID);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, numPolygons*sizeof(sPolygons), Polygons, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

};

void cModel::Render()

{

glBindBuffer(GL_ARRAY_BUFFER, VBOID);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOID);

glEnableClientState(GL_VERTEX_ARRAY);

glEnableClientState(GL_COLOR_ARRAY);

glVertexPointer(3, GL_FLOAT, 11*sizeof(float), (char*)NULL+0);

glColorPointer(3, GL_FLOAT, 11*sizeof(float), (char*)NULL+3*sizeof(float));

glDrawElements(GL_TRIANGLES, nPolygons, GL_FLOAT, 0);

//glDrawArrays(GL_TRIANGLES, 0, nVertices);

glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

};


If I comment out the DrawElements line and uncomment the DrawArrays line, it works perfectly. Otherwise I get nothing.

Anyone have any ideas? I promise I'll stop asking questions for a while if I get help with this :)
The count parameter to glDrawElements is the number of indices to draw. You want to draw three indices from the index array.

This topic is closed to new replies.

Advertisement