Matthew Mitchell
Matthew Mitchell

Reputation: 5393

OpenGL Vertex Buffer Object code giving bad output

My Vertex Buffer Object code is supposed to render textures nicely but instead the textures are being rendered oddly with some triangle shapes.

What happens - http://godofgod.co.uk/my_files/wrong.png

What is supposed to happen - http://godofgod.co.uk/my_files/right.png

This function creates the VBO and sets the vertex and texture coordinate data:

extern "C" GLuint create_box_vbo(GLdouble size[2]){
    GLuint vbo;
    glGenBuffers(1,&vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    GLsizeiptr data_size = 8*sizeof(GLdouble);
    GLdouble vertices[] = {0,0,  0,size[1],  size[0],0,  size[0],size[1]};
    glBufferData(GL_ARRAY_BUFFER, data_size, vertices, GL_STATIC_DRAW);
    data_size = 8*sizeof(GLint);
    GLint textcoords[] = {0,0,  0,1,  1,0, 1,1};
    glBufferData(GL_ARRAY_BUFFER, data_size, textcoords, GL_STATIC_DRAW);
    return vbo;
}

Here is some relavant code from another function which is supposed to draw the textures with the VBO.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor4d(1,1,1,a/255);
glBindTexture(GL_TEXTURE_2D, texture);
glTranslated(offset[0],offset[1],0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_DOUBLE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer (2, GL_INT, 0, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 1, 3);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);

I would have hoped for the code to use the first three coordinates (top-left,bottom-left,top-right) and the last three (bottom-left,top-right,bottom-right) to draw the triangles with the texture data correctly in the most efficient way. I don't see why triangles should make it more efficient but apparently that's the way to go. It, of-course, fails for some reason.

I am asking what is broken but also am I going about it in the right way generally?

Thank you.

Upvotes: 1

Views: 1037

Answers (2)

Ivan Baldin
Ivan Baldin

Reputation: 3469

If you want to use the one VBO for both vertex and texture coordinates you need to group them using a struct.

Define your data:

typedef struct {
    GLdouble x, y;
    GLint    s, t;
} VertexData;

VertexData data[] = {
//  x        y        s  t
    {0.0,     0.0,     0, 0},
    {0.0,     size[1], 0, 1},
    {size[0], 0.0,     1, 0},
    {size[0], size[1], 1, 1}
};

Copy it into VBO:

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), (GLvoid*)data, GL_STATIC_DRAW);

Set pointers. Note that stride is your struct's size and pointer itself serves as offset:

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_DOUBLE, sizeof(VertexData), (GLvoid*)offsetof(VertexData, x));
glTexCoordPointer(2, GL_INT, sizeof(VertexData), (GLvoid*)offsetof(VertexData, s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

And draw.

EDIT: Implemented offset with offsetof() as Bahbar suggested.

Upvotes: 1

Bahbar
Bahbar

Reputation: 18015

You're loading data twice to the vbo. The second call to glBufferData is replacing the first one. Then both calls to gl*Pointer actually use the same data when calling draw.

Upvotes: 0

Related Questions