OpenGL绘制多个对象

OpenGL drawing several objects

本文关键字:对象 绘制 OpenGL      更新时间:2023-10-16

人们通常如何在OpenGL 3.3+中绘制多个对象?我有两个对象:一个地形和一个球体。对于每个对象,我有2个数组(顶点和索引)。我尝试设置不同的VBO和IBO(像这样):

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

但看起来GPU只在关闭这个函数后计算/绘制所有内容,而我只看到一个球体。那么,我该怎么办?

您似乎误解了绑定缓冲区的含义以及正确的调用顺序。

您预计在这个序列中,draw调用将从id为m_VBO:的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);

这不是它的工作方式。当前的GL_ARRAY_BUFFER绑定对draw调用绝对没有影响。

调用glVertexAttribPointer()时,需要绑定正确的VBO。除了指定相应属性(格式、步幅等)设置值的直接参数外,此调用还指定将当前绑定的VBO用作属性数据的源。

因此,您需要为每个对象调用glVertexAttribPointer(),并在绑定相应的VBO后调用它们。

调用顺序为:

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

如果要减少每次绘制调用前所需的设置调用次数,请查找"顶点阵列对象"(VAO)。