【Qt+OpenGL】绘制旋转正方体

说明:如下的代码是参考: https://blog.csdn.net/github_18974657/article/details/122533506

感觉他写的很好,我这些代码是为了方便自己看的。

.h文件

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>

namespace Ui {
class Widget;
}

class Widget : public QOpenGLWidget, public QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();


    void timerEvent(QTimerEvent *event);

private:
    Ui::Widget *ui;

    QOpenGLVertexArrayObject m_vao;
    QOpenGLBuffer m_vbo;

    QOpenGLShaderProgram *m_program = nullptr;
    QOpenGLTexture *m_texture  = nullptr;

    QMatrix4x4 m_projection;
    QMatrix4x4 m_view;
    QMatrix4x4 m_model;

    int m_angle;

};

#endif // WIDGET_H

.cpp文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

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

    auto newFormat = this->format();
    newFormat.setSamples(16);
    this->setFormat(newFormat);

    startTimer(1000 / 60);
}

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

void Widget::initializeGL()
{
    //qDebug() << "initializeGL";
    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);
    glClearColor(0, 0.5, 0.7, 1);

    m_vao.create();
    m_vbo.create();

    m_program = new QOpenGLShaderProgram();
    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vertex_shader.glsl");
    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fragment_shader.glsl");
    m_program->link();

    //m_texture = new QOpenGLTexture(QImage(":/image/2.png").mirrored());
    m_texture = new QOpenGLTexture(QImage(":/image/2.png"));
    //m_texture = new QOpenGLTexture(QImage(":/image/1.jpeg"));


    // 顶点缓存中前三个是顶点坐标, 后两个是纹理坐标, 一个顶点由5个float值组成
    float vertex[] = {
    //顶点						纹理
    // 1
        -1,  1,  1,		0.50, 0.25,	// 左上
        -1, -1,  1,		0.50, 0.50,	// 左下
         1, -1,  1,		0.75, 0.50,	// 右下
         1,  1,  1,		0.75, 0.25,  // 右上
    // 6
         1,  1, -1,		0.00, 0.25,	// 左上
         1, -1, -1,		0.00, 0.50,	// 左下
        -1, -1, -1,		0.25, 0.50,	// 右下
        -1,  1, -1,		0.25, 0.25,	// 右上
    // 2
         1,	 1,  1,		0.75, 0.25,  // 左上
         1,	-1,  1,		0.75, 0.50,	// 左下
         1,	-1, -1,		1.00, 0.50,	// 右下
         1,	 1, -1,		1.00, 0.25,	// 右上
    // 5
        -1,  1, -1,		0.25, 0.25,	// 左上
        -1, -1, -1,		0.25, 0.50,	// 左下
        -1, -1,  1,		0.50, 0.50,	// 右下
        -1,  1,  1,		0.50, 0.25,	// 右上
    // 3
        -1,  1, -1,		0.00, 0.00,	// 左上
        -1,  1,  1,		0.00, 0.25,	// 左下
         1,  1,  1,		0.25, 0.25,  // 右下
         1,  1, -1,		0.25, 0.00,	// 右上
    // 4
        -1, -1,  1,		0.00, 0.50,  // 左上
        -1, -1, -1,		0.00, 0.75,	// 左下
         1, -1, -1,		0.25, 0.75,	// 右下
         1, -1,  1,		0.25, 0.50,	// 右上
    };

    m_vao.bind();
    m_vbo.bind();

    m_vbo.allocate(vertex, sizeof(vertex));

    m_program->bind();
//    m_program->setAttributeBuffer("vPos", GL_FLOAT, 0, 3, 0);
//    m_program->enableAttributeArray("vPos");

    // 绑定顶点坐标信息, 从0 * sizeof(float)字节开始读取3个float, 因为一个顶点有5个float数据, 所以下一个数据需要偏移5 * sizeof(float)个字节
    m_program->setAttributeBuffer("vPos", GL_FLOAT, 0 * sizeof(float), 3, 5 * sizeof(float));
    m_program->enableAttributeArray("vPos");
    // 绑定纹理坐标信息, 从3 * sizeof(float)字节开始读取2个float, 因为一个顶点有5个float数据, 所以下一个数据需要偏移5 * sizeof(float)个字节
    m_program->setAttributeBuffer("vTexture", GL_FLOAT, 3 * sizeof(float), 2, 5 * sizeof(float));
    m_program->enableAttributeArray("vTexture");


    m_program->release();
    m_vao.release();
}

void Widget::resizeGL(int w, int h)
{
    //qDebug() << "resizeGL";

    m_projection.setToIdentity();
    m_projection.perspective(60, (float)w / h, 0.001, 1000);

    m_view.setToIdentity();
    m_view.lookAt(QVector3D(3, 3, 3), QVector3D(0, 0, 0), QVector3D(0, 1, 0));

    m_model.setToIdentity();
    m_model.rotate(m_angle, 0, 0, 1);

}

void Widget::paintGL()
{
    //qDebug() << "paintGL";

    glEnable(GL_CULL_FACE);

    m_texture->bind();
    m_vao.bind();
    m_program->bind();

    // 绑定变换矩阵
    m_program->setUniformValue("projection", m_projection);
    m_program->setUniformValue("view", m_view);
    m_program->setUniformValue("model", m_model);

    //glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    // 绘制
    for (int i = 0; i < 6; ++i)
    {
        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
    }

    m_vao.release();
    m_program->release();
    m_texture->release();
}

void Widget::timerEvent(QTimerEvent *event)
{
    m_angle += 1;
    if (m_angle >= 360)
        m_angle = 0;
    m_model.setToIdentity();
    m_model.rotate(m_angle, 0, 1, 0);
    repaint();
}

fragment_shader.glsl文件 如下:

cpp 复制代码
#version 330 core
in vec2 oTexture;
uniform sampler2D uTexture;
void main()
{
    gl_FragColor = texture2D(uTexture, oTexture);
}

vertex_shader.glsl 文件如下:

cpp 复制代码
#version 330 core
in vec3 vPos;
in vec2 vTexture;
out vec2 oTexture;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
void main()
{
    gl_Position = projection * view * model * vec4(vPos, 1.0);
    oTexture = vTexture;
}

运行结果:

需要使用到的图像:

相关推荐
C++ 老炮儿的技术栈19 分钟前
main函数之后的调用
c语言·c++·人工智能·qt·mfc·c
知识分享小能手1 小时前
C++ 学习教程,从入门到精通,C++ 友元、异常和其他特性 — 详细知识点(15)
开发语言·c++·学习
朝朝辞暮i1 小时前
C++ 第 26 课:对象、指针与 ->
java·开发语言·c++
2601_962885722 小时前
如何用 Python 做股价历史分位选股?(筛出处于历史低位的股票)
开发语言·python
殷色玫瑰2 小时前
C++入门基础复习:从命名空间到引用与nullptr,一篇重新捡回C++基础
java·开发语言·c++
(Charon)3 小时前
【C++面试】手写线程池:任务队列、工作线程与优雅退出
开发语言·c++
言乐63 小时前
Python概括后端原理
开发语言·python·django·virtualenv·pygame
@大迁世界3 小时前
JEV RAG:更高效的 RAG 系统解决方案?
开发语言·rust
朝朝辞暮i4 小时前
C++ 第一阶段总结:从零基础到 ROS2 前置语法
开发语言·c++·算法
2601_962885724 小时前
如何用 Python 回测定投策略(定期定额 DCA)?(和一次性买入对比)
开发语言·人工智能·python