QT+Opengl (1):渲染一个三角形

我这是使用QT写的

目录

效果

[1 核心源码](#1 核心源码)

[1.1 MyOpenGL头文件](#1.1 MyOpenGL头文件)

[1.2 MyOpenGL实现文件](#1.2 MyOpenGL实现文件)

[1.3 cmake文件](#1.3 cmake文件)

[2 QOpenGLWidget提升为自定义MyOpenglWidget](#2 QOpenGLWidget提升为自定义MyOpenglWidget)

[2.1 提升为自定义的MyOpenGL](#2.1 提升为自定义的MyOpenGL)

[2.2 设置setCentralWidget为MyOpenGL](#2.2 设置setCentralWidget为MyOpenGL)


效果

1 核心源码

1.1 MyOpenGL头文件

cpp 复制代码
#ifndef MYOPENGL_H
#define MYOPENGL_H

// 继承字OpenGLWidget
#include <QOpenGLWidget>
// 使用3.3的版本
#include <QOpenGLFunctions_3_3_Core>
// Qt的shaderProgram对象
#include <QOpenGLShaderProgram>

class MyOpenGL : public QOpenGLWidget,protected QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    explicit MyOpenGL(QWidget* parent = nullptr);
    ~MyOpenGL();
protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();
private:
    unsigned int VAO,VBO,EBO;

    // shader程序对象
    QOpenGLShaderProgram* m_shaderProgram;
    GLuint native_shaderProgram;

    void setupGeometry();
    void initNativeShader();
    void initQtShader();
};

#endif // MYOPENGL_H

1.2 MyOpenGL实现文件

cpp 复制代码
#include "myopengl.h"

MyOpenGL::MyOpenGL(QWidget *parent)
    :QOpenGLWidget(parent)
{

    qDebug()<< "inited";

}

MyOpenGL::~MyOpenGL()
{
    // 切换到当前widget的上下文
    makeCurrent();

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1,&VBO);

    glDeleteBuffers(1, &EBO);

    glDeleteProgram(native_shaderProgram);
    doneCurrent();

}

void MyOpenGL::initializeGL()
{
    // 获取OpenGL的函数指针
    this->initializeOpenGLFunctions();

    // 1 opengl原生方法初始化Shader程序
    initNativeShader();
    // initQtShader();

    // 2 初始化物体信息
    setupGeometry();
}

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

}

void MyOpenGL::setupGeometry(){

    float vertices[24] = {
        // 位置            颜色
        0.0f,  0.5f, 0.0f,  1.0f,0.0f,0.0f,   //上 红
        -0.5f, -0.0f, 0.0f,  0.0f,1.0f,0.0f,   //左下 绿
        0.5f, 0.0f, 0.0f,  0.0f,0.0f,1.0f,    //右下 蓝
        0.0f, -0.5f, 0.0f,  1.0f,1.0f,0.0f    //右下 橙色
    };

    // 每3个点读一次
    unsigned int indexes[6] = {0,1,2,1,2,3};


    glGenVertexArrays(1,&VAO);

    glGenBuffers(1, &VBO);
    glGenBuffers(1, &EBO);

    // 激活定点数组配置,开始记录定点属性
    glBindVertexArray(VAO);

    // 绑定VBO 包含数据
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);


    // EBO 缓冲
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indexes),indexes,GL_STATIC_DRAW);


    // 参数1:索引
    // 参数2:几个数据
    // 参数3:数据类型
    // 参数4:是否归一化,如果是0-255需要转为0-1
    // 参数5:步长
    // 参数6:偏移量
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,6 * sizeof(float),(void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // 解绑VBO
    glBindBuffer(GL_ARRAY_BUFFER,0);
    // 解绑VAO 不需要解绑EBO,当VAO解绑时自动解绑
    glBindVertexArray(0);

}

void MyOpenGL::paintGL()
{
    // 只在200*200的范围内绘制
    glViewport(0,0,200,200);
    // 清理屏幕
    glClearColor(0.1,0.2,0.3,1);
    glClear(GL_COLOR_BUFFER_BIT);

    // 使用shader程序
    glUseProgram(native_shaderProgram); //原生写法
    // m_shaderProgram->bind(); // qt 的写法

    glBindVertexArray(VAO);

    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,nullptr);

    glBindVertexArray(0);
    glUseProgram(0);

}


void MyOpenGL::initNativeShader(){

    const char* vSrc = R"(
        #version 330 core
        layout(location=0) in vec3 aPos;
        layout(location=1) in vec3 aColor;
        out vec3 ourColor;
        void main(){
            gl_Position = vec4(aPos,1.0);
            ourColor = aColor;
        }
        )";

    const char* fSrc = R"(
        #version 330 core
        in vec3 ourColor;
        out vec4 FragColor;
        void main(){
            FragColor = vec4(ourColor,1.0);
        }
        )";

    // 创建shader,加载源码,编译
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader,1,&vSrc,nullptr);
    glCompileShader(vertexShader);

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader,1,&fSrc,nullptr);
    glCompileShader(fragmentShader);

    // 创建程序,绑定shader,链接为GPU程序
    native_shaderProgram = glCreateProgram();
    glAttachShader(native_shaderProgram,vertexShader);
    glAttachShader(native_shaderProgram,fragmentShader);

    glLinkProgram(native_shaderProgram);

    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);


}

void MyOpenGL::initQtShader()
{

    const char* vSrc = R"(
        #version 330 core
        layout(location=0) in vec3 aPos;
        layout(location=1) in vec3 aColor;
        out vec3 ourColor;
        void main(){
            gl_Position = vec4(aPos,1.0);
            ourColor = aColor;
        }
        )";

    const char* fSrc = R"(
        #version 330 core
        in vec3 ourColor;
        out vec4 FragColor;
        void main(){
            FragColor = vec4(ourColor,1.0);
        }
        )";


    m_shaderProgram = new QOpenGLShaderProgram();
    QOpenGLShader * vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
    vertexShader->compileSourceCode(vSrc);

    QOpenGLShader * fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment);
    fragmentShader->compileSourceCode(fSrc);

    // 对应原生的attach
    m_shaderProgram->addShader(vertexShader);
    m_shaderProgram->addShader(fragmentShader);

    // 将编译完成的着色器目标对象进行链接,生成完整GPU着色器程序
    m_shaderProgram->link();

}

1.3 cmake文件

cpp 复制代码
cmake_minimum_required(VERSION 3.19)
project(python LANGUAGES CXX)

find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets)
# 查找组件
find_package(Qt6 REQUIRED COMPONENTS OpenGLWidgets)
qt_standard_project_setup()

qt_add_executable(python
    WIN32 MACOSX_BUNDLE
    main.cpp
    mainwindow.cpp
    mainwindow.h
    mainwindow.ui
    resources.qrc
    myopengl.h myopengl.cpp

)

target_link_libraries(python
    PRIVATE
        Qt::Core
        Qt::Widgets
)

# 自定义函数的头文件查找地址
target_include_directories(python PRIVATE ${CMAKE_SOURCE_DIR})
# 链接库
target_link_libraries(python PRIVATE Qt6::OpenGLWidgets)

install(TARGETS python
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

qt_generate_deploy_app_script(
    TARGET python
    OUTPUT_SCRIPT deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

2 QOpenGLWidget提升为自定义MyOpenglWidget

2.1 提升为自定义的MyOpenGL

2.2 设置setCentralWidget为MyOpenGL

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

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

MainWindow::~MainWindow()
{
    delete ui;
}
相关推荐
A-刘晨阳2 小时前
金仓时序数据库:以高效压缩、快速写入与时序优化,破解工业海量数据管理难题
数据库·时序数据库
2603_965148112 小时前
终极清单:构建自动化选品比价系统的所有组件与资源
大数据·运维·数据库·数据挖掘·自动化
打工仔折腾 AI2 小时前
SQL 编辑器不是高级记事本:KStudio 与 KSQL Developer 的建表与增删改查手法
数据库·人工智能·后端·python·sql·编辑器·ai agent 实战
CNSSIRD数据库2 小时前
中国省地县乡四级行政建制及区划代码-2025年版
大数据·数据库·数据分析·论文笔记
for_ever_love__2 小时前
LangGraph Checkpointer:持久化、断点续跑与多轮记忆
服务器·数据库·学习·持久化·langgraph·checkpointer·断点续跑
Data analyse4562 小时前
用户路径SQL按会话起止时间聚合的方法
大数据·服务器·前端·数据库·人工智能·sql·数据分析
Lhan.zzZ2 小时前
Linux + Qt/QML:解决 QtQuick.VirtualKeyboard.Plugins 模块加载失败与环境变量配置
linux·数据库·qt
大圣编蚕2 小时前
Redis 为什么快?现在还是单线程吗?
数据库·redis·缓存
鸥梨菌Honevid2 小时前
UVM 面试高频:uvm_test_top 与 uvm_config_db 路径机制全解析
数据库·面试·职场和发展