Sign in to follow this  

VBO error

This topic is 2048 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

[CODE]
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);
};
[/CODE]

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.

Share this post


Link to post
Share on other sites
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
[CODE]glDrawArrays(GL_TRIANGLES, 0, numVertices);[/CODE]

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! [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
Best regards

Share this post


Link to post
Share on other sites
That did it!

Thank you so much.

[quote name='Tsus' timestamp='1336132637' post='4937347']
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.
[/quote]

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
[quote name='mhagain' timestamp='1336134218' post='4937352']
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.
[/quote]

It is the second case. I'm working on the structs, but I'm not so good with them. Hopefully a little more practice...

Share this post


Link to post
Share on other sites
Ok. Would anyone mind to give me a hand with my structs.

I created the following structs:

[CODE]
struct float3

{

float x, y, z;

};

struct sVertex

{

float3 Position;

};

[/CODE]

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

[CODE]

sVertex Vertices[3] =

{

300.0f, 200.0f, -1.0f,

350.0f, 150.0f, -1.0f,

250.0f, 150.0f, -1.0f

};

[/CODE]

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

[CODE]
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);

};

[/CODE]

And the render function:

[CODE]

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);

};

[/CODE]

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. Edited by MrSimon

Share this post


Link to post
Share on other sites
Wow. I fixed it.

If I initialise the struct better:

[CODE]

sVertex Vertices[3] =

{

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

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

{250.0f, 150.0f, -1.0f}

};

[/CODE]

And change:

[CODE]

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


[/CODE]

to:

[CODE]

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

[/CODE]

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.

Share this post


Link to post
Share on other sites
So far so good.

I'm expanding my structs now, and adding colours the vertices. But, naturally ([img]http://public.gamedev.net//public/style_emoticons/default/tongue.png[/img] ), I'm having some difficulties.

This is the new struct form for sVertex:

[CODE]

struct sVertex

{

float3 Position, colours, normals;

float2 Texture;

};

[/CODE]

And here is the data:

[CODE]

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}

};

[/CODE]

The colorpointer is defined as:

[CODE]

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

[/CODE]

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!

Share this post


Link to post
Share on other sites
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.

[CODE]
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);

};
[/CODE]

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 :)

Share this post


Link to post
Share on other sites
Hi!

Besides, [url="http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElements.xml"]glDrawElements[/url] wants to know the format of the index buffer, so instead of GL_FLOAT you need either GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT.
Currently you use int in the sPolygons struct, so you should probably change that to unsigned int and then pick GL_UNSIGNED_INT in glDrawElements.

Hope that helps! :) Edited by Tsus

Share this post


Link to post
Share on other sites
And now it works.

Thank you guys.

I should be quiet for a couple of days while I try to work out loading textures! :)

Thanks again guys. You make a difficult process (for me anyway - it's only been a week, so far) a whole lot easier.

Share this post


Link to post
Share on other sites
OK. I have one more. After this, I promise, I'll leave you all alone.

VBO works, colours work, IBO works. Texture doesn't work?

Any ideas what's wrong?

[CODE]
struct float3

{

float x, y, z;

};

struct float2

{

float x, y;

};
struct sVertex
{

float3 Position, colours, normals;

float2 Texture;
};

struct sPolygons

{

int x, y, z;

//float Normal;

};
class cModel
{

private:

GLuint TextureID;

GLuint VBOID;

GLuint IBOID;

int nVertices, nPolygons;

unsigned char* TextureData;

public:

cModel(int nVertices, sVertex Vertices[], int nPolygons, sPolygons Polygons[], const char * TextureFile, int TextureWidth, int
TextureHeight);

void Update();

void Render();

};
cModel::cModel(int numVertices, sVertex Vertices[], int numPolygons, sPolygons Polygons[], const char * TextureFile, int TextureWidth, int
TextureHeight)
{
nVertices = numVertices;

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);

nPolygons = numPolygons;

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOID);

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

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

FILE * file = NULL;
file = fopen(TextureFile, "rb");
TextureData = new unsigned char [TextureWidth * TextureHeight * 3];

fread(TextureData, TextureWidth * TextureHeight * 3, 1, file);

fclose(file);

glGenTextures(1, &TextureID);

glBindTexture(GL_TEXTURE_2D, TextureID);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureWidth, TextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureData);

};
void cModel::Render()
{
glBindBuffer(GL_ARRAY_BUFFER, VBOID);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBOID);

glBindTexture(GL_TEXTURE_2D, TextureID);

glEnableClientState(GL_VERTEX_ARRAY);

glEnableClientState(GL_COLOR_ARRAY);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);

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

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

glTexCoordPointer(2, GL_FLOAT,11*sizeof(float), ((char*)NULL)+9*sizeof(float));

glDrawElements(GL_TRIANGLES, nPolygons*3, GL_UNSIGNED_INT, 0);

//glDrawArrays(GL_TRIANGLES, 0, nVertices);

glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
};
sVertex Vertices[3] =
{
{{0.0f, 5.0f, -1.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.5f, 1.0f}},

{{5.0f, -5.0f, -1.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {1.0f, 0.0f}},

{{-5.0f, -5.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}
};
sPolygons Array2[1] =
{
{0, 1, 2}
};
[/CODE]

I really promise, this will be the last thing for a while (a little while anyway). Edited by MrSimon

Share this post


Link to post
Share on other sites
You probably have to set filters for the texture.
[CODE]glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);[/CODE]

Oh, and texturing should be enabled of course. [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
[CODE]glEnable(GL_TEXTURE_2D);[/CODE]

Best regards

Share this post


Link to post
Share on other sites

This topic is 2048 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this