Qt 5.5和OpenGL:尝试调用paintGL()时引发的读取访问冲突异常

时间:2015-08-29 15:11:22

标签: c++ qt opengl

我正在编写一个简单的应用程序,它使用Qt 5.5和OpenGL在QtOpenGLWidget中绘制一些非常基本的几何体。最初,大部分顶点数据初始化和渲染代码都是从用于绘制单个三角形的教程中取出的。这个版本工作正常,但我自己尝试修改它以促进4个顶点形成一个正方形已经没有成功。程序编译时没有错误,但在执行时甚至没有将ui绘制到屏幕时崩溃,并出现以下错误:

error: Exception at 0x53fe35, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)

我到处都在使用Qt的OpenGL包装器。

我发现的第一个潜在(可能)解决方案是the manual帖子;有问题的问题有一个相同的错误签名,并且错误地启用或配置VAO的问题原因的描述,对我来说似乎相当可观,考虑到向VBO添加另一个顶点以及我可能无法正确重新配置glVertexAttribPointer。但是,我不能在我的代码中找到问题。

GLWidget(有问题的OpenGL小部件)声明:

class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
    Q_OBJECT

    void prepareVertexBuffers();

    void prepareVertexShader();
    void prepareFragmentShader();
    void prepareShaderProgram();

    void applyShaderPrograms();

    QOpenGLBuffer *vertBuffer;
    QOpenGLBuffer *elementBuffer;
    QOpenGLVertexArrayObject *vao;

    QOpenGLShader *vertShader;
    QOpenGLShader *fragShader;
    QOpenGLShaderProgram *shaderProgram;

public:
    GLWidget(QWidget *parent = 0);

    void initializeGL();
    void resizeGL();
    void paintGL();

signals:
    void shaderCompiled(const QString compilationLog);

public slots:
    void updateFragmentShader(QString newsource);
};

prepareVertexBuffers()函数 - 这里我定义了4个顶点并将它们排列成2个三角形以形成正方形。

void GLWidget::prepareVertexBuffers() {

    static const GLfloat vertData[] = {
       -1.0f, 1.0f, 0.0f,
       -1.0f, -1.0f, 0.0f,
       1.0f,  -1.0f, 0.0f,
       1.0f,  1.0f, 0.0f,
    };

    static const GLushort elementData[] = {1, 2, 3, 2, 3, 4};

    vao = new QOpenGLVertexArrayObject(this);
    vao->create();
    vao->bind();

    vertBuffer = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    vertBuffer->create();
    vertBuffer->allocate(vertData, 4 * 3 * sizeof(GLfloat) );
    vertBuffer->setUsagePattern( QOpenGLBuffer::StaticDraw );
    vertBuffer->bind();

    elementBuffer = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    elementBuffer->create();
    elementBuffer->allocate(elementData, 6 * sizeof(GLushort) );
    elementBuffer->setUsagePattern( QOpenGLBuffer::StaticRead );
    elementBuffer->bind();
}

paintGL(),我怀疑问题是:

void GLWidget::paintGL() {
    vao->bind();
    vertBuffer->bind();
    elementBuffer->bind();

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, (void*)0 );
    glEnableVertexAttribArray(0);

    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLES, 0, 4);
    glDisableVertexAttribArray(0);
    elementBuffer->release();
    vertBuffer->release();
    vao->release();
}

很明显,我几乎没有使用OpenGL的经验,因此我们也会理解如何正确构建代码,以及一般的编码实践。

1 个答案:

答案 0 :(得分:0)

感谢derhass做了一些澄清。我盲目地假设glDrawArrays神奇地使用当前绑定的元素缓冲区来绘制 - 显然它不是这样。我改变了行

glDrawArrays(GL_TRIANGLES, 0, 4);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

并且程序在启动时不再崩溃。

此外,我确保在根据文档为它们分配内存之前绑定()缓冲区。