• 矩阵转换


    原文:https://www.jianshu.com/p/62fb681df39c

    Qt中有对应的QMatrix4x4处理4维矩阵

    使用OpenGL函数版

    #include "widget.h"
    #include "ui_widget.h"
    #include <QTImer>
    #include <QDebug>
    
    static GLuint VBO, VAO, EBO, texture1, texture2;
    
    Widget::Widget(QWidget *parent) :
        QOpenGLWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        m_timer = new QTimer(this);
        m_nTimeValue = 0;
        connect(m_timer,&QTimer::timeout,this,&slotTimer);
        m_timer->start(50);
    }
    
    void Widget::slotTimer()
    {
        m_nTimeValue += 5;
        update();
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::initializeGL()
    {
        this->initializeOpenGLFunctions();
    
        int success = m_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/textures.vert");
        if (!success) {
            qDebug() << "program addShaderFromSourceFile Failed." << m_program.log();
            return;
        }
        success = m_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/textures.frag");
        if (!success) {
            qDebug() << "program addShaderFromSourceFile Failed." << m_program.log();
            return;
        }
        success = m_program.link();
        if (!success) {
            qDebug() << "program link Failed." << m_program.log();
        }
    
        // VAO VBO VEO data
        float vertices[] = {
            // positions          // colors           // texture coords
             0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
             0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
        unsigned int indices[] = {  // note that we start from 0!
            0, 1, 3,  // first Triangle
            1, 2, 3   // second Triangle
        };
    
        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);
    
        // position attribute
        glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)0);
        glEnableVertexAttribArray(0);
        // color attribute
        glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)(3*sizeof(float)));
        glEnableVertexAttribArray(1);
        // texture coords
        glVertexAttribPointer(2,2,GL_FLOAT,GL_FALSE,8*sizeof(float),(void*)(6*sizeof(float)));
        glEnableVertexAttribArray(2);
    
        // texture1
        glGenTextures(1,&texture1);
        glBindTexture(GL_TEXTURE_2D,texture1);
    
        // set texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
        // SET texture filting parameters
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        // load image,create texture,generate mipmaps
        QImage image1 = QImage(":/image/image/container.jpg").convertToFormat(QImage::Format_RGB888);
        if (!image1.isNull()){
            glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,image1.width(),image1.height(),0,GL_RGB,GL_UNSIGNED_BYTE,image1.bits());
            glGenerateMipmap(GL_TEXTURE_2D);
        }
    
        // texture2
        glGenTextures(1,&texture2);
        glBindTexture(GL_TEXTURE_2D,texture2);
    
        // set texture wrapping parameters
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
        // SET texture filting parameters
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        // load image,create texture,generate mipmaps
        QImage image2 = QImage(":/image/image/awesomeface.png").convertToFormat(QImage::Format_RGBA8888).mirrored(true, true);
        if (!image2.isNull()){
            // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
            glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image2.width(),image2.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,image2.bits());
            glGenerateMipmap(GL_TEXTURE_2D);
        }
    
        // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
        m_program.bind();   // don't forget to activate/use the shader before setting uniforms!
        glUniform1i(m_program.uniformLocation("texture1"),0);
        glUniform1i(m_program.uniformLocation("texture2"),1);
        m_program.release();
    }
    
    void Widget::resizeGL(int w, int h)
    {
        glViewport(0,0,w,h);
    }
    
    void Widget::paintGL()
    {
        glClearColor(0.2f,0.3f,0.3f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
    
        // bind textures on corresponding texture units
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,texture1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D,texture2);
    
    
        // create transformations
        QMatrix4x4 transform;
        transform.translate(QVector3D(0.5f, -0.5f, 0.0f));
        transform.rotate(m_nTimeValue, QVector3D(0.0f, 0.0f, 1.0f));
    
        // get matrix's uniform location and set matrix
        m_program.bind();
        int transformLoc = m_program.uniformLocation("transform");
        glUniformMatrix4fv(transformLoc, 1, GL_FALSE, transform.data());
    
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,NULL);
        m_program.release();
    }
    cpp
    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    #include <QOpenGLWidget>
    #include <QOpenGLFunctions_3_3_Core>
    #include <QOpenGLShader>
    #include <QOpenGLShaderProgram>
    
    
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QOpenGLWidget,protected QOpenGLFunctions_3_3_Core
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = 0);
        ~Widget();
    
    protected:
        virtual void initializeGL();
        virtual void resizeGL(int w,int h);
        virtual void paintGL();
    public slots:
        void slotTimer();
    private:
        QOpenGLShaderProgram m_program;
        QTimer* m_timer;
        int m_nTimeValue;
    private:
        Ui::Widget *ui;
    };
    
    #endif // WIDGET_H
    hpp
    析构函数要记得释放
        glDeleteVertexArrays(1, &VAO);
        glDeleteBuffers(1, &VBO);
        glDeleteBuffers(1, &EBO);
    #version 330 core
    layout (location = 0) in vec3 aPos;
    layout (location = 1) in vec3 aColor;
    layout (location = 2) in vec2 aTexCoord;
    
    out vec3 ourColor;
    out vec2 TexCoord;
    
    uniform mat4 transform;
    
    void main()
    {
        gl_Position = transform * vec4(aPos, 1.0f);
        ourColor = aColor;
        TexCoord = aTexCoord;
        //TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);
    }
    texture.vert
    #version 330 core
    out vec4 FragColor;
    
    in vec3 ourColor;
    in vec2 TexCoord;
    
    uniform sampler2D texture1;
    uniform sampler2D texture2;
    
    void main()
    {
        //FragColor = texture(texture1, TexCoord) * vec4(ourColor, 1.0);
        FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
    }
    fragment.frag

    使用Qt相关函数版

    尝试再次调用glDrawElements画出第二个箱子,使用变换将其摆放在不同的位置。让这个箱子被摆放在窗口的左上角,并且会不断的缩放(而不是旋转)

    #include "qtfunwidget.h"
    #include <QTimer>
    
    QtFunWidget::QtFunWidget(QWidget *parent)
        : QOpenGLWidget(parent)
        ,vbo(QOpenGLBuffer::VertexBuffer)
        ,ebo(QOpenGLBuffer::IndexBuffer)
    {
        m_timer = new QTimer(this);
        connect(m_timer,&QTimer::timeout,this,[=]{
            m_timeValue += 5;
            update();
        });
        m_timer->start(50);
    }
    
    QtFunWidget::~QtFunWidget()
    {
        /*Prepares for rendering OpenGL content for this widget by making
         * the corresponding context current and binding the framebuffer object in that context.
    
            It is not necessary to call this function in most cases,
            because it is called automatically before invoking paintGL().
        */
        makeCurrent();
        vbo.destroy();
        ebo.destroy();
    
        if(texture1)
            delete texture1;
        if(texture2)
            delete texture2;
    
        doneCurrent();
    }
    
    void QtFunWidget::initializeGL()
    {
        this->initializeOpenGLFunctions();
        int success = m_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/textures.vert");
        if (!success) {
            qDebug() << "program addShaderFromSourceFile Failed." << m_program.log();
            return;
        }
        success = m_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/textures.frag");
        if (!success) {
            qDebug() << "program addShaderFromSourceFile Failed." << m_program.log();
            return;
        }
        success = m_program.link();
        if (!success) {
            qDebug() << "program link Failed." << m_program.log();
        }
    
        // VAO VBO VEO data
        float vertices[] = {
            // positions          // colors           // texture coords
             0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
             0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
        unsigned int indices[] = {  // note that we start from 0!
            0, 1, 3,  // first Triangle
            1, 2, 3   // second Triangle
        };
    
        QOpenGLVertexArrayObject::Binder vaobind(&vao);
    
        vbo.create();
        vbo.bind();
        vbo.allocate(vertices,sizeof(vertices));
    
        ebo.create();
        ebo.bind();
        ebo.allocate(indices,sizeof(indices));
    
        // position attribute
        int attr = -1;
        attr = m_program.attributeLocation("aPos");
        m_program.setAttributeBuffer(attr,GL_FLOAT,0,3,8*sizeof(GL_FLOAT));
        m_program.enableAttributeArray(attr);
        // color attribute
        attr = m_program.attributeLocation("aColor");
        m_program.setAttributeBuffer(attr,GL_FLOAT,3*sizeof(GL_FLOAT),3,8*sizeof(GL_FLOAT));
        m_program.enableAttributeArray(attr);
    
       // texture coord attribute
        attr = m_program.attributeLocation("aTexCoord");
        m_program.setAttributeBuffer(attr,GL_FLOAT,6*sizeof(GL_FLOAT),2,8*sizeof(GL_FLOAT));
        m_program.enableAttributeArray(attr);
    
        // texture1
        //直接生成绑定一个2d纹理, 并生成多级纹理MipMaps
        texture1 = new QOpenGLTexture(QImage(":/image/container.jpg"),QOpenGLTexture::GenerateMipMaps);
        if(!texture1->isCreated()){
            qDebug() << "failed to load texture.";
        }
        texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);// 等于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        // set texture filtering parameters
        texture1->setMinificationFilter(QOpenGLTexture::Linear);   //等价于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        texture1->setMagnificationFilter(QOpenGLTexture::Linear);
    
        // texture2
        //直接生成绑定一个2d纹理, 并生成多级纹理MipMaps
        texture2 = new QOpenGLTexture(QImage(":/image/awesomeface.png").mirrored(true,true),QOpenGLTexture::GenerateMipMaps);
        if(!texture2->isCreated()){
            qDebug() << "failed to load texture.";
        }
        texture2->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);// 等于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        texture2->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        // set texture filtering parameters
        texture2->setMinificationFilter(QOpenGLTexture::Linear);   //等价于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        texture2->setMagnificationFilter(QOpenGLTexture::Linear);
    
        m_program.bind();
        m_program.setUniformValue("texture1",0);
        m_program.setUniformValue("texture2",1);
    
        vbo.release();
    //    remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
    //    ebo.release();
    }
    
    void QtFunWidget::resizeGL(int w, int h)
    {
        glViewport(0,0,w,h);
    }
    
    void QtFunWidget::paintGL()
    {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
    
        // bind textures on corresponding texture units
        glActiveTexture(GL_TEXTURE0);
        texture1->bind();
        glActiveTexture(GL_TEXTURE1);
        texture2->bind();
    
        // create transformations
        QMatrix4x4 transform;
        transform.translate(QVector3D(0.5f, -0.5f, 0.0f));
        transform.rotate(m_timeValue, QVector3D(0.0f, 0.0f, 1.0f));
    
        m_program.bind();
        m_program.setUniformValue("transform", transform);
    
        {// render container
            QOpenGLVertexArrayObject::Binder vaoBind(&vao);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
        }
    
        // create transformations
        QMatrix4x4 transform2;
        transform2.translate(QVector3D(-0.5f, 0.5f, 0.0f));
        float scaleAmount = sin(m_timeValue);
        transform2.scale(QVector3D(scaleAmount, scaleAmount, scaleAmount));
    
        //m_program.bind();
        m_program.setUniformValue("transform", transform2);
    
        {// render container
            QOpenGLVertexArrayObject::Binder vaoBind(&vao);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
        }
    
        texture1->release();
        texture2->release();
        m_program.release();
    }
    两个箱子
    #include "qtfunwidget.h"
    #include <QTimer>
    
    QtFunWidget::QtFunWidget(QWidget *parent)
        : QOpenGLWidget(parent)
        ,vbo(QOpenGLBuffer::VertexBuffer)
        ,ebo(QOpenGLBuffer::IndexBuffer)
    {
        m_timer = new QTimer(this);
        connect(m_timer,&QTimer::timeout,this,[=]{
            m_timeValue += 5;
            update();
        });
        m_timer->start(50);
    }
    
    QtFunWidget::~QtFunWidget()
    {
        /*Prepares for rendering OpenGL content for this widget by making
         * the corresponding context current and binding the framebuffer object in that context.
    
            It is not necessary to call this function in most cases,
            because it is called automatically before invoking paintGL().
        */
        makeCurrent();
        vbo.destroy();
        ebo.destroy();
    
        if(texture1)
            delete texture1;
        if(texture2)
            delete texture2;
    
        doneCurrent();
    }
    
    void QtFunWidget::initializeGL()
    {
        this->initializeOpenGLFunctions();
        int success = m_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/textures.vert");
        if (!success) {
            qDebug() << "program addShaderFromSourceFile Failed." << m_program.log();
            return;
        }
        success = m_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/textures.frag");
        if (!success) {
            qDebug() << "program addShaderFromSourceFile Failed." << m_program.log();
            return;
        }
        success = m_program.link();
        if (!success) {
            qDebug() << "program link Failed." << m_program.log();
        }
    
        // VAO VBO VEO data
        float vertices[] = {
            // positions          // colors           // texture coords
             0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
             0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
        };
        unsigned int indices[] = {  // note that we start from 0!
            0, 1, 3,  // first Triangle
            1, 2, 3   // second Triangle
        };
    
        QOpenGLVertexArrayObject::Binder vaobind(&vao);
    
        vbo.create();
        vbo.bind();
        vbo.allocate(vertices,sizeof(vertices));
    
        ebo.create();
        ebo.bind();
        ebo.allocate(indices,sizeof(indices));
    
        // position attribute
        int attr = -1;
        attr = m_program.attributeLocation("aPos");
        m_program.setAttributeBuffer(attr,GL_FLOAT,0,3,8*sizeof(GL_FLOAT));
        m_program.enableAttributeArray(attr);
        // color attribute
        attr = m_program.attributeLocation("aColor");
        m_program.setAttributeBuffer(attr,GL_FLOAT,3*sizeof(GL_FLOAT),3,8*sizeof(GL_FLOAT));
        m_program.enableAttributeArray(attr);
    
       // texture coord attribute
        attr = m_program.attributeLocation("aTexCoord");
        m_program.setAttributeBuffer(attr,GL_FLOAT,6*sizeof(GL_FLOAT),2,8*sizeof(GL_FLOAT));
        m_program.enableAttributeArray(attr);
    
        // texture1
        //直接生成绑定一个2d纹理, 并生成多级纹理MipMaps
        texture1 = new QOpenGLTexture(QImage(":/image/container.jpg"),QOpenGLTexture::GenerateMipMaps);
        if(!texture1->isCreated()){
            qDebug() << "failed to load texture.";
        }
        texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);// 等于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        // set texture filtering parameters
        texture1->setMinificationFilter(QOpenGLTexture::Linear);   //等价于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        texture1->setMagnificationFilter(QOpenGLTexture::Linear);
    
        // texture2
        //直接生成绑定一个2d纹理, 并生成多级纹理MipMaps
        texture2 = new QOpenGLTexture(QImage(":/image/awesomeface.png").mirrored(true,true),QOpenGLTexture::GenerateMipMaps);
        if(!texture2->isCreated()){
            qDebug() << "failed to load texture.";
        }
        texture2->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);// 等于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        texture2->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);//    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        // set texture filtering parameters
        texture2->setMinificationFilter(QOpenGLTexture::Linear);   //等价于glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        texture2->setMagnificationFilter(QOpenGLTexture::Linear);
    
        m_program.bind();
        m_program.setUniformValue("texture1",0);
        m_program.setUniformValue("texture2",1);
    
        vbo.release();
    //    remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
    //    ebo.release();
    }
    
    void QtFunWidget::resizeGL(int w, int h)
    {
        glViewport(0,0,w,h);
    }
    
    void QtFunWidget::paintGL()
    {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
    
        // bind textures on corresponding texture units
        glActiveTexture(GL_TEXTURE0);
        texture1->bind();
        glActiveTexture(GL_TEXTURE1);
        texture2->bind();
    
        // create transformations
        QMatrix4x4 transform;
        transform.translate(QVector3D(0.5f, -0.5f, 0.0f));
        transform.rotate(m_timeValue, QVector3D(0.0f, 0.0f, 1.0f));
    
        m_program.bind();
        m_program.setUniformValue("transform", transform);
    
        {// render container
            QOpenGLVertexArrayObject::Binder vaoBind(&vao);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
        }
    
        texture1->release();
        texture2->release();
        m_program.release();
    }
    .cpp
    #ifndef QTFUNWIDGET_H
    #define QTFUNWIDGET_H
    
    #include <QWidget>
    #include <QOpenGLWidget>
    #include <QOpenGLShader>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLFunctions>
    #include <QOpenGLVertexArrayObject>
    #include <QOpenGLBuffer>
    #include <QOpenGLTexture>
    
    class QtFunWidget : public QOpenGLWidget,protected QOpenGLFunctions
    {
        Q_OBJECT
    
    public:
        QtFunWidget(QWidget *parent = 0);
        ~QtFunWidget() Q_DECL_OVERRIDE;
    protected:
        virtual void initializeGL() Q_DECL_OVERRIDE;
        virtual void resizeGL(int w,int h) Q_DECL_OVERRIDE;
        virtual void paintGL() Q_DECL_OVERRIDE;
    private:
        QOpenGLShaderProgram m_program;
        QOpenGLBuffer vbo,ebo;
        QOpenGLVertexArrayObject vao;
        QOpenGLTexture *texture1{nullptr};
        QOpenGLTexture *texture2{nullptr};
    
        QTimer *m_timer{nullptr};
        int m_timeValue{0};
    };
    
    #endif // QTFUNWIDGET_H
    .hpp
  • 相关阅读:
    从zk监控canal-client消费延迟情况
    python面向对象——类的参数
    python面向对象——类的继承
    python并发——进程间同步和通信(二)
    python并发——线程池与进程池(转)
    python从指定目录排除部分子目录——用于删除目录
    python并发统计s3目录大小
    Java对象的序列化和反序列化
    多态、抽象类和接口
    Java输入输出流
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/12073460.html
Copyright © 2020-2023  润新知