嵌入式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 渲染。
-
确认系统支持 EGLFS:
ls /usr/lib/arm-linux-gnueabihf/qt5/plugins/platforms/libqeglfs.so如果存在
libqeglfs.so,表示系统支持 EGLFS。 -
设置环境变量启用 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
-
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(); } -
openglwidget.h:#ifndef OPENGLWIDGET_H #define OPENGLWIDGET_H#include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QTimer>class OpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions {Q_OBJECTpublic: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 -
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, // 顶点10.5f, -0.5f, -0.5f, // 顶点20.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(); // 触发重绘 } -
创建项目文件并编译运行:
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/*
完成后,你的金字塔应用程序将在树莓派的无窗口系统中运行并水平旋转!
相关文章:
嵌入式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-dev2. 安…...
webGL入门教程_06变换矩阵与绕轴旋转总结
变换矩阵与绕轴旋转总结 目录 1. 变换矩阵简介2. 平移矩阵3. 缩放矩阵4. 旋转矩阵 4.1 绕 Z 轴旋转4.2 绕 X 轴旋转4.3 绕 Y 轴旋转 5. 组合变换矩阵6. 结论 1. 变换矩阵简介 在计算机图形学中,变换矩阵用于在三维空间中对物体进行操作,包括ÿ…...
生成树详解(STP、RSTP、MSTP)
目录 1、STP 1.概述 2.基本概念 3.端口角色及其作用 4.报文结构 5.STP的端口状态 6.三种定时器 7.STP选举步骤 8.配置BPDU的比较原则 9.TCN BPDU 10.临时环路的问题 11.传统STP的不足 拓扑变更处理过程 2、RSTP 1.端口角色 2.端口状态 3.P/A(Propo…...
【QNX+Android虚拟化方案】128 - QNX 侧触摸屏驱动解析
【QNX+Android虚拟化方案】128 - QNX 侧触摸屏驱动解析 一、QNX 侧触摸屏配置基于原生纯净代码,自学总结 纯技术分享,不会也不敢涉项目、不泄密、不传播代码文档!!! 本文禁止转载分享 !!! 汇总链接:《【QNX+Android虚拟化方案】00 - 系列文章链接汇总》 本文链接:《【…...
C#中的集合初始化器
C#中的集合初始化器是一种简洁的语法,允许在声明集合的同时初始化其元素。这种语法特别适用于初始化实现了IEnumerable接口并具有Add方法的集合类型,如List<T>、Dictionary<TKey, TValue>等。 集合初始化器的基本用法 集合初始化器的基本语…...
cartographer建图与定位应用
文章目录 前言一、安装cartographer1.安装环境2.源码编译2.1 下载2.2 编译 二、gazebo仿真2d建图0.准备仿真环境1.编写lua文件2.编写启动文件3.建图保存 三、cartographer定位 move_base导航3.1 编写启动文件3.2 启动launch 总结 前言 本文介绍cartographer在ubuntu18.04下的…...
专业解析 .bashrc 中 ROS 工作空间的加载顺序及其影响 ubuntu 机器人
专业解析 .bashrc 中 ROS 工作空间的加载顺序及其影响 在使用 ROS(Robot Operating System)进行开发时,通常会涉及多个 Catkin 工作空间(Catkin Workspace)。这些工作空间包含不同的 ROS 包和节点,可能相互…...
Apache Doris 现行版本 Docker-Compose 运行教程
特别注意!Doris On Docker 部署方式仅限于开发环境或者功能测试环境,不建议生产环境部署! 如有生产环境或性能测试集群部署诉求,请使用裸机/虚机部署或K8S Operator部署方案! 原文阅读:Apache Doris 现行版…...
Flink四大基石之窗口(Window)使用详解
目录 一、引言 二、为什么需要 Window 三、Window 的控制属性 窗口的长度(大小) 窗口的间隔 四、Flink 窗口应用代码结构 是否分组 Keyed Window --键控窗 Non-Keyed Window 核心操作流程 五、Window 的生命周期 分配阶段 触发计算 六、Wi…...
NGINX配置https双向认证(自签一级证书)
一 生成自签证书 以下是生成自签证书(包括服务端和客户端的证书)的步骤,以下命令执行两次,分别生成客户端和服务端证书和私钥。具体执行可以先建两个目录client和server,分别进入到这两个目录下执行下面的命令。 生成私钥: 首先&…...
Flink双流Join
在离线 Hive 中,我们经常会使用 Join 进行多表关联。那么在实时中我们应该如何实现两条流的 Join 呢?Flink DataStream API 为我们提供了3个算子来实现双流 join,分别是: join coGroup intervalJoin 下面我们分别详细看一下这…...
【数据结构实战篇】用C语言实现你的私有队列
🏝️专栏:【数据结构实战篇】 🌅主页:f狐o狸x 在前面的文章中我们用C语言实现了栈的数据结构,本期内容我们将实现队列的数据结构 一、队列的概念 队列:只允许在一端进行插入数据操作,在另一端…...
基于web的海贼王动漫介绍 html+css静态网页设计6页+设计文档
📂文章目录 一、📔网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站演示 五、⚙️网站代码 🧱HTML结构代码 💒CSS样式代码 六、🔧完整源码下载 七、📣更多 一、&#…...
2022 年 9 月青少年软编等考 C 语言三级真题解析
目录 T1. 课程冲突T2. 42 点思路分析T3. 最长下坡思路分析T4. 吃糖果思路分析T5. 放苹果思路分析T1. 课程冲突 此题为 2021 年 9 月三级第一题原题,见 2021 年 9 月青少年软编等考 C 语言三级真题解析中的 T1。 T2. 42 点 42 42 42 是: 组合数学上的第 5 5 5 个卡特兰数字…...
机器学习算法(六)---逻辑回归
常见的十大机器学习算法: 机器学习算法(一)—决策树 机器学习算法(二)—支持向量机SVM 机器学习算法(三)—K近邻 机器学习算法(四)—集成算法 机器学习算法(五…...
计算机科学中的主要协议
1、主要应用层协议: HTTP、FTP、SMTP、POP、IMAP、DNS、TELNET和SSH等 应用层协议的主要功能是支持网络应用,定义了不同应用程序之间的通信规则。它们负责将用户操作转换为网络可以理解的数据格式,并通过传输层进行传输。应用层协议直接与用…...
下载maven 3.6.3并校验文件做md5或SHA512校验
一、下载Apache Maven 3.6.3 Apache Maven 3.6.3 官方下载链接: 二进制压缩包(推荐): ZIP格式: https://archive.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.zipTAR.GZ格式: https://archive.apache.org/dist/…...
【Android】View工作原理
View 是Android在视觉上的呈现在界面上Android提供了一套GUI库,里面有很多控件,但是很多时候我们并不满足于系统提供的控件,因为这样就意味这应用界面的同类化比较严重。那么怎么才能做出与众不同的效果呢?答案是自定义View&#…...
TIE算法具体求解-为什么是泊松方程和傅里叶变换
二维泊松方程的通俗理解 二维泊松方程 是偏微分方程的一种形式,通常用于描述空间中某个标量场(如位相场、电势场)的分布规律。其一般形式为: ∇ 2 ϕ ( x , y ) f ( x , y ) \nabla^2 \phi(x, y) f(x, y) ∇2ϕ(x,y)f(x,y) 其…...
postman中获取随机数、唯一ID、时间日期(包括当前日期增减)截取指定位数的字符等
在Postman中,您可以使用内置的动态变量和编写脚本的方式来获取随机数、唯一ID、时间日期以及截取指定位数的字符。以下是具体的操作方法: 一、postman中获取随机数、唯一ID、时间日期(包括当前日期增减)截取指定位数的字符等 获取…...
Qt桌面应用集成PaddleOCR:从环境搭建到精准识别的实践指南
1. 环境准备:搭建PaddleOCR的Qt开发环境 第一次在Qt里折腾PaddleOCR时,我对着官方文档折腾了半天还是报错,后来发现是第三方库的路径没配好。这里分享下我踩坑后总结的可靠方案。 核心依赖三件套:PaddlePaddle推理库、PaddleOCR C…...
芯片研发的残酷真相:流片成功只是开始
芯片成功"点亮"那一刻,项目算完成了吗?如果你认为算,那大概率还没经历过真正的芯片项目后期。事实是,点亮和demo跑通,只不过是拿到了入场券而已。真正的战斗,从客户拿到样片那一刻才开始。很多工…...
Python与OPC UA实战:高效读写PLC数据
1. 为什么选择Python操作OPC UA? 在工业自动化领域,PLC(可编程逻辑控制器)就像工厂的"大脑",而OPC UA则是让这个大脑与其他系统对话的"普通话"。作为Python开发者,我们经常需要从PLC读…...
Phi-4-mini-reasoning部署教程:Nginx反向代理+Basic Auth安全加固
Phi-4-mini-reasoning部署教程:Nginx反向代理Basic Auth安全加固 1. 项目介绍 Phi-4-mini-reasoning是一款由微软开源的轻量级AI模型,专注于数学推理、逻辑推导和多步解题等强逻辑任务。这个3.8B参数的模型虽然体积小巧,但在推理能力上表现…...
PyCharm+Conda环境避坑指南:手把手配置Real-ESRGAN,解决‘torch.cuda.is_available()‘报错和依赖冲突
PyCharmConda环境避坑指南:手把手配置Real-ESRGAN,解决‘torch.cuda.is_available()‘报错和依赖冲突 图像超分辨率技术正在改变我们处理低质量图像的方式,而Real-ESRGAN作为当前最先进的通用图像修复模型之一,其效果令人惊艳。但…...
【Git】深入解析 ‘.git/index.lock‘ 文件冲突:从报错到彻底解决
1. 当Git突然罢工:index.lock报错现场还原 那天下午我正忙着切换分支部署新功能,突然终端弹出红字警告:fatal: Unable to create .git/index.lock: File exists。这就像你急着上厕所却发现门被反锁,更糟的是你不知道里面到底有没有…...
ADNS3080光学传感器驱动开发与聚焦校准实战
1. ADNS3080光学运动传感器底层驱动技术解析ADNS3080是Avago(现Broadcom)推出的一款高精度、低功耗CMOS光学运动传感器,专为机械鼠标、轨迹球及工业位移检测等场景设计。其核心优势在于集成化程度高——片内集成了LED驱动电路、图像采集阵列&…...
别再数据线了!用FastAPI 分钟搭个局域网文件+剪贴板神器
AI Agent 时代的沙箱需求 从 Copilot 到 Agent:执行能力的质变 在生成式 AI 的早期阶段,应用主要以“Copilot”形式存在,AI 仅作为辅助生成建议。然而,随着 AutoGPT、BabyAGI 以及 OpenAI Code Interpreter(现为 Advan…...
【已验证】STM32驱动OLED(SSD1306)显示字符
本文介绍如何使用STM32F103C8T6(蓝板)通过软件模拟IIC协议驱动0.96英寸OLED(驱动芯片SSD1306),这个小屏幕相信每一个朋友在大学生活里都不会错过,也是很多课设毕设显示需求的首选,我一向喜欢直接…...
FanControl进阶指南:从噪音诊断到智能散热系统构建
FanControl进阶指南:从噪音诊断到智能散热系统构建 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/Fa…...
