学习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) 效果(待补充)
来源:CSDN
作者:Hit_HSW
链接:https://blog.csdn.net/hit1524468/article/details/104864699