Qt Opengl VBO 数据损坏

Posted

技术标签:

【中文标题】Qt Opengl VBO 数据损坏【英文标题】:Qt Opengl VBO data corrupted 【发布时间】:2015-12-03 17:49:49 【问题描述】:

到现在为止,我已经尝试了将近两个星期来让 VBO 在 Qt 环境中工作,但到目前为止没有任何效果。我的目标是创建一个三角形网格以用作某些地形的基础,就像在 Lighthouse3D 教程中一样。我的程序的相关部分如下:

GameWindow.h

class GameWindow : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core

    Q_OBJECT
public:
    GameWindow(QWidget *parent = 0);
    ~GameWindow();

protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int width, int height) override;
    virtual void paintGL() override;

    QGLShaderProgram *shaderProgram;

private:
    int frame;

    std::vector<GLfloat> grid;

    QOpenGLBuffer vbo;
    GLuint vboId;

    QVector3D position;
;

GameWindow.cpp

GameWindow::GameWindow(QWidget *parent) :
    QOpenGLWidget(parent),
    position(QVector3D(0, 5, -5)),
    vbo(QOpenGLBuffer(QOpenGLBuffer::VertexBuffer))


GameWindow::~GameWindow()


void GameWindow::initializeGL()

    QOpenGLWidget::initializeGL();
    initializeOpenGLFunctions();

    shaderProgram = new QGLShaderProgram(QGLContext::currentContext());

    QGLShader vertex(QGLShader::Vertex);
    vertex.compileSourceFile(QDir(":/shaders").absoluteFilePath("basic.vert"));
    shaderProgram->addShader(&vertex);

    QGLShader fragment(QGLShader::Fragment);
    fragment.compileSourceFile(QDir(":/shaders").absoluteFilePath("basic.frag"));
    shaderProgram->addShader(&fragment);

    shaderProgram->link();

    QImage image;
    image.load("C:\\test.png");

    int width = image.width(); //=10
    int height = image.height(); //=10

    for (int i = 0; i < height-1; i++) 
        for (int j = 0; j < width-1; j++) 
            grid.push_back(GLfloat(j));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i));

            grid.push_back(GLfloat(j));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i+1));

            grid.push_back(GLfloat(j+1));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i+1));


            grid.push_back(GLfloat(j+1));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i+1));

            grid.push_back(GLfloat(j+1));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i));

            grid.push_back(GLfloat(j));
            grid.push_back(GLfloat(0.0f));
            grid.push_back(GLfloat(i));
        
    

    vbo.create();
    vbo.bind();
    vbo.allocate(grid.size()*sizeof(GLfloat));

    vbo.write(0, grid.data(), grid.size()*sizeof(GLfloat));
    vbo.release();

    /*
    glGenBuffers(1, &vboId);

    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, grid.size() * sizeof(GLfloat), grid.data(), GL_STATIC_DRAW);
    //*/

    std::cout << std::boolalpha << (glGetError() == GL_NO_ERROR) << std::endl;


void GameWindow::resizeGL(int width, int height)

    QOpenGLWidget::resizeGL(width, height);


void GameWindow::paintGL()

    shaderProgram->bind();

    QMatrix4x4 projection;
    projection.perspective(45, qreal(width())/qreal(height() > 0 ? height() : 1), 0.1f, 100.0f);

    QMatrix4x4 view;
    view.lookAt(position, QVector3D(0, 0, 0), QVector3D(0, 1, 0));

    QMatrix4x4 model;
    model.translate(-0.5f, 0, 0);

    QMatrix4x4 mvp;
    mvp = projection * view * model;

    shaderProgram->setUniformValue("matrix", mvp);

    glClear(GL_COLOR_BUFFER_BIT);

    vbo.bind();

    shaderProgram->enableAttributeArray("vertex");
    shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
    glDrawArrays(GL_TRIANGLES, 0, vbo.size());

    shaderProgram->disableAttributeArray("vertex");

    /*
    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, 0);

    glDrawArrays(GL_TRIANGLES, 0, grid.size());

    glDisableVertexAttribArray(0);
    */

    shaderProgram->release();

    update();

着色器

//Vertex Shader
attribute vec3 vertex;
uniform mat4 matrix;

varying vec3 pos;

void main(void)

    gl_Position = matrix * vec4(vertex, 1);

    pos = vertex;


//Fragment Shader
void main(void)

    gl_FragColor.rgb = pos;

最后我像这样打开窗口:

QSurfaceFormat format;
format.setVersion(3, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);

GameWindow *w = new GameWindow();
w->show();

运行这个程序后,我得到了类似的东西,虽然它经常改变:

从代码中可以看出,我尝试使用QOpenGLBuffer 和原始gl* 命令创建和绘制我的VBO,结果相似。谷歌没有任何帮助,所以现在我向你寻求帮助。我的 VBO 出了什么问题,为什么数据损坏了?

注意:

当我运行时,我在标准输出中收到此错误:

[opengl\qopenglframebufferobject.cpp line 565] OpenGL Error: 1286
QOpenGLFramebufferObject: Unsupported framebuffer format.
QOpenGLFramebufferObject: Unsupported framebuffer format.
[opengl\qopenglframebufferobject.cpp line 720] OpenGL Error: 1280

但我不知道这是否与它有关。

注2:

尝试使用 vbo.read() 会使我的程序崩溃。

【问题讨论】:

您能解释一下您投反对票的原因吗? 【参考方案1】:

当你发出这个命令时:

shaderProgram->setAttributeBuffer("vertex", GL_FLOAT, 0, 3);

您确实是在说每 3 个浮点数将被解释为 1 个属性。因此,要绘制,您需要调用:

glDrawArrays(GL_TRIANGLES, 0, grid.size()/3);

注意。在我看来, vbo.size() 为您提供了进入 vbo 对象的字节数,而不是进入缓冲区的元素数量

【讨论】:

非常感谢,成功了:D【参考方案2】:

在 Qt 中,OpenGL 操作仅在放置在 makeCurrent ... doneCurrent 块内或 …GL 方法内时才有效。如果两个前提条件都不满足,则没有可创建 VBO 的 OpenGL 活动。

解决方案:将 OpenGL 初始化代码从构造函数移至 initializeGL

【讨论】:

哦,哇,原来如此简单:/奇怪的是它对单个三角形工作正常......但谢谢你,我会试试这个:)

以上是关于Qt Opengl VBO 数据损坏的主要内容,如果未能解决你的问题,请参考以下文章

QT_OPENGL-------- 3.ElementArraryBuffer

使用 OpenGL VBO 绘制数千个多边形

Qt/OpenGL 小部件中的显示损坏

Qt/OpenGL 试图显示 2D 纹理

配置VAO和VBO时,顶点数据数组是不是应该使用相同的方法? (OpenGL)[重复]

OpenGL 更新不同大小的 VBO 数据