将VAO与glDrawElements一起使用

时间:2018-04-20 19:22:34

标签: c++ opengl-3 vao

我正在尝试(第一次)使用OpenGL 3.2在屏幕上绘制一些精灵。我正在尝试建立一个VAO,但它不起作用。我在调用glDrawElements时得到了一个EXC_BAD_ACCESS。

VAO设置:

// setting up VAO

glGenVertexArrays(1, &vao_);

glBindVertexArray(vao_);

glGenBuffers(1, &indices_id_);

glGenBuffers(1, &attributes_id_);

glBindBuffer(GL_ARRAY_BUFFER, attributes_id_);

constexpr GLfloat* ptr = 0;

::glVertexAttribPointer(attribute_position_, 2, GL_FLOAT, false, STRIDE, ptr);
::glVertexAttribPointer(attribute_region_, 2, GL_FLOAT, false, STRIDE, ptr + 2);
::glVertexAttribPointer(attribute_color_, 4, GL_FLOAT, false, STRIDE, ptr + 4);

::glEnableVertexAttribArray(attribute_position_);
::glEnableVertexAttribArray(attribute_region_);
::glEnableVertexAttribArray(attribute_color_);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_id_);

{
    auto data = std::make_unique<short[]>(BATCH_SIZE * 6);

    short j = 0;

    for (std::size_t i = 0; i < BATCH_SIZE * 6; i += 6, j += 4)
    {
        data[i] = j;
        data[i + 1] = (short)(j + 1);
        data[i + 2] = (short)(j + 2);
        data[i + 3] = (short)(j + 2);
        data[i + 4] = (short)(j + 3);
        data[i + 5] = j;
    }

    glBufferData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLsizeiptr>(BATCH_SIZE * 6 * sizeof(short)), data.get(), GL_STATIC_DRAW);
}

glBindVertexArray(0);

然后在绘图循环的其他地方:

// drawing

glBindVertexArray(vao_);

glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(sizeof(float) * buffer_index_), attributes_.data(), GL_DYNAMIC_DRAW);

glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(6 * number_of_sprites_), GL_UNSIGNED_SHORT, 0);

glBindVertexArray(0);

谁能看到我做错了什么?

更新

我已经添加了建议的更改(非常感谢那些)。但是,我现在发现我需要在glBindBuffer(GL_ARRAY_BUFFER, attributes_id_);之前添加对glBindVertexArray(vao_);的调用,以便在绘制时摆脱EXC_BAD_ACCESS错误。

2 个答案:

答案 0 :(得分:1)

glBufferData()期望作为目标缓冲区的第一个参数。命名在这里有点令人困惑,但这意味着你告诉OpenGL你指的是哪个绑定缓冲区,而不是缓冲区的name。这是一个例子:

glBindBuffer(GL_ARRAY_BUFFER, foo); // Binds the buffer named foo to the GL_ARRAY_BUFFER target

glBufferData(GL_ARRAY_BUFFER, ...); // Tells GL you mean the buffer bound to the GL_ARRAY_BUFFER target

答案 1 :(得分:1)

OpenGL 4.6 API Core Profile Specification; 10.3. VERTEX ARRAYS; page 347

  

通过绑定GenVertexArrays返回的名称来创建顶点数组对象   使用命令

void BindVertexArray( uint array );
     

array是顶点数组对象名。生成的顶点数组对象是一个新的状态向量,包含表中列出的所有状态和相同的初始值   23.4- 23.7。

表23.4包含ELEMENT_ARRAY_BUFFER_BINDING


这意味着绑定的ELEMENT_ARRAY_BUFFER的状态存储在Vertex Array Object中。

在您的情况下indices_id_存储在vao_的状态向量中,因为

glBindVertexArray(vao_);

.....

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_id_);

致电时

glBindVertexArray(0);

然后indices_id_不再是当前状态向量。

您必须更改说明的顺序:

glBindVertexArray(vao_);

.....

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_id_);
{
    .....
    glBufferData(indices_id_, static_cast<GLsizeiptr>(BATCH_SIZE * 6), data.get(), GL_STATIC_DRAW);
}
glBindVertexArray(0);