如何正确使用glDrawElements与glBindVertexArray

时间:2014-12-15 22:36:23

标签: c++ opengl glsl

我要做的是使用glDrawElements绘制没有顶点冗余的内容,如下所示:

Model ModelManager::CreateModel(std::vector<glm::vec3>&vertices, std::vector<uint16_t>&vertexIndeces)
{
    //Vertecies
    GLuint vertexArray;

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

    GLuint vBufferId;
    glGenBuffers(1, &vBufferId);
    glBindBuffer(GL_ARRAY_BUFFER, vBufferId);
    glBufferData(GL_ARRAY_BUFFER, vertices.size(), vertices.data(), GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

    GLuint iBufferId;
    glGenBuffers(1, &iBufferId);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBufferId);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertexIndeces.size(), vertexIndeces.data(), GL_STATIC_DRAW);

    glBindVertexArray(0);
    //
    return Model(vertexArray, vBufferId, iBufferId, vertexIndeces.size());
}

然后当我画画时:

void Model::Draw()
{
    if (vertexArray)
    {
        isFinishedIniting = true;
        glBindVertexArray(vertexArray);
        glDrawElements(GL_TRIANGLES, elementCount, GL_UNSIGNED_SHORT, 0);
        glBindVertexArray(0);
    }
}

着色器:

#version 120


void main()
{
        gl_Position= gl_ModelViewProjectionMatrix*gl_Vertex;

}

#version 120


void main()
{
    gl_FragColor=vec4(1.0,0.0,0.0,0.0);
}

我试图加载的obj文件很容易实现:

v 0.0 0.0 0.0
v 1.0 1.0 0.0
v -1.0 1.0 0.0
v -1.0 -1.0 0.0
v 1.0 -1.0 0.0

f 1/1/1 2/1/1 3/1/1
f 1/1/1 4/1/1 5/1/1

所以它应该显示两个红色三角形,但它没有在屏幕上绘制任何东西!

1 个答案:

答案 0 :(得分:2)

此代码中存在一些问题:

  1. 传递给glBufferData()的尺码看起来不对:

    glBufferData(GL_ARRAY_BUFFER, vertices.size(), vertices.data(), GL_STATIC_DRAW);
    ...
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertexIndeces.size(), vertexIndeces.data(), GL_STATIC_DRAW);
    

    verticesvertexIndeces()都是向量。 .size()上的vector方法提供了元素的数量,而glBufferData()期望字节中的大小。要解决此问题,请将代码更改为:

    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertices[0]),
                 vertices.data(), GL_STATIC_DRAW);
    ...
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertexIndeces.size() * sizeof(vertexIndeces[0]),
                 vertexIndeces.data(), GL_STATIC_DRAW);
    
  2. API调用使用固定函数属性和通用顶点属性的混合。基于着色器代码中的版本和着色器代码本身(特别是gl_Vertex的使用),您将使用具有固定功能属性的OpenGL 2.1级别着色器。因此,您需要使用glEnableClientState()glVertexPointer()代替glEnableVertexAttribArray()glVertexAttribPointer()

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, 0);
    

    您可以使用通用顶点属性,但是您需要在顶点着色器中声明类型为attribute的变量,而不是使用gl_Vertex