在现代 OpenGL 中使用 Indexed Draw 绘制立方体

Drawing a cube using Indexed Draw in modern OpenGL

我正在尝试使用 OpenGL 3.3 中的索引绘制来绘制立方体。但它没有显示正确... 这是我尝试做的。

GLfloat vertices01[] = {
  -1.0f,1.0f,0.0f,
  -1.0f,-1.0f,0.0f,
  1.0f,1.0f,0.0f,
  1.0f,-1.0f,0.0f,
  -1.0f,1.0f,-1.0f,
  -1.0f,-1.0f,-1.0f,
  1.0f,1.0f,-1.0f,
  1.0f,-1.0f,-1.0f
};
unsigned int indices01[] = {
  0, 2, 3, 1,
  2, 6, 7, 3,
  6, 4, 5, 7,
  4, 0, 1, 5,
  0, 4, 6, 2,
  1, 5, 7, 3
};


Mesh* obj3 = new Mesh();
obj3->CreateMesh(vertices01, indices01, 24, 24);
meshList.push_back(obj3);

meshList[0]->RenderMesh();

//在网格中class indexCount = numOfIndices;

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0])*numOfIndices, indices, GL_STATIC_DRAW);

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

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0])*numOfVertices, vertices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

glBindVertexArray(0);

glBindVertexArray(VAO);

//bind ibo
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

glDrawElements(GL_TRIANGLES,indexCount, GL_UNSIGNED_INT, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);

输出显示了一个部分立方体,它的每一边都有一个三角形,还有一个三角形穿过它的对角线

如果您使用兼容性配置文件上下文,那么您可以保留索引以供使用 GL_QUADS instead of GL_TRIANGLES. But that's deprecated (Legacy OpenGL)。

由于基本类型是GL_TRIANGLES,立方体的每一面都必须由2个三角形组成。参见 Triangle primitives

更改索引缓冲区以解决问题:

unsigned int indices01[] = {
  0, 2, 3, 0, 3, 1,
  2, 6, 7, 2, 7, 3,
  6, 4, 5, 6, 5, 7,
  4, 0, 1, 4, 1, 5,
  0, 4, 6, 0, 6, 2,
  1, 5, 7, 1, 7, 3,
};

另一种解决方案是使用原始类型 GL_TRIANGLE_STRIP and a Primitive Restart 索引。

启用原始重启并定义重启索引:

例如

glEnable( GL_PRIMITIVE_RESTART );
glPrimitiveRestartIndex( 99 );

定义2个三角带,由重启索引分隔:

unsigned int indices01[] = {
    0, 1, 2, 3, 6, 7, 4, 5,
    99, // 99 is the restart index
    7, 3, 5, 1, 4, 0, 6, 2
};
int indexCOunt = 17;

并绘制元素:

glDrawElements(GL_TRIANGLE_STRIP, indexCount, GL_UNSIGNED_INT, 0);

请注意,Index buffer binding is stored in the Vertex Array Object
因此,在设置 VAO 时绑定一次索引缓冲区就足够了:

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);  

// [...]

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

// [...]

// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); <---- delete this

glBindVertexArray(0);

然后在绘制调用之前再次绑定索引缓冲区是多余的:

glBindVertexArray(VAO);

// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); <---- now this is superfluous 

glDrawElements(GL_TRIANGLES,indexCount, GL_UNSIGNED_INT, 0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);