About OpenGL



  • I create a openglwidget in my application, it is placed in another widget which is the central widget of my application. I want to draw a 3D three pyramid. But it only appears for an instant. Please help me analyze my code to find where is my problem. Thanks in advance. The code is following:

    #ifndef MY_OPENGL_H
    #define MY_OPENGL_H
    
    #include <QOpenGLWidget>
    #include <QOpenGLFunctions_3_3_Core>
    #include <QOpenGLContext>
    #include <QOpenGLPaintDevice>
    #include <QPainter>
    #include <QOpenGLVertexArrayObject>
    #include <QOpenGLBuffer>
    #include <QOpenGLShader>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLTexture>
    #include <QEvent>
    #include <QApplication>
    #include <QMatrix4x4>
    
    class my_OpenGL : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
    {
        Q_OBJECT
    
    public:
        explicit my_OpenGL(QWidget *parent = 0);
        ~my_OpenGL();
    
        void initializeGL()override;
        void resizeGL(int w,int h)override;
        void paintGL()override;
    //    virtual void paintGL(QPainter *painter);
    
        void setAnimating(bool animating);
    
    public slots:
        void paintLater();
    //    void paintNow();
    
    protected:
        void paintEvent(QPaintEvent *e) override;
    //    bool event(QEvent *e) override;
    
    protected slots:
    //    void update();
    
    private:
        bool m_animating;
    //    QOpenGLContext *m_context;
        QOpenGLPaintDevice *m_device;
        QOpenGLShader *m_vertex_shader;
        QOpenGLShader *m_fragment_shader;
        QOpenGLShaderProgram *m_program;
        QOpenGLTexture *m_texture;
    
        unsigned int VBO;
        unsigned int VAO;
        unsigned int EBO;
    
        QMatrix4x4 view;
        QMatrix4x4 projection;
        QMatrix4x4 model;
    
        quint64 m_frame;
    };
    
    #endif // MY_OPENGL_H
    
    #include "my_opengl.h"
    
    float vertices[] = {
        0.0f, 0.707f, 0.0f, 1.0f, 0.0f, 0.0f,
        -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f,
        0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 0.707f,0.0f, 0.0f, 0.0f
    };
    
    unsigned int indices[] = {
        0, 1, 2,
        0, 1, 3,
        0, 2, 3,
        1, 2, 3
    };
    
    my_OpenGL::my_OpenGL(QWidget *parent):QOpenGLWidget(parent)
                ,m_program(0)
                ,m_texture(0)
                ,m_animating(false)
                ,m_device(0)
                ,m_frame(0)
    {
        QSurfaceFormat format;
        format.setSamples(16);
        format.setDepthBufferSize(24);
        setFormat(format);
    }
    
    my_OpenGL::~my_OpenGL()
    {
        makeCurrent();
    
        delete m_texture;
        delete m_vertex_shader;
        delete m_fragment_shader;
        delete m_program;
        delete m_device;
    
        doneCurrent();
    }
    
    const char *vertexShaderSource = "#version 330 core\n"
        "layout (location = 0) in vec3 aPos;\n"
        "layout (location = 1) in vec3 aCol;\n"
        "varying lowp vec4 col;\n"
        "uniform mat4 model;\n"
        "uniform mat4 view;\n"
        "uniform mat4 projection;\n"
        "void main()\n"
        "{\n"
        " gl_Position = projection * view * model * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
        " col = vec4(aCol.x, aCol.y, aCol.z, 1.0);\n"
        "}\0";
    const char *fragmentShaderSource = "#version 330 core\n"
        "out vec4 FragColor;\n"
        "varying lowp vec4 col;\n"
        "void main()\n"
        "{\n"
        " FragColor = col;\n"
        "}\n\0";
    
    void my_OpenGL::initializeGL()
    {
        initializeOpenGLFunctions();
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    
        m_texture = new QOpenGLTexture(QImage(":/myImages/image/icon.png"));
    
        m_vertex_shader = new QOpenGLShader(QOpenGLShader::Vertex);
        m_vertex_shader->compileSourceCode(vertexShaderSource);
    
        m_fragment_shader = new QOpenGLShader(QOpenGLShader::Fragment);
        m_fragment_shader->compileSourceCode(fragmentShaderSource);
    
        m_program = new QOpenGLShaderProgram(this);
        m_program->addShader(m_vertex_shader);
        m_program->addShader(m_fragment_shader);
        m_program->link();
    
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);
        // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
        glBindVertexArray(VAO);
    
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
    
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
    
        glEnable(GL_DEPTH_TEST);
    }
    
    void my_OpenGL::paintGL()
    {
        const qreal retinaScale = devicePixelRatio();
        glViewport(0, 0, width() * retinaScale, height() * retinaScale);
    
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    
        m_program->bind();
        glBindVertexArray(VAO);
    
        projection.perspective(45.0f, (float)1024/640, 0.1f, 100.0f);
        view.translate(0.0f, 0.0f, -3.0f);
        model.rotate(-30.0, 1.0f, 0.0f, 0.0f);
    
        m_program->setUniformValue(m_program->uniformLocation("projection"), projection);
        m_program->setUniformValue(m_program->uniformLocation("view"), view);
        m_program->setUniformValue(m_program->uniformLocation("model"), model);
    
        glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);
    
        m_program->release();
    
        ++m_frame;
    }
    
    void my_OpenGL::paintLater()
    {
    
    }
    
    void my_OpenGL::resizeGL(int w, int h)
    {
        Q_UNUSED(w);
        Q_UNUSED(h);
    }
    
    void my_OpenGL::setAnimating(bool animating)
    {
        m_animating = animating;
    
        if (animating)
            paintLater();
    }
    
    void my_OpenGL::paintEvent(QPaintEvent *e)
    {
        Q_UNUSED(e);
    
        if(isVisible())
        {
            paintGL();
            update();
        }
    
        else return;
    }
    
    


  • I think maybe the problem is that my openglwidget is embed into another widget.



  • Anyone can help me? I've been puzzled for a long time, and I don't know where the problem is. Or give me an example of QOpenGLWidget? Thanks a lot!


  • Lifetime Qt Champion

    Hi,

    Does it do anything if you only show that widget ?



  • Thank you for your reply. I have tried to build a small program, only used a QOpenGLWidget. After the same problem, I went through a step-by-step debugging. Finally, I found the problem, my OpenGL drawing code is not wrong, the error is wrong to use the update () function. The Qt documentation shows that the update () function will automatically call the paintEvent event function. If you do not restructure the paintEvent function, then your fictitious paintGL () function will be called automatically and the graph updated. Wrong function call order caused my 3D graphics to not get the correct context. The best and easiest solution is to call update () directly in the paintGL () function and discard restructuring paintEvent function. This code has become very simple, my problem is solved. I do not know if my understanding is correct, but after the amendment my program is running correctly.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.