QT OpenGL基础学习——旋转立方体

第一个QOpenGLWidget程序

在这里插入图片描述

学习内容:

1.创建OpenGL窗口;
2.创建并编写着色器程序;
3.为着色器程序装配顶点数据;
4.启动渲染管线进行绘图。

这部分知识我在该博主这里学习的
这部分基础详细讲解我就不赘述也不搬运了,这里我给出学习了这部分基础后自己写出的代码;大家可以学习完基础看看我的代码,我初期学习都加了注释

代码:

main.cpp
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QTimer>

//创建opengl窗口只需新建类继承于QOpenGLWidegt,再实现QOpenGL提供的三个虚函数,就可以完成opengl窗口的创建。
//需要在类中使用opengl函数,只需要使类继承于QOpenGLExtraFunctions
class Widget : public QOpenGLWidget,protected QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    //initializeGL()—建立OpenGL的资源和状态。在第一次调用resizeGL()或paintGL()之前调用一次
   //resizeGL()—设置OpenGL视口,投影等。每当调整Widget的大小时(第一次显示窗口Widget时会调用它,因为所有新创建Widget都会自动获得调整大小的事件)。
   //paintGL()—渲染OpenGL场景,需要更新Widget时就会调用。
    virtual void initializeGL() override;
    virtual void paintGL() override;
    virtual void resizeGL(int w,int h) override;

private:
    QVector<float> vertices;//声明数组
    QOpenGLShaderProgram shaderprogram;//声明着色器程序
    QOpenGLVertexArrayObject VAO;//声明VAO顶点数组对象
    QOpenGLBuffer VBO;//声明VBO数组缓冲对象

};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QtMath>
#include <QTime>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
    ,VBO(QOpenGLBuffer::VertexBuffer)
{

    QSurfaceFormat format;
    format.setAlphaBufferSize(24);  //设置alpha缓冲大小
    format.setVersion(3,3);         //设置版本号
    format.setSamples(10);          //设置重采样次数,用于反走样

    this->setFormat(format);

    vertices={
        // 位置              // 颜色
         0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
        -0.5f,  0.5f, 0.0f,  0.0f, 1.0f, 1.0f,   // 左下
         0.5f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f,   // 右上
    };

}
Widget::~Widget()
{
    makeCurrent();
}

void Widget::initializeGL()
{
    this->initializeOpenGLFunctions();//初始化opengl函数
    shaderprogram.create();//生成着色器程序
    if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/gl.vert")){
        qDebug()<<"ERROR:"<<shaderprogram.log();    //如果编译出错,打印报错信息
    }
    if(!shaderprogram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/gl.frag")){
        qDebug()<<"ERROR:"<<shaderprogram.log();    //如果编译出错,打印报错信息
    }

    //将添加到此程序的着色器与addshader链接在一起
     if(!shaderprogram.link()){
         qDebug()<<"ERROR:"<<shaderprogram.log();    //如果链接出错,打印报错信息
     }

    VAO.create();// 创建一个VAO对象,OpenGL会给它(顶点数组缓存对象)分配一个id
    VAO.bind();//将RC中的当前顶点数组缓存对象Id设置为VAO的id
    VBO.create();
    VBO.bind();
    VBO.allocate(vertices.data(),sizeof(float)*vertices.size());//将顶点数据分配到VBO中,第一个参数为数据指针,第二个参数为数据的字节长度

    shaderprogram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 6);
    shaderprogram.enableAttributeArray("aPos");
    shaderprogram.setAttributeBuffer("aColor", GL_FLOAT,sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 6);
    shaderprogram.enableAttributeArray("aColor");

    VAO.release();//释放
    VBO.release();

}

void Widget::paintGL()
{
    this->glClearColor(0.1f,0.5f,0.7f,1.0f);//设置清屏颜色
    this->glClear(GL_COLOR_BUFFER_BIT);//清空颜色缓冲区

    shaderprogram.bind();
    //将此着色器程序绑定到活动的qopenglcontext,并使其成为当前着色器程序。任何先前绑定的着色器程序都将被释放
    //成功绑定返回ture,反之,返回false.
    QOpenGLVertexArrayObject::Binder bind(&VAO);//绑定VAO
    this->glDrawArrays(GL_POLYGON,0,4);
}

void Widget::resizeGL(int w,int h)
{
    this->glViewport(0,0,w,h);
}

gl.vert
#version 330 core
layout (location = 0) in vec3 aPos;   // 位置变量的属性位置值为 0
layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1

out vec3 ourColor; // 向片段着色器输出一个颜色

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor; // 将ourColor设置为我们从顶点数据那里得到的输入颜色
}
gl.frag
#version 330 core
out vec4 FragColor;
in vec3 ourColor;

void main()
{
    FragColor = vec4(ourColor, 1.0);
}
运行即可得到如下结果

在这里插入图片描述

旋转立方体

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603160831983.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NjYzNjA2Mw==,size_16,color_FFFFFF,t_70![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603161320266.gif

主要内容

基础讲解在该播主这里

代码

main.cpp
#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QTimer>
#include <QTime>
#include <QtMath>
#include <QVector>

class Widget : public QOpenGLWidget,public QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int w,int h) override;
    virtual void paintGL() override;
private:
    QVector<float> vertices;
    QOpenGLShaderProgram shaderProgram;
    QOpenGLBuffer VBO;
    QOpenGLVertexArrayObject VAO;
    QOpenGLTexture texture;
    QOpenGLTexture texture1;
    QTimer timer;
};

#endif // WIDGET_H

widget.cpp
#include "widget.h"
#include <QtMath>

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
    , VBO(QOpenGLBuffer::VertexBuffer)
    , texture(QOpenGLTexture::Target2D)
    , texture1(QOpenGLTexture::Target2D)
{
    vertices = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
0.5f,  0.5f, -0.5f,  1.0f, 1.0f,0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
       -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
    timer.setInterval(18);
    connect(&timer,&QTimer::timeout,this,static_cast<void (Widget::*)()>(&Widget::update));
    timer.start();
}

Widget::~Widget()
{
}

void Widget::initializeGL()
{
    this->initializeOpenGLFunctions();        //初始化opengl函数
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/triangle.vert")){     //添加并编译顶点着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果编译出错,打印报错信息
    }
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/triangle.frag")){   //添加并编译片段着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果编译出错,打印报错信息
    }
    if(!shaderProgram.link()){                      //链接着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果链接出错,打印报错信息
    }

    QOpenGLVertexArrayObject::Binder{&VAO};

    VBO.create();       //生成VBO对象
    VBO.bind();         //将VBO绑定到当前的顶点缓冲对象(QOpenGLBuffer::VertexBuffer)中

    //将顶点数据分配到VBO中,第一个参数为数据指针,第二个参数为数据的字节长度
    VBO.allocate(vertices.data(),sizeof(float)*vertices.size());

    texture.create();
    texture.setData(QImage(":/opengl.jpg").mirrored());
    texture.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);
    texture.setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::Repeat);
    texture.setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::Repeat);

    texture1.create();
    texture1.setData(QImage(":/sea.jpg").mirrored());
    texture1.setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);
    texture1.setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::Repeat);
    texture1.setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::Repeat);

    //设置顶点解析格式,并启用顶点
    shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 5);
    shaderProgram.enableAttributeArray("aPos");
    shaderProgram.setAttributeBuffer("aTexCoord", GL_FLOAT,sizeof(GLfloat) * 3, 2, sizeof(GLfloat) * 5);
    shaderProgram.enableAttributeArray("aTexCoord");

     this->glEnable(GL_DEPTH_TEST);
}

void Widget::resizeGL(int w, int h)
{
    this->glViewport(0,0,w,h);                //定义视口区域
}

void Widget::paintGL()
{
    this->glClearColor(0.1f,0.5f,0.7f,1.0f);  //设置清屏颜色
    this->glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);       //清除颜色缓存

    shaderProgram.bind();                     //使用shaderProgram着色程序
    {

        float time=QTime::currentTime().msecsSinceStartOfDay()/1000.0;
        QMatrix4x4 model;//位移旋转矩阵
        model.rotate(180*time,QVector3D(1.0f,0.5f,0.3f));
        shaderProgram.setUniformValue("model",model);

        QMatrix4x4 view;//观察矩阵
        view.translate(0.0f,0.0f,-3.0f);
        shaderProgram.setUniformValue("view",view);

        QMatrix4x4 projection;//投影矩阵
        projection.perspective(45.0f,width()/(float)height(),0.1f,100.0f);
        shaderProgram.setUniformValue("projection",projection);

        texture.bind(0);                                    //将texture绑定到纹理单元0
        shaderProgram.setUniformValue("ourTexture",0);      //让ourTexture从纹理单元0中获取纹理数据

        texture1.bind(1);                                    //将texture绑定到纹理单元1
        shaderProgram.setUniformValue("ourTexture1",1);      //让ourTexture从纹理单元1中获取纹理数据

        QOpenGLVertexArrayObject::Binder{&VAO};
        this->glDrawArrays(GL_TRIANGLES, 0, 36);     //使用以0开始,长度为36的顶点数据来绘制三角形

    }
}

triangle.vert
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    // 注意乘法要从右向左读
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    TexCoord = aTexCoord;
}
triangle.frag
#version 330 core
out vec4 FragColor;

in vec2 TexCoord;

uniform sampler2D ourTexture;
uniform sampler2D ourTexture1;
void main()
{
    FragColor = mix(texture(ourTexture, TexCoord), texture(ourTexture1, TexCoord), 0.4);
}
结果

运行即可得到旋转的立方体

光照

光照学习借鉴

到此,基础学习完成,后期文章进入正题

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值