QOpenGLVertexArrayObject 的使用

Posted

技术标签:

【中文标题】QOpenGLVertexArrayObject 的使用【英文标题】:Usage of QOpenGLVertexArrayObject 【发布时间】:2013-12-17 12:49:46 【问题描述】:

我有一个关于 QT 中的 VAO 的问题。正如假设的here,我编写了以下代码用于初始化:

void GLWidget::initializeGL() 
    vao.create();
    vao.bind();
    // setting up buffers
    buffer.create();
    buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
    buffer.bind();
    buffer.allocate(vertices.data(), 3 * vertices.size() * sizeof(float));
    vao.release();


在绘画阶段,我只是简单地做以下事情:

void GLWidget::paintGL() 
  // some other code
  vao.bind();
  if(shader_program->isLinked()) 
    shader_program->setUniformValue("mvpMatrix", p_matrix * v_matrix * m_matrix);
    // the interesting part about the buffer:
    shader_program->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
    shader_program->enableAttributeArray("vertex");
    // the drawing
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());
    shader_program->disableAttributeArray("vertex");
   
  vao.release();
 

就我只处理一个 VAO 而言,这很有效。但是在使用多个 VAO 时,没有或只绘制一个“对象”(缓冲区)。每个对象的代码完全相同,所以绘图总是

    绑定 VAO 为着色器程序分配变量 画三角形 发布 VAO

所以问题是如何使用多个 vao,包括不同的缓冲区。

【问题讨论】:

否决这个问题的意义何在? m47h,你有没有找到在 Qt 中处理多个 VAO 或 VBO 的解决方案?我也有类似的问题。 @Alchete:不,我没有。我决定放弃这些 Qt 包装类并“手动”完成。 【参考方案1】:

您错误地抽象了您的 GLSL 程序类。

程序本身不存储顶点数组指针和数组启用/禁用状态,VAO 会。您需要将代码直接移动到注释下方:“关于缓冲区的有趣部分:”到initializeGL (...),但由于您的 GLSL 程序类当前设置的方式,您需要重构它以及您的 VAO 类。

目前没有initializeGL (...) 中的命令实际上会影响您的 VAO 的状态 - 您正在绑定和解除绑定 VAO 之间有一些不相关的命令(正如我将在下面解释的那样)。


请注意,VAO 不会显式存储顶点缓冲区绑定,但数组指针与调用函数时绑定的任何 VBO 相关。然而,VAO确实存储元素缓冲区绑定(用于glDrawElements (...))。当您重新装备您的 VAO 类时,这可能会成为重要的知识。

在使用 VAO 时,您也不应该在绘制前后启用和禁用数组,这是创建 VAO 的部分原因。您在绘制之前绑定一个 VAO,它负责启用它需要的所有数组并禁用它不需要的数组(应该在您的 initializeGL (...) 函数中建立)。

【讨论】:

我想我明白了。但我的问题是,VAO 类和 Shaderprogram 类是从 QT 5 提供的,我想知道如何在不重构它们的情况下以正确的方式使用它们。 真的吗?我对 Trolltech/诺基亚/现在拥有 Qt 的人的期望会更好。 GLSL 程序不存储您必须使用 GLSL 程序对象来设置的状态...必须使用 GLSL 程序来设置 VAO 状态是彻头彻尾的糟糕设计:-\ 我想您只需要记住这一点, VAO 存储这些状态,因此即使您使用 GLSL 程序对象来设置它们,您也需要在当前绑定的任何 VAO 的上下文中执行它们。

以上是关于QOpenGLVertexArrayObject 的使用的主要内容,如果未能解决你的问题,请参考以下文章