嵌入式Linux(SOC带GPU树莓派)无窗口系统下搭建 OpenGL ES + Qt 开发环境,并绘制旋转金字塔

树莓派无窗口系统下搭建 OpenGL ES + Qt 开发环境,并绘制旋转金字塔

1. 安装 OpenGL ES 开发环境

运行以下命令安装所需的 OpenGL ES 开发工具和库:

sudo apt install cmake mesa-utils libegl1-mesa-dev libgles2-mesa-dev libdrm-dev libgbm-dev

2. 安装 Qt 开发环境

安装 Qt 的核心开发库:

sudo apt install -y qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qtdeclarative5-dev qml-module-qtquick2

3. 配置 Qt 使用 EGL 和 GBM(无窗口模式)

使用 EGLFS(EGL Fullscreen)插件

EGLFS 插件可以在没有窗口管理器的环境下直接使用 OpenGL 渲染。

  1. 确认系统支持 EGLFS

    ls /usr/lib/arm-linux-gnueabihf/qt5/plugins/platforms/libqeglfs.so
    

    如果存在 libqeglfs.so,表示系统支持 EGLFS。

  2. 设置环境变量启用 EGLFS

    export QT_QPA_PLATFORM=eglfs
    

    使用 GBM 后台支持:

    export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
    

    或者切换到 Framebuffer(可选):

    export QT_QPA_PLATFORM=linuxfb
    

4. 编写并运行 Qt 项目代码

创建项目目录和文件
mkdir qt-opengl-example
cd qt-opengl-example
  1. main.cpp

    #include <QApplication>
    #include <QMainWindow>
    #include "openglwidget.h"
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
    
        QMainWindow window;
        OpenGLWidget *widget = new OpenGLWidget();
        window.setCentralWidget(widget);
        window.setWindowTitle("OpenGL ES Rotating Pyramid");
        window.resize(800, 600);
        window.show();
    
        return app.exec();
    }
    
  2. openglwidget.h

    #ifndef OPENGLWIDGET_H
    #define OPENGLWIDGET_H
    
    #include <QOpenGLWidget>
    #include <QOpenGLFunctions>
    #include <QTimer>
    
    class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
    {
        Q_OBJECT
    
    public:
        explicit OpenGLWidget(QWidget *parent = nullptr);
        ~OpenGLWidget();
    
    protected:
        void initializeGL() override;
        void resizeGL(int w, int h) override;
        void paintGL() override;
        void timerEvent(QTimerEvent *event) override;
    
    private:
        float rotationAngle;
    };
    
    #endif // OPENGLWIDGET_H
    
  3. openglwidget.cpp

    #include "openglwidget.h"
    #include <QOpenGLShaderProgram>
    #include <QOpenGLBuffer>
    #include <QOpenGLVertexArrayObject>
    #include <QMatrix4x4>
    #include <QtMath>
    
    OpenGLWidget::OpenGLWidget(QWidget *parent) :
        QOpenGLWidget(parent), rotationAngle(0.0f)
    {
        setAutoFillBackground(false);  // 不自动填充背景,交给OpenGL渲染
        startTimer(10);// 启动定时器,每隔0.01秒触发
    }
    
    OpenGLWidget::~OpenGLWidget()
    {
    }
    
    void OpenGLWidget::initializeGL()
    {
        initializeOpenGLFunctions();
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);  // 设置清屏颜色
        glEnable(GL_DEPTH_TEST);  // 启用深度测试
    }
    
    void OpenGLWidget::resizeGL(int w, int h)
    {
        glViewport(0, 0, w, h);
    }
    
    void OpenGLWidget::paintGL()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // 清除颜色和深度缓冲
    
        // 定义金字塔的顶点数据
        GLfloat vertices[] = {
            // 底面
            -0.5f, -0.5f, -0.5f,  // 顶点1
             0.5f, -0.5f, -0.5f,  // 顶点2
             0.5f, -0.5f,  0.5f,  // 顶点3
            -0.5f, -0.5f,  0.5f,  // 顶点4
    
            // 顶面
            0.0f,  0.5f,  0.0f   // 顶点5
        };
    
        // 定义金字塔的索引
        GLuint indices[] = {
            0, 1, 4,  // 底面与顶面连接的三角形
            1, 2, 4,  // 底面与顶面连接的三角形
            2, 3, 4,  // 底面与顶面连接的三角形
            3, 0, 4,  // 底面与顶面连接的三角形
            0, 1, 2,  // 底面三角形
            2, 3, 0   // 底面三角形
        };
    
        // 创建并绑定着色器程序
        QOpenGLShaderProgram program;
        program.addShaderFromSourceCode(QOpenGLShader::Vertex,
            "#version 300 es\n"
            "in vec3 position;\n"
            "uniform mat4 modelViewProjectionMatrix;\n"
            "void main() {\n"
            "   gl_Position = modelViewProjectionMatrix * vec4(position, 1.0);\n"
            "}"
        );
        program.addShaderFromSourceCode(QOpenGLShader::Fragment,
            "#version 300 es\n"
            "precision mediump float;\n"
            "out vec4 fragColor;\n"
            "void main() {\n"
            "   fragColor = vec4(1.0, 0.5, 0.0, 1.0);  // 金字塔颜色:橙色\n"
            "}"
        );
        program.link();
        program.bind();
    
        // 创建顶点数组对象和顶点缓冲对象
        GLuint vao, vbo, ebo;
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
    
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
        glGenBuffers(1, &ebo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
        GLint posAttrib = program.attributeLocation("position");
        program.enableAttributeArray(posAttrib);
        glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
    
        // 创建一个模型视图投影矩阵
        QMatrix4x4 projection;
        projection.perspective(45.0f, (float)width() / height(), 0.1f, 100.0f);
        projection.translate(0.0f, 0.0f, -3.0f);  // 将物体向远离观察者的方向移动
    
        QMatrix4x4 modelView;
        modelView.rotate(rotationAngle, 0.0f, 1.0f, 0.0f);  // 水平旋转金字塔
    
        QMatrix4x4 modelViewProjectionMatrix = projection * modelView;
    
        // 将 MVP 矩阵传递给着色器
        program.setUniformValue("modelViewProjectionMatrix", modelViewProjectionMatrix);
    
        // 绘制金字塔
        glDrawElements(GL_TRIANGLES, 18, GL_UNSIGNED_INT, nullptr);
    
        glBindVertexArray(0);
    }
    
    void OpenGLWidget::timerEvent(QTimerEvent *event)
    {
        rotationAngle += 1.0f;  // 增加旋转角度
        if (rotationAngle >= 360.0f)
            rotationAngle = 0.0f;
        update();  // 触发重绘
    }
    
  4. 创建项目文件并编译运行

    qmake -project
    echo "QT += core gui widgets opengl" >> qt-opengl-example.pro
    qmake
    make
    ./qt-opengl-example
    

5. 调试与优化

启用调试日志
export QT_LOGGING_RULES="qt.qpa.*=true"
权限问题

确保当前用户有权限访问 /dev/fb0/dev/dri/*

sudo chmod a+rw /dev/fb0
sudo chmod a+rw /dev/dri/*

完成后,你的金字塔应用程序将在树莓派的无窗口系统中运行并水平旋转!

相关推荐
尘佑不尘11 分钟前
shell编程7,bash解释器的 for循环+while循环
linux·开发语言·笔记·后端·web安全·bash·shell编程
小技与小术13 分钟前
MySQL高可用之组复制(MGR)
运维·数据库·mysql·adb
好想有猫猫21 分钟前
【STM32】定时器介绍&定时中断
c语言·笔记·stm32·单片机·嵌入式硬件
LightningJie24 分钟前
stm32中systick时钟pinlv和系统节拍频率有什么区别,二者有无影响?
单片机·嵌入式硬件
捂月24 分钟前
如何在 Spring Boot 中配置数据库?
数据库·spring boot·后端
ibuki_fuko25 分钟前
QTableView 实现表格及相关用法(C++)(QStandardItemModel+QItemSelectionModel)
开发语言·c++·qt
神经星星28 分钟前
【TVM 教程】如何在 CPU 上优化 GEMM
数据库·人工智能·机器学习
苍天饶过谁?29 分钟前
qt-unified-windows-x64-online
开发语言·qt
代码小鑫29 分钟前
【开源】A060-基于Spring Boot的游戏交易系统的设计与实现
java·开发语言·数据库·spring boot·后端
码农客栈31 分钟前
qt QGraphicsRotation详解
qt