矩阵转换

原文: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
posted @ 2019-12-20 15:42  狂奔~  阅读(458)  评论(0编辑  收藏  举报