顶点着色器
#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); }