【问题标题】:Drawing a cube using Indexed Draw in modern OpenGL在现代 OpenGL 中使用 Indexed Draw 绘制立方体
【发布时间】:2019-05-12 14:40:05
【问题描述】:

我正在尝试使用 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();

//在网格类中 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);

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

【问题讨论】:

    标签: opengl glfw glew


    【解决方案1】:

    如果您使用兼容性配置文件上下文,那么您可以使用GL_QUADS 而不是GL_TRIANGLES。但这已被弃用 (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_STRIPPrimitive 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 绑定存储在 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);
    

    那么在draw call之前再次绑定索引缓冲区是多余的:

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

    【讨论】:

    • 所以 GL_TRIANGLES 是在现代 OpenGL 中绘制立方体的唯一方法?
    • @ArpithS 我在答案中提供了一个替代解决方案。 (刚刚)
    • @ArpithS 答案中有一个复制/过去的问题。 glPrimitiveRestartIndex( 99 ); 不见了。我现在修好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    相关资源
    最近更新 更多