Jump to content
  • Advertisement
Sign in to follow this  
MarkS

I'm having trouble drawing multiple VBOs.

This topic is 2439 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

I'm making a little Checkers game for my nieces and nephews. This is the first time I have truly messed with VBOs and shaders. The problem I am having is that the object drawn depends entirely on load order. If I load the board object and follow it with the piece object, any and all draw calls draw the piece object. Reverse the load calls and all draws calls draw the board.

The load functions are pretty much the same.

The board loading function:

[source]

void board::LoadBoard(void)
{
FILE *fs;

if(fopen_s(&fs,"data/board.mdl","rb") != 0)
return;

fread(&num_board_vertices,4,1,fs);

board_vertices = new vertex[num_board_vertices];

fseek(fs,4,SEEK_SET);
fread(board_vertices,num_board_vertices * sizeof(vertex),1,fs);

// Create, bind and fill the board's VBO.

glGenBuffers(1,&board_VBO);
glBindBuffer(GL_ARRAY_BUFFER,board_VBO);

board_texture = new texture;
board_texture->LoadTexture("data/board.tga");

glBufferData(GL_ARRAY_BUFFER,num_board_vertices * sizeof(vertex),board_vertices,GL_STATIC_DRAW);

glVertexPointer(3,GL_FLOAT,sizeof(vertex),BUFFER_OFFSET(0));
glNormalPointer(GL_FLOAT,sizeof(vertex),BUFFER_OFFSET(12));
glTexCoordPointer(2,GL_FLOAT,sizeof(vertex),BUFFER_OFFSET(24));

board_shaders = new Shader("data/shaders/board.vs","data/shaders/board.fs");

glBindTexture(GL_TEXTURE_2D,board_texture->GetTextureID());
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,board_texture->GetImageWidth(),board_texture->GetImageHeight(),0,GL_RGBA,GL_UNSIGNED_BYTE,board_texture->GetImageData());

glBindBuffer(GL_ARRAY_BUFFER,0);

fclose(fs);
}
[/source]

The piece loading function is similar.

To draw, I'm doing this:

[source]

void board::DrawBoard(void)
{
int texture_location;

glBindBuffer(GL_ARRAY_BUFFER,board_VBO);

board_shaders->bind();

glActiveTexture(GL_TEXTURE0);
texture_location = glGetUniformLocation(board_shaders->id(),"tex");
glUniform1i(texture_location,0);
glBindTexture(GL_TEXTURE_2D,board_texture->GetTextureID());

glEnableClientState(GL_VERTEX_ARRAY);
//glEnableClientState(GL_COLOR_ARRAY); // Normal and color arrays are not used yet.
//glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glDrawArrays(GL_TRIANGLES,0,num_board_vertices);

glDisableClientState(GL_TEXTURE_COORD_ARRAY);
//glDisableClientState(GL_NORMAL_ARRAY);
//glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER,0);

board_shaders->unbind();
}
[/source]

Again, the piece rendering function is similar. The major difference is that the piece rendering function sets the VBO to the piece's VBO, shaders and vertex count.

It is as if glBindBuffer isn't binding the data to the correct buffer. I know that the code works, so long as I don't try to load multiple models. Each model loads and renders correctly on its own.

I am aware that there are newer and better methods of using VBOs, but I want to get this to work before I change the functions. I had already written the code when I found out about the attribute functions. It stands to reason that if I cannot get the older functions to work properly, that I'll end up having trouble with the new function. One thing at a time.

Share this post


Link to post
Share on other sites
Advertisement
Never mind. I figured it out. I just needed to move the glBufferData and glXXXPointer functions into the render function.

Share this post


Link to post
Share on other sites
I think, moving glBufferData of static vertex-data into the draw-loop isn't what you want to do, because then you reupload the same data every frame.

I think the problem was, that the calls to gl*Pointer for both buffers have overwritten each other.
It should be enough to call glBindBuffer and the corresponding gl*Pointer calls in the render-loop.

A common way to store this state is using VertexArrayObjects (VAO). Those store the opengl-state of one or more buffers and which attribute-locations are connected to them through the gl*Pointer-calls.

For example you could do something like that:

GLuint board_vao;
glGenVertexArrays(1, &board_vao);
glGenBuffers(1,&board_VBO);

glBindVertexArray(board_vao);
glBindBuffer(GL_ARRAY_BUFFER,board_VBO);
glBufferData(GL_ARRAY_BUFFER,num_board_vertices * sizeof(vertex),board_vertices,GL_STATIC_DRAW);

glVertexPointer(3,GL_FLOAT,sizeof(vertex),BUFFER_OFFSET(0));
glNormalPointer(GL_FLOAT,sizeof(vertex),BUFFER_OFFSET(12));
glTexCoordPointer(2,GL_FLOAT,sizeof(vertex),BUFFER_OFFSET(24));

If you do the same for the your other VBO's, which vertices you want to draw independently, then you can simply draw them like this:

glBindVertexArray(board_vao); // remembers which VBO's are bound and which attribs have been connected via gl*Pointer.
board_shaders->bind();
// Set texture-state ...
glDrawArrays(GL_TRIANGLES,0,num_board_vertices);

glBindVertexArray(piece_vao);
piece_shaders->bind();
// Set texture-state ...
glDrawArrays(GL_TRIANGLES,0,num_piece_vertices);

...

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!