Denis
Denis

Reputation: 759

OpenGL drawing several objects

How usually people draw several objects in OpenGL 3.3+? I have 2 objects: a terrain and a sphere. For each object i have 2 arrays(of vertices and indices). I tried to set different VBO and IBO(like this):

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);

    glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
    glDrawElements(GL_TRIANGLES, (size-1)*(size-1)*6, GL_UNSIGNED_INT, 0);



    glBindBuffer(GL_ARRAY_BUFFER, m_VBOsphere);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBOsphere);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);

but looks like GPU calculates/draw everything only after closing of this function and I see only a sphere. So, what should I do?

Upvotes: 1

Views: 338

Answers (1)

Reto Koradi
Reto Koradi

Reputation: 54572

It looks like you misunderstood the implications of binding a buffer, and the correct sequence of calls.

You expected that in this sequence, the draw call would get its vertices from the VBO with id m_VBO:

glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
glDrawElements(GL_TRIANGLES, (size-1)*(size-1)*6, GL_UNSIGNED_INT, 0);

That's not the way it works. The current GL_ARRAY_BUFFER binding has absolutely no effect on the draw call.

You need to have the right VBO bound when glVertexAttribPointer() is called. Beyond the direct arguments that specify values for the setup of the corresponding attribute (format, stride, etc), this call also specifies that the currently bound VBO is used as the source for the attribute data.

Therefore, you need the glVertexAttribPointer() calls for each object, and call them after binding the corresponding VBO.

The call sequence is then:

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
glDrawElements(GL_TRIANGLES, (size-1)*(size-1)*6, GL_UNSIGNED_INT, 0);

glBindBuffer(GL_ARRAY_BUFFER, m_VBOsphere);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBOsphere);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);

If you want to reduce the number of setup calls you need before each draw call, look up Vertex Array Objects (VAO).

Upvotes: 2

Related Questions