【问题标题】:Combining Vertex Array Object with Vertex Buffer & Index Buffer将顶点数组对象与顶点缓冲区和索引缓冲区相结合
【发布时间】:2016-06-23 18:52:05
【问题描述】:

我正在尝试使用 Qt 将顶点数组对象与顶点缓冲区和索引缓冲区结合起来。

以下代码结合了 VAO 和 VBO,完美运行:

// Create buffers
void Tile::setupBuffers() {
    vbo.create();
    vbo.bind();
    vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    vbo.allocate(vertices.constData(), vertices.size() * sizeof(QVector3D));
    vbo.release();

    vao.create();

    shaderProgram->bind();
    vao.bind();
        vbo.bind();
        shaderProgram->enableAttributeArray(0);
        shaderProgram->setAttributeBuffer(positionLocation, GL_FLOAT, 0, 3, 0);    
    vao.release();

    shaderProgram->disableAttributeArray(0);
    vbo.release();
    shaderProgram->release();
}

// Draw triangle    
void Tile::draw() {
    shaderProgram->bind();
    vao.bind();

    glDrawArrays(GL_TRIANGLES, 0, 3);

    vao.release();
    shaderProgram->release();
}

当我现在尝试添加索引缓冲区时,除了清晰的颜色之外,什么都没有绘制。代码如下:

// Create buffers
void Tile::setupBuffers() {
    vbo.create();
    vbo.bind();
    vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    vbo.allocate(vertices.constData(), vertices.size() * sizeof(QVector3D));
    vbo.release();

    ibo.create();
    ibo.bind();
    ibo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    ibo.allocate(indices.constData(), indices.size() * sizeof(GLushort));
    ibo.release();

    vao.create();

    shaderProgram->bind();
    vao.bind();
        vbo.bind();
        shaderProgram->enableAttributeArray(0);
        shaderProgram->setAttributeBuffer(positionLocation, GL_FLOAT, 0, 3, 0);

        ibo.bind();
    vao.release();

    shaderProgram->disableAttributeArray(0);
    vbo.release();
    ibo.release();
    shaderProgram->release();
}

void Tile::draw() {
    shaderProgram->bind();
    vao.bind();

    glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, 0);

    vao.release();
    shaderProgram->release();
}

这是我的顶点向量和索引向量的内容:

vertices = {
    QVector3D(1.0f, -1.0f, 0.0f),
    QVector3D(1.0f, 1.0f, 0.0f),
    QVector3D(-1.0f, -1.0f, 0.0f)
};

indices = {
     0, 1, 2
};

我假设在第二个代码块中绑定 VAO/VBO/IBO 的顺序是错误的,我只是不知道它是如何正确完成的。任何帮助表示赞赏。

【问题讨论】:

  • 这里面是否有任何真正的 OpenGL,或者你只是为所有这些使用某种包装器?
  • ...哇。 Qt 的包装是garbage。我不知道更糟的是:他们使setAttributeBuffer 成为与顶点状态绝对无关的类型的成员,或者他们甚至懒得让你通过缓冲区直接对象,即the very worst aspect of glVertexAttribPointer。我印象深刻;把搞得那么糟需要真正的努力。
  • @NicolBolas:是的,不幸的是,QOpenGLShaderProgram 试图通过为位置查找 + 顶点缓冲区规范提供方便的方法来变得有点“太聪明”。 (它也有许多其他的缺点,但我们现在不要去那里)。在那里使用这些方法没有任何意义。 OTOH,我明白为什么没有一个“更好”的地方来放置它们——我想到了 VAO,但在 GL2 或 GLES2 中没有 VAO,并且您可以想象 QOGLSP 早于 QOGLVAO。 :-\

标签: qt opengl


【解决方案1】:
glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, 0);

您的索引是GLushorts,而不是浮点数。你应该得到一个GL_INVALID_ENUM 错误;你应该经常检查 GL 错误。

另外,shaderProgram->disableAttributeArray(0); 完全没有必要。启用/禁用状态是 VAO 的一部分(Qt 的白痴包装相反)。禁用该属性不会更改 VAO,因为您取消了它的绑定。而且你也不想禁用它。

最后是这样的:

shaderProgram->enableAttributeArray(0);
shaderProgram->setAttributeBuffer(positionLocation, GL_FLOAT, 0, 3, 0);

这两个函数的第一个参数应该相同。他们可能是,所以这更像是一个良性错误。但还是错了。

【讨论】:

  • 谢谢,现在绘图工作。如果我不必使用 Qt,我就不会,你可以确定。
  • @vigilanum:您不必必须使用 Qt 的包装器。您可以使用 Qt 创建窗口并使用直接 OpenGL 调用来渲染它。
  • 好吧,我必须这样做,因为任务规定了这一点。
  • @vigilanum 在最基本的层面上,Qt 为您提供了已解析的指向 GL 的函数指针,这些指针被包装到了简单的方法中。您不需要使用任何更高级别的抽象,除非任务特别指定。
猜你喜欢
  • 2018-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多