完整例子和调用关系qt OpenGL

项目结构

首先,你需要在 Qt 项目中创建一个类,继承自 QOpenGLWidget 来进行 OpenGL 渲染。文件结构如下:
- main.cpp
- MyOpenGLWidget.h
- MyOpenGLWidget.cpp
- vertex_shader.glsl
- fragment_shader.glsl

1. main.cpp

这是 Qt 项目的入口文件,创建一个 QApplication 实例并显示一个包含 QOpenGLWidget 的窗口。
// 包含 Qt 应用程序的核心类,用于管理 Qt 应用程序的控制流。
#include <QApplication>// 包含 Qt 的主窗口类,可以创建一个包含菜单、工具栏等常见组件的窗口。
#include <QMainWindow>// 包含我们自定义的 OpenGL 渲染窗口类。
#include "MyOpenGLWidget.h"int main(int argc, char *argv[]) {/* 初始化 Qt 应用程序。argc 和 argv 是命令行参数,通常用来传递命令行参数到程序中。QApplication 是所有 Qt 应用程序的基础,它管理应用程序的生命周期和事件循环。*/QApplication app(argc, argv);// 创建一个主窗口对象 window,它是应用程序的主界面。QMainWindow window;// 创建自定义的 OpenGL 渲染窗口 glWidget。// &window 将主窗口 window 作为父窗口传递给 glWidget。MyOpenGLWidget *glWidget = new MyOpenGLWidget(&window);// 将 glWidget 设为 window 的中心部件。// QMainWindow 中的中心部件通常占据主窗口的最大区域。window.setCentralWidget(glWidget);// 设置窗口大小window.resize(800, 600);// 显示窗口window.show();return app.exec();
}

2. MyOpenGLWidget.h

这是声明文件,继承自 QOpenGLWidget 和 QOpenGLFunctions, 用于处理 OpenGL 渲染。在这里,我们声明必要的 OpenGL 初始化、绘制和清理函数。
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H// 包含 Qt 的 OpenGL 小部件类,这样我们可以创建一个 OpenGL 渲染窗口。
#include <QOpenGLWidget>
// 包含 OpenGL 功能的接口。我们可以通过这个类访问 OpenGL 的核心功能。
#include <QOpenGLFunctions>
// 包含 OpenGL 着色器程序类,负责加载、编译、链接和管理着色器程序。
#include <QOpenGLShaderProgram>
// 包含 OpenGL 缓冲区类,负责创建和管理顶点缓冲对象(VBO)和索引缓冲对象(EBO)。
#include <QOpenGLBuffer>/* 声明一个名为 MyOpenGLWidget 的类,继承自 QOpenGLWidget 和 QOpenGLFunctions。QOpenGLWidget 是 Qt 提供的 OpenGL 渲染窗口基类,QOpenGLFunctions 提供了 OpenGL 的基本功能。protected QOpenGLFunctions 是为了能够访问 OpenGL 的函数接口。
*/
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions {Q_OBJECTpublic:MyOpenGLWidget(QWidget *parent = nullptr);~MyOpenGLWidget();protected:// 初始化 OpenGL 环境的函数。// 在这里你会设置 OpenGL 的状态,例如开启深度测试、设置视口、加载着色器等。void initializeGL() override;// 当窗口大小改变时自动调用。你可以在这里设置 OpenGL 视口以及投影矩阵。void resizeGL(int w, int h) override;// 每次需要重新绘制时调用。在这里绘制 OpenGL 图形。void paintGL() override;private:// 用于初始化并编译着色器的函数。void initializeShaders();// 用于初始化顶点数据和缓冲区的函数。void initializeBuffers();// 指向 OpenGL 着色器程序的指针。用于管理着色器的加载、编译、链接和绑定。QOpenGLShaderProgram *shaderProgram;// 一个 QOpenGLBuffer 对象,用于存储顶点数据的缓冲区(VBO)。QOpenGLBuffer vertexBuffer;        // 顶点数组对象的句柄。VAO 用于管理顶点属性和缓冲区对象。GLuint VAO, VBO;                          
};#endif // MYOPENGLWIDGET_H

3. MyOpenGLWidget.cpp

这是实现文件,包含了 OpenGL 初始化、着色器编译、数据传输和渲染的具体代码。
#include "MyOpenGLWidget.h"
// 包含 OpenGL 着色器类,负责加载着色器代码并编译它们。
#include <QOpenGLShader>
#include <QOpenGLBuffer>
#include <QDebug>MyOpenGLWidget::MyOpenGLWidget(QWidget *parent): QOpenGLWidget(parent),shaderProgram(nullptr) 
{
}MyOpenGLWidget::~MyOpenGLWidget() {// 销毁 shaderProgram,释放着色器程序的内存。delete shaderProgram;
}void MyOpenGLWidget::initializeGL() {// 1. 初始化 OpenGL 函数,确保可以使用 OpenGL 的所有函数。initializeOpenGLFunctions();// 启用深度测试,确保物体在 3D 场景中的正确显示(即前面物体遮挡后面物体)。glEnable(GL_DEPTH_TEST);  // 2. 初始化着色器程序initializeShaders();// 3. 初始化顶点数据initializeBuffers();
}void MyOpenGLWidget::initializeShaders() {// 2.1 创建并编译顶点着色器// 创建一个新的着色器程序对象。shaderProgram = new QOpenGLShaderProgram();// 加载并编译顶点着色器,QOpenGLShader::Vertex 指明这是顶点着色器,文件路径为 :/vertex_shader.glsl。shaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vertex_shader.glsl");// 加载并编译片段着色器,QOpenGLShader::Fragment 指明这是片段shaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fragment_shader.glsl");// 2.2 链接着色器程序shaderProgram->link();shaderProgram->bind();
}void MyOpenGLWidget::initializeBuffers() {// 3.1 顶点数据(一个简单的三角形)GLfloat vertices[] = {-1.0f,  1.0f, 0.0f,   // 顶点1-1.0f, -1.0f, 0.0f,   // 顶点21.0f, -1.0f, 0.0f    // 顶点3};// 3.2 创建 VAO 和 VBOglGenVertexArrays(1, &VAO);  // 创建 VAOglBindVertexArray(VAO);      // 绑定 VAOglGenBuffers(1, &VBO);       // 创建 VBOglBindBuffer(GL_ARRAY_BUFFER, VBO);  // 绑定 VBOglBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // 分配数据给 VBO// 3.3 设置顶点属性(位置)// 启用顶点属性(位置属性)shaderProgram->enableAttributeArray(0);// 设置位置数据的格式shaderProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 3 * sizeof(GLfloat));vertexBuffer.release();  // 释放 VBOglBindVertexArray(0);  // 解绑 VAO
}void MyOpenGLWidget::resizeGL(int w, int h) {// 4. 设置视口大小glViewport(0, 0, w, h);// 4.1 设置投影矩阵(透视投影)glMatrixMode(GL_PROJECTION); // 设定当前矩阵为投影矩阵glLoadIdentity();  // 重置当前矩阵// 设置透视投影gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.1, 100.0);// 切换回模型视图矩阵glMatrixMode(GL_MODELVIEW);
}void MyOpenGLWidget::paintGL() {// 5. 清空屏幕并准备绘制// 清空颜色和深度缓冲glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();// 5.1 使用着色器程序shaderProgram->bind();glBindVertexArray(VAO);// 5.2 绘制三角形// 使用顶点数据绘制三角形glDrawArrays(GL_TRIANGLES, 0, 3);glBindVertexArray(0);shaderProgram->release();
}

4. vertex_shader.glsl

顶点着色器(将顶点位置传递给片段着色器):
#version 330 core
layout(location = 0) in vec3 position;
void main() {gl_Position = vec4(position, 1.0);  // 直接输出位置
}

5. fragment_shader.glsl

片段着色器(指定最终颜色):
#version 330 core
out vec4 color;
void main() {color = vec4(1.0, 0.0, 0.0, 1.0);  // 输出红色
}


函数作用说明

  • initializeGL():负责 OpenGL 环境的初始化工作,包括启用深度测试、初始化着色器和顶点数据。这个函数会在 QOpenGLWidget 创建后自动调用。
  • initializeShaders():编译顶点和片段着色器,并将它们链接成一个 OpenGL 程序。着色器代码通常存储在外部文件中,这里用 addShaderFromSourceFile() 来加载。
  • initializeBuffers():创建并初始化顶点缓冲对象(VBO)和顶点数组对象(VAO)。VBO 存储顶点数据,而 VAO 用于管理 VBO 的状态。顶点数据传送到 GPU 后,OpenGL 会使用它来绘制物体
  • resizeGL(int w, int h):用于处理 OpenGL 上下文的大小变化,设置视口以及投影矩阵,使得绘制的图形不会在窗口大小变化时失真。
  • paintGL():这个函数每次需要重新绘制时都会被调用。这里,我们清空屏幕,使用着色器程序,并通过 glDrawArrays() 绘制三角形。

调用关系和逻辑

  1. 在程序启动时,QOpenGLWidget 的构造函数会被调用。QOpenGLWidget 会创建一个 OpenGL 上下文,并在需要时调用 initializeGL()。
  2. 在 initializeGL() 中,我们初始化 OpenGL 状态(如深度测试),然后调用 initializeShaders() 来加载并编译着色器程序,接着调用 initializeBuffers() 初始化顶点数据。
  3. 每当窗口大小改变时,resizeGL() 会被自动调用来调整视口大小和设置合适的投影矩阵。
  4. 每次需要绘制时(例如每帧刷新时),paintGL() 会被调用。在此函数中,我们绑定着色器程序、顶点数组对象(VAO),并通过 glDrawArrays() 来绘制三角形。

总结

  • initializeGL() -> 调用 initializeShaders() 初始化着色器,调用 initializeBuffers() 初始化顶点数据。
  • paintGL() -> 每次绘制时使用着色器和顶点数据。
  • resizeGL() -> 当窗口大小变化时调整视口和投影矩阵。

疑惑补充:

QOpenGLShaderProgram 对象-CSDN博客

OpenGL疑惑-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73176.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VSCode 配置优化指南:打造极致高效的前端开发环境

VSCode 配置优化指南&#xff1a;打造极致高效的前端开发环境 一、基础环境配置&#xff1a;让开发更流畅 1. 性能优化设置 // settings.json {"files.autoSave": "afterDelay", // 自动保存&#xff08;延迟1秒&#xff09;"files.exclud…

源IP泄露后如何涅槃重生?高可用架构与自动化防御体系设计

一、架构层解决方案 1. 高防代理架构设计 推荐架构&#xff1a; 用户 → CDN&#xff08;缓存静态资源&#xff09; → 高防IP&#xff08;流量清洗&#xff09; → 源站集群&#xff08;真实IP隐藏&#xff09; ↑ Web应用防火墙&#xff08;WAF&#xff09; 实施要点&a…

【英伟达AI论文】多模态大型语言模型的高效长视频理解

摘要&#xff1a;近年来&#xff0c;基于视频的多模态大型语言模型&#xff08;Video-LLMs&#xff09;通过将视频处理为图像帧序列&#xff0c;显著提升了视频理解能力。然而&#xff0c;许多现有方法在视觉主干网络中独立处理各帧&#xff0c;缺乏显式的时序建模&#xff0c;…

无障碍阅读(Web Accessibility)NVDA打开朗读查看器后,enter键不生效的原因

用NVDA测试Web Accessibility时&#xff0c;打开朗读查看器&#xff0c;enter键会无效&#xff0c;而不打开测试器&#xff0c;就没有问题&#xff0c;很大原因是被应用的元素不是可聚焦的&#xff0c;解决方法尝试&#xff1a; 将标签改为可聚焦的语义化标签&#xff0c;如 b…

2Android中的AIDL是什么以及如何使用它

一、Android中的AIDL概述 AIDL&#xff08;Android Interface Definition Language&#xff09;是Android系统中用于定义和实现跨进程通信&#xff08;IPC&#xff09;接口的语言。它允许一个进程向另一个进程发送请求并获取响应&#xff0c;是Android中实现进程间通信的一种重…

Python绘制数据分析中经典的图形--列线图

Python绘制数据分析中经典的图形–列线图 列线图是数据分析中的经典图形&#xff0c;通过背后精妙的算法设计&#xff0c;展示线性模型&#xff08;logistic regression 和Cox&#xff09;中各个变量对于预测结果的总体贡献&#xff08;线段长短&#xff09;&#xff0c;另外&…

leetcode【面试经典150系列】(一)

目录 121.买卖股票最佳时机 题目描述 示例 算法分析 代码(python3) 122.买卖股票最佳时机II 题目描述 示例 算法分析 代码&#xff08;python3&#xff09; 55.跳跃游戏 题目描述 示例 算法分析 代码 45.跳跃游戏II 题目描述 示例 算法分析 代码 121.买卖股票…

为什么会出现redis数据库?redis是什么?

什么是 Redis? 为什么要用 Redis? 下面我将从 Redis 出现的背景、Redis 的解决方案个来回答。 1、Redis 出现的背景 互联网的应用越来越多&#xff0c;例如社交网络、电商、实时服务发展的十分迅速&#xff0c;这就导致了传统技术栈&#xff08;如关系型数据库&#xff09;…

Windows 11下Git Bash执行cURL脚本400问题、CMD/PowerShell不能执行多行文本等问题记录及解决方案

问题 在Postman里可成功执行的POST请求&#xff1a; 找到Postman的Code 因为cURL基本上算是行业标准&#xff0c;所以Postman默认选中cURL&#xff0c;支持切换不同的开发语言&#xff1a; 点击上图右上角的复制按钮&#xff0c;得到cURL脚本。 Windows 11家庭版&#xff…

Docker基础入门(一)

初识Docker 什么是Docker Docker是一个快速交付应用、运行应用的技术&#xff1a; 可以将程序及其依赖、运行环境一起打包为一个镜像&#xff0c;可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器&#xff0c;各个应用互不干扰启动、移除都可以通过一行命令完成&…

容器编排革命:从 Docker Run 到 Docker Compose 的进化之路20250309

容器编排革命&#xff1a;从 Docker Run 到 Docker Compose 的进化之路 一、容器化部署的范式转变 在 Docker 生态系统的演进中&#xff0c;容器编排正从“手动操作”走向“自动化管理”。根据 Docker 官方 2023 年开发者调查报告&#xff0c;78% 的开发者已采用 Docker Compo…

c++ 嵌入汇编的方式实现int型自增

x86/x86_64 实现 x86 平台上&#xff0c;使用 LOCK XADD 指令来实现原子自增&#xff1a; #include <iostream>inline int atomic_increment_x86(int* value) {int result;__asm__ __volatile__("lock xaddl %1, %0": "m"(*value), "r"(…

区块链与去中心化技术

区块链与去中心化技术 核心进展 区块链从加密货币&#xff08;如比特币&#xff09;扩展至智能合约和供应链管理。以太坊2.0引入分片技术提升交易吞吐量&#xff0c;而零知识证明&#xff08;ZKP&#xff09;增强了隐私保护15。企业级应用如IBM的Food Trust平台通过区块链追踪…

逐梦DBA:Linux环境下 MySQL 的卸载

1. 查看是否安装过MySQL&#xff0c;如果不存在&#xff0c;则不显示任何内容 rpm -qa | grep -i mysql # -i 忽略大小写 2. 查看MySQL服务状态 systemctl status mysqld.service 3. 关闭 mysql 服务 systemctl stop mysqld.service 4. 查看当前 mysql 卸载状况 rpm -qa…

【蓝桥杯python研究生组备赛】003 贪心

题目1 股票买卖 给定一个长度为 N 的数组&#xff0c;数组中的第 i 个数字表示一个给定股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&#xff09;。 注意&#xff1a;你不能同时参与多笔交易&…

网络通信Socket中多态HandleIO设计模式深度解析

网络通信 Socket 中多态 handleIO 详细讲解 大纲 引言 网络通信的重要性Socket 编程在网络通信中的地位多态 handleIO 的意义和作用 Socket 编程基础 Socket 的基本概念Socket 的类型&#xff08;TCP 和 UDP&#xff09;Socket 编程的基本流程 多态的概念与实现 多态的定义和…

flutter 如何与原生框架通讯安卓 和 ios

在 Flutter 中与原生框架&#xff08;Android 和 iOS&#xff09;进行通信的主要方式是通过 **平台通道&#xff08;Platform Channels&#xff09;**。平台通道允许 Flutter 代码与原生代码进行双向通信。以下是详细的步骤和示例&#xff0c;说明如何在 Flutter 中与 Android …

LabVIEW VI Scripting实现连接器窗格自动化

通过VI Scripting自动化配置连接器窗格&#xff0c;可大幅提升开发效率、统一接口规范&#xff0c;并适配动态需求。以下为真实场景中的典型应用案例&#xff0c;涵盖工业、汽车电子及教育领域&#xff0c;展示其实际价值与实施效果。 特点&#xff1a; 程序化配置&#xff1a;…

1-001:MySQL的存储引擎有哪些?它们之间有什么区别?

MySQL 存储引擎 ├── InnoDB&#xff08;默认引擎&#xff09; │ ├── 事务支持&#xff1a;支持 ACID 和事务&#xff08;事务日志、回滚、崩溃恢复&#xff09; │ ├── 锁机制&#xff1a;支持行级锁&#xff0c;提高并发性能 │ ├── 外键支持&#xff1a;支持外键…

package.json 依赖包约束及快速删除node_modules

文章目录 一、package.json版本约束1、初始项目安装2. 已有 yarn.lock 文件的项目安装3. 特殊情况手动修改 package.json 版本&#xff1a;使用 yarn upgrade 命令&#xff1a; 二、快速删除node_modules三、depcheck 检测npm未使用的依赖 一、package.json版本约束 1、初始项…