QT学习OpenGL序列-HelloTransformations

坚强是说给别人听的谎言 提交于 2020-03-17 04:04:24

学习OpenGL变换

(1) 头文件

#ifndef COPENGLWIDGETHELLOTRANSFORMATIONS_H
#define COPENGLWIDGETHELLOTRANSFORMATIONS_H

/*
 * 控件名称:Hello Transformations
 *
 *
 * 注意:STD C++ Version >= C++11
 *
 * Author: hsw
 *
*/
#include <QPainter>
#include <QPaintEngine>
#include <QKeyEvent>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLWidget>          // OpenGLWidget
#include <QOpenGLFunctions>       // OpenGL函数
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QMatrix4x4>

class COpenGLWidgetHelloTransformations : public QOpenGLWidget, public QOpenGLFunctions
{
public:
    COpenGLWidgetHelloTransformations(int mode = 0, QWidget* parent = 0);
    ~COpenGLWidgetHelloTransformations();
protected:
    void initializeGL() override;
    void resizeGL(int width, int height) override;
    void paintGL() override;
protected:
    bool eventFilter(QObject *obj, QEvent *event);
signals:
    void m_openglCloseSgn();
private:
    void m_paintRect();
private:
    QWidget*         m_pParent;
private:
    // OpenGL
    QOpenGLShader*        m_pVShader;        // 顶点着色器
    QOpenGLShader*        m_pFShader;        // 片段着色器
    QOpenGLShaderProgram* m_pShaderProgram;  // 管理着色器
    QOpenGLBuffer         m_vBufferObject;   // 顶点的缓冲对象
    QOpenGLTexture*       m_pTexture;        // 纹理对象
    QOpenGLTexture*       m_pTexture2;       //
    int                   m_vertexAttr;      // 顶点位置数据对象
    int                   m_colorAttr;       // 顶点颜色数据对象
    int                   m_textureAttr;     // 纹理数据对象
    int                   m_mode;            // 着色器中传入颜色的模式:= 0, 表示矩形示例, = 1, 表示矩形示例 + 自定义颜色
};

#endif // COPENGLWIDGETHELLOTRANSFORMATIONS_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "copenglwidgethellotransformations.h"
#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    COpenGLWidgetHelloTransformations*  m_pRSOpenGLWidgetHelloTransformations;
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

(2) CPP文件

#include "copenglwidgethellotransformations.h"

COpenGLWidgetHelloTransformations::COpenGLWidgetHelloTransformations(int mode, QWidget *parent) : QOpenGLWidget(parent)
{
    m_pParent = parent;
    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    QSurfaceFormat::setDefaultFormat(format);

    m_mode = mode;
}

COpenGLWidgetHelloTransformations::~COpenGLWidgetHelloTransformations()
{
    // TODO...
    delete m_pTexture;
    delete m_pTexture2;
    delete m_pShaderProgram;
    delete m_pFShader;
    delete m_pVShader;
}

void COpenGLWidgetHelloTransformations::initializeGL()
{
    // 初始化OpenGL的函数
    initializeOpenGLFunctions();

    // 初始化纹理
    m_pTexture  = new QOpenGLTexture(QImage(":/resource/textures/wall.jpg"));
    m_pTexture->setMinificationFilter(QOpenGLTexture::Nearest);
    m_pTexture->setMagnificationFilter(QOpenGLTexture::Linear);
    m_pTexture->setWrapMode(QOpenGLTexture::Repeat);

    m_pTexture2 = new QOpenGLTexture(QImage(":/resource/textures/awesomeface.png"));
    m_pTexture2->setMinificationFilter(QOpenGLTexture::Nearest);
    m_pTexture2->setMagnificationFilter(QOpenGLTexture::Linear);
    m_pTexture2->setWrapMode(QOpenGLTexture::Repeat);

    // 初始化顶点着色器
    m_pVShader = new QOpenGLShader(QOpenGLShader::Vertex);
    QString vShaderSrc;

    vShaderSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("layout (location = 1) in vec3 aColor;\n")
            + QString("layout (location = 2) in vec2 aTexCoord;\n")
            + QString("\n")
            + QString("out vec3 ourColor;\n")
            + QString("out vec2 TexCoord;\n")
            + QString("uniform mat4 transform; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = transform * vec4(aPos, 1.0);\n")
            + QString("    ourColor    = aColor;\n")
            + QString("    TexCoord    = vec2(aTexCoord.x, aTexCoord.y);\n")
            + QString("}\n");


    m_pVShader->compileSourceCode(vShaderSrc);


    // 初始化片段着色器
    m_pFShader = new QOpenGLShader(QOpenGLShader::Fragment);

    //
    // 注意:顶点着色器输出的颜色的变量名称 和 片段着色器输入的颜色的变量名称必须相同
    //
    QString fShaderSrc;
    fShaderSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor;\n")
            + QString("\n")
            + QString("in vec3 ourColor;\n")
            + QString("in vec2 TexCoord;\n")
            + QString("\n")
            + QString("// texture sampler\n")
            + QString("uniform sampler2D texture1;\n")
            + QString("uniform sampler2D texture2;\n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);\n")
            + QString("}\n");


    m_pFShader->compileSourceCode(fShaderSrc);

    // 初始化着色器管理对象
    m_pShaderProgram = new QOpenGLShaderProgram;
    m_pShaderProgram->addShader(m_pVShader);
    m_pShaderProgram->addShader(m_pFShader);

    bool ret = m_pShaderProgram->link();

    if(ret == false)
    {
        qDebug() << "QOpenGLWidget Link Failed !";
        qDebug() << m_pShaderProgram->log();
    }

    m_vertexAttr      = m_pShaderProgram->attributeLocation("aPos");
    m_colorAttr       = m_pShaderProgram->attributeLocation("aColor");
    m_textureAttr     = m_pShaderProgram->attributeLocation("aTexCoord");
}


// 窗口调整
void COpenGLWidgetHelloTransformations::resizeGL(int width, int height)
{
    //
}

// 窗口重新绘制
// 注意:调用update()和paintEvent()时都会自动调用paintGL()
//
void COpenGLWidgetHelloTransformations::paintGL()
{
    QPainter painter;

    painter.begin(this);

    // OpenGL 绘制
    painter.beginNativePainting();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);


    m_pShaderProgram->bind();
    m_paintRect();
    m_pShaderProgram->release();


    glDisable(GL_DEPTH_TEST);

    painter.endNativePainting();

    // QT 绘制
    painter.setPen(Qt::green);
    QString textInfo = QString("按\"ESC\"退出");
    painter.drawText(25, 25, textInfo);

    painter.end();
}

bool COpenGLWidgetHelloTransformations::eventFilter(QObject *obj, QEvent * event)
{
    if(obj == m_pParent)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent != NULL)
        {
            if(keyEvent->type() == QKeyEvent::KeyPress)
            {
                if(keyEvent->key() == Qt::Key_Escape)
                {
                    qDebug() << "Close QOpenGLWidget";
                    QCoreApplication::quit();
                }
            }
        }
    }

    return false;
}

// 绘制矩形
void COpenGLWidgetHelloTransformations::m_paintRect()
{
    if(!m_vBufferObject.isCreated())
    {
        GLfloat vertices[] =
        {
            //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
            0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f    // 左上
        };

        // 顶点缓冲区创建
        m_vBufferObject.create();
        m_vBufferObject.bind();
        m_vBufferObject.allocate(8 * 4 * sizeof(float));
        m_vBufferObject.write(0, vertices, sizeof(vertices));
        m_vBufferObject.release();
    }

    // 传入变换矩阵
    QMatrix4x4 trans;
    trans.translate(0.5f, -0.5f, 0.0f);
    trans.rotate(90, QVector3D(0.0f, 0.0f, 1.0f)); // 输入的角度单位为度:逆时针旋转90度
    trans.scale(0.5, 0.5, 0.5);
    m_pShaderProgram->setUniformValue("transform", trans);

    m_pShaderProgram->setUniformValue("texture1", 0);
    m_pTexture->bind(0);

    m_pShaderProgram->setUniformValue("texture2", 1);
    m_pTexture2->bind(1);


    // 启用顶点
    m_pShaderProgram->enableAttributeArray(m_vertexAttr);
    m_pShaderProgram->enableAttributeArray(m_colorAttr);
    m_pShaderProgram->enableAttributeArray(m_textureAttr);
    // 绑定缓冲区
    m_vBufferObject.bind();
    m_pShaderProgram->setAttributeBuffer(m_vertexAttr , GL_FLOAT, 0                , 3, 8 * sizeof(float));
    m_pShaderProgram->setAttributeBuffer(m_colorAttr  , GL_FLOAT, 3 * sizeof(float), 3, 8 * sizeof(float));
    m_pShaderProgram->setAttributeBuffer(m_textureAttr, GL_FLOAT, 6 * sizeof(float), 2, 8 * sizeof(float));
    m_vBufferObject.release();
    glDrawArrays(GL_QUADS, 0, 4);
    m_pShaderProgram->disableAttributeArray(m_vertexAttr);
    m_pShaderProgram->disableAttributeArray(m_colorAttr);
    m_pShaderProgram->disableAttributeArray(m_textureAttr);

    m_pTexture->release();
    m_pTexture2->release();
}
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowTitle(QString("LearnOpenGLHelloTransformations"));

    m_pRSOpenGLWidgetHelloTransformations = new COpenGLWidgetHelloTransformations(0, this);

    ui->verticalLayout->addWidget(m_pRSOpenGLWidgetHelloTransformations);

    this->installEventFilter(m_pRSOpenGLWidgetHelloTransformations);
}

MainWindow::~MainWindow()
{
    delete ui;
}

(3) 效果(待补充)

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!