zl程序教程

您现在的位置是:首页 >  IT要闻

当前栏目

【OpenGL+Qt 学习】 你好,三角形

2023-04-18 15:22:11 时间

参考

LearnOpenGL CN (learnopengl-cn.github.io)
1-2VAO与VBO_哔哩哔哩_bilibili

定义 OpenGL 窗口类

#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>


class MyGLwidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
public:
    explicit MyGLwidget(QWidget* parent = nullptr);
    ~MyGLwidget();

private:
    unsigned int VAO;///< 顶点数组对象 ID
    unsigned int VBO;///< 顶点缓冲对象 ID
    unsigned int shaderProgram;///< 着色器程序 ID

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

#endif // MYGLWIDGET_H
#include "myglwidget.h"
#include <QDebug>

/// 顶点着色器 GLSL 源代码硬编码
const char *vertexShaderSource = "#version 330 core
"
    "layout (location = 0) in vec3 aPos;
"
    "void main()
"
    "{
"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
"
    "}";

/// 片段着色器 GLSL 源代码硬编码
const char *fragmentShaderSource = "#version 330 core
"
    "out vec4 FragColor;
"
    "void main()
"
    "{
"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
"
    "}
";

/// 三角形顶点数据
float vertices[]={
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};

MyGLwidget::MyGLwidget(QWidget* parent)
    :QOpenGLWidget{parent}
{

}

MyGLwidget::~MyGLwidget()
{
    // 删除没用的对象
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteProgram(shaderProgram);
}

void MyGLwidget::initializeGL()
{
    initializeOpenGLFunctions();

    /* 顶点着色器 *************************************************/
    // 创建顶点着色器
    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);

    // 把着色器源码附加到着色器对象上,然后编译它
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    // 检查着色器程序是否编译成功
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);

    if(!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" 
            << infoLog << Qt::endl;
    }

    /* 片段着色器 *************************************************/
    // 创建片段着色器
    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

    // 把着色器源码附加到着色器对象上,然后编译它
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    // 检查着色器程序是否编译成功
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if(!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED
" 
            << infoLog << Qt::endl;
    }

    /* 着色器程序 *************************************************/
    // 创建一个着色器程序
    shaderProgram = glCreateProgram();

    // 把之前编译的着色器附加到程序对象上
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    // 连接着色器程序
    glLinkProgram(shaderProgram);

    // 检查链接着色器程序是否失败
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(!success)
    {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED
" << infoLog << Qt::endl;
    }

    // 在把着色器对象链接到程序对象以后,记得删除着色器对象,不再需要它们了
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // 创建一个 VAO 对象
    glGenVertexArrays(1, &VAO);
    // 先绑定 VAO 对象
    glBindVertexArray(VAO);

    // 创建一个 VBO 对象

    glGenBuffers(1, &VBO);

    // 绑定 VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

    // 把顶点数组复制到顶点缓冲区中供 OpenGL 使用
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // 设置顶点属性指针——函数告诉OpenGL该如何解析顶点数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);// 启用顶点属性

    // 使用glVertexAttribPointer设置好顶点属性指针后,就可以解绑 VBO 了
    glBindBuffer(GL_ARRAY_BUFFER,0);

    // 只有绑定的状态下才能修改 VAO
    // 解除绑定VAO,以便其他 VAO 调用不会意外修改此VAO
    glBindVertexArray(0);

}

void MyGLwidget::resizeGL(int w, int h)
{

}

void MyGLwidget::paintGL()
{
    // 设置背景色
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderProgram);
    glBindVertexArray(VAO);
    // 第一个参数:打算绘制的OpenGL图元的类型
    // 第二个参数指定了顶点数组的起始索引,我们这里填 0
    // 最后一个参数指定我们打算绘制多少个顶点,这里是 3
    glDrawArrays(GL_TRIANGLES, 0, 3);
}

定义主窗口类

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "myglwidget.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    MyGLwidget* glWidget;

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    glWidget = new MyGLwidget;
    this->setCentralWidget(glWidget);
}

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