【问题标题】:Using VAO with glDrawElements将 VAO 与 glDrawElements 一起使用
【发布时间】:2018-04-20 19:22:34
【问题描述】:

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

谁能看出我做错了什么?

更新

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

【问题讨论】:

    标签: c++ opengl-3 vao


    【解决方案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);
    

    【讨论】:

    • 感谢您的有用建议。我已经更新了我的代码,但是我仍然遇到一个奇怪的问题,我必须在绘图代码中的glBindVertexArray(vao_); 之前调用glBindBuffer(GL_ARRAY_BUFFER, attributes_id_);。这正常吗?
    • 原因是glBindBuffer(GL_ARRAY_BUFFER, attributes_id_);必须在glBufferData(GL_ARRAY_BUFFER, ..)之前调用
    • 是的,谢谢刚刚找到一个关于它的帖子(非常感谢您的帮助):stackoverflow.com/questions/17227031/…
    【解决方案2】:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-21
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      • 2020-01-05
      • 1970-01-01
      • 1970-01-01
      • 2013-09-21
      相关资源
      最近更新 更多