顶点着色器
#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);
}
片段着色器
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}
头文件
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
class CoreFunctionWidget : public QOpenGLWidget
, protected /*QOpenGLExtraFunctions*/QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
explicit CoreFunctionWidget(QWidget *parent = nullptr);
~CoreFunctionWidget();
int velocity = 0;
double xP=0;
double yP=0;
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
private:
QOpenGLShaderProgram shaderProgram;
QTimer* m_pTimer = nullptr;
int m_nTimeValue = 0;
};
cpp文件
#include "CoreFunctionWidget.h"
#include <QDebug>
#include <QTimer>
static GLuint VBO, VAO, EBO, texture1, texture2;
CoreFunctionWidget::CoreFunctionWidget(QWidget *parent) : QOpenGLWidget(parent)
{
m_pTimer = new QTimer(this);
connect(m_pTimer, &QTimer::timeout, this, [=] {
m_nTimeValue += velocity;
update();
});
m_pTimer->start(50);//每隔50毫秒触发一次m_nTimeValue+=velocity
}
CoreFunctionWidget::~CoreFunctionWidget()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
}
void CoreFunctionWidget::initializeGL() {
this->initializeOpenGLFunctions();
bool success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "textures.vert");
if (!success) {
qDebug() << "shaderProgram addShaderFromSourceFile failed!" << shaderProgram.log();
return;
}
success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "textures.frag");
if (!success) {
qDebug() << "shaderProgram addShaderFromSourceFile failed!" << shaderProgram.log();
return;
}
success = shaderProgram.link();
if (!success) {
qDebug() << "shaderProgram link failed!" << shaderProgram.log();
}
//VAO,VBO 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);
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 coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
QImage img1 = QImage("container.jpg").convertToFormat(QImage::Format_RGB888);
if (!img1.isNull()) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img1.width(), img1.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, img1.bits());
glGenerateMipmap(GL_TEXTURE_2D);
}
glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
QImage img2 = QImage("awesomeface.png").convertToFormat(QImage::Format_RGBA8888).mirrored(true, true);
if (!img2.isNull()) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img2.width(), img2.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img2.bits());
glGenerateMipmap(GL_TEXTURE_2D);
}
shaderProgram.bind(); //操作着色器程序的时候使用
glUniform1i(shaderProgram.uniformLocation("texture1"), 0);
glUniform1i(shaderProgram.uniformLocation("texture2"), 1);
shaderProgram.release();
}
void CoreFunctionWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
}
void CoreFunctionWidget::paintGL() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2);
//移动
QMatrix4x4 transform;
transform.translate(QVector3D(xP, yP, 0.0f));//往右下角移动
transform.rotate(m_nTimeValue, QVector3D(0.0f, 0.0f, 1.0f));//绕着z轴旋转
shaderProgram.bind();
int transformLoc = shaderProgram.uniformLocation("transform");
/*
location : uniform的位置。
count : 需要加载数据的数组元素的数量或者需要修改的矩阵的数量。
transpose : 指明矩阵是列优先(column major)矩阵(GL_FALSE)还是行优先(row major)矩阵(GL_TRUE)。
value : 指向由count个元素的数组的指针。
*/
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, transform.data());
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,0);
shaderProgram.release();
}
qt控制类
#pragma once
#include <QtWidgets/QWidget>
#include "ui_opengl_04.h"
class opengl_04 : public QWidget
{
Q_OBJECT
public:
opengl_04(QWidget *parent = Q_NULLPTR);
private:
Ui::opengl_04Class* ui;
};
opengl_04::opengl_04(QWidget *parent)
: QWidget(parent)
{
ui = new Ui::opengl_04Class;
ui->setupUi(this);
CoreFunctionWidget*w = new CoreFunctionWidget;
connect(ui->pushButton, &QPushButton::clicked, [=]() {
if (ui->lineEdit->text().isEmpty())return;
w->velocity=ui->lineEdit->text().toInt();
w->xP = ui->lineEdit_2->text().toDouble();
w->yP = ui->lineEdit_3->text().toDouble();
});
ui->gridLayout->addWidget(w);
}
效果如图