运行我的QOpenGLWidget实现时出现分段错误

nukf8bse  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(162)

我正在尝试实现一个最小可行的示例,以使用QOpenGLWidget运行与OpenGL2.1兼容的管道。在此示例中,我正在尝试创建一个与视图空间中的xy平面平行的平面(使用正交投影矩阵)。我还希望在片段着色器中使用顶点着色器的颜色输出变量。
当我运行我的代码时,我在调用glDrawElements时得到一个Segfault。我不是OpenGLMaven,总是很难正确地设置它,所以也许有人可以告诉我我在这里错过了什么。
CMakeLists.txt文件

cmake_minimum_required(VERSION 3.10)

project(OpenGLExample)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

find_package(Qt6 REQUIRED COMPONENTS Widgets OpenGLWidgets)
set(CMAKE_AUTOMOC ON)

add_executable(MainApp main.cpp)
target_link_libraries(MainApp PRIVATE Qt6::Widgets Qt6::OpenGLWidgets)

主文件. cpp


# include <QApplication>

# include <QOpenGLWidget>

# include <QOpenGLVertexArrayObject>

# include <QOpenGLBuffer>

# include <QOpenGLShader>

# include <QOpenGLShaderProgram>

# include <QVector3D>

# include <QOpenGLContext>

namespace {
    const QString vertexShader = ( "#version 120\n"
                                   "attribute vec3 pos;\n"
                                   "varying vec3 color;\n"
                                   "uniform mat4 mvp_mat;\n"
                                   "void main(){\n"
                                   "    gl_Position = mvp_mat * vec4(pos, 1);\n"
                                   "    color = (vec3(pos.x, pos.y, 0) + 1) / 2;\n"
                                   "}" );
    const QString fragmentShader = ( "#version 120\n"
                                     "varying vec3 color;\n"
                                     "void main() {\n"
                                     "    gl_FragColor = vec4(color, 1);\n"
                                     "}" );
}

class OpenGLTestWidget: public QOpenGLWidget {
    Q_OBJECT

public:
    OpenGLTestWidget(QWidget* parent = nullptr)
        : QOpenGLWidget(parent)
        , vertexData({QVector3D(-0.5f, -0.5f, -0.5f), 
                      QVector3D(0.5f, -0.5f, -0.5f), 
                      QVector3D(0.5f, 0.5f, -0.5f), 
                      QVector3D(-0.5f, 0.5f, -0.5f)})
    {
        modelMatrix.setToIdentity();
        viewMatrix.setToIdentity();
        projectionMatrix.setToIdentity();
        projectionMatrix.ortho(-1.0, 1.0, -1.0, 1.0, 0, 1);
    }

    virtual ~OpenGLTestWidget() {
        cleanup();
    }
protected:
    void initializeGL() override {
        vao.create(); // added in edit
        vao.bind(); // added in edit

        vbo.create();
        vbo.bind();
        vbo.allocate(vertexData.data(), sizeof(QVector3D) * vertexData.size());

        program = new QOpenGLShaderProgram(this);
        program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShader);
        program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShader);
        program->link();
        program->bind();

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLTestWidget::cleanup);
    }

    void paintGL() override {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        const QMatrix4x4 mpvMatrix = projectionMatrix * viewMatrix * modelMatrix;
        program->setUniformValue("mpv_mat", mpvMatrix);

        const int vertexLocation = program->attributeLocation("pos");
        program->enableAttributeArray(vertexLocation);
        program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(QVector3D));

        // glDrawElements(GL_TRIANGLE_FAN, vertexData.size(), GL_UNSIGNED_SHORT, nullptr); // <-- ERROR
        glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData.size()); // <-- no segfault but nothing renders
    }

private:
    QOpenGLVertexArrayObject vao; // added in edit
    QOpenGLBuffer vbo;
    QOpenGLShaderProgram* program;
    std::array<QVector3D, 4> vertexData;
    QMatrix4x4 modelMatrix;
    QMatrix4x4 viewMatrix;
    QMatrix4x4 projectionMatrix;

    void cleanup(){
        makeCurrent();
        delete program;
        vbo.destroy();
        vao.destroy(); // added in edit
        doneCurrent();
        disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLTestWidget::cleanup);
    }
};

# include "main.moc"

int main(int argc, char* argv[]) {
    QApplication a(argc, argv);
    OpenGLTestWidget test;
    test.show();
    return a.exec();
}
vjhs03f7

vjhs03f71#

1.缺少顶点数组对象。请添加成员变量

QOpenGLVertexArrayObject vao;

以及呼叫了

vao.create();
vao.bind();

然后绑定VBO。
1.模型-视图-投影矩阵的统一名称不匹配。

program->setUniformValue("mpv_mat", mpvMatrix);

需要

program->setUniformValue("mvp_mat", mpvMatrix);

1.绘制调用glDrawElements用于索引呈现。

glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData.size());

主动建议:您可能需要设置一个QOpenGLDebugLogger。在这种情况下,它并没有那么重要,但它在跟踪这类错误时可能很有用。

相关问题