当前位置: 首页 > news >正文

QOpenGLFunctions_2_1 与 OpenGL 的区别

核心区别:Qt 封装器 vs. 图形标准

OpenGL 是一种用于渲染 2D 和 3D 向量图形的跨语言、跨平台的应用程序编程接口(API)规范。它本身不是一个可执行文件或库,而是一系列函数的标准定义。你的显卡驱动程序提供了这个标准的具体实现。

QOpenGLFunctions_2_1Qt 框架提供的一个 C++ 类。它的主要目的是帮助你在 Qt 应用中安全、方便地使用 OpenGL 2.1 版本的函数。

你可以把它想象成一个遥控器:

  • OpenGL 是你的电视机(功能强大的底层硬件和软件)。
  • QOpenGLFunctions_2_1 是一个精心设计的遥控器,它让你能够轻松、安全地控制电视机的特定功能(OpenGL 2.1 功能),而无需自己去处理复杂的电源线和内部电路。

详细对比

特 性QOpenGLFunctions_2_1OpenGL (标准)
本质一个 C++ 一个图形 API 规范
所属Qt 框架Khronos Group(标准制定者)
作用封装和加载 OpenGL 函数指针定义了一套用于渲染的函数集合
版本对应 OpenGL 2.1 和 OpenGL ES 2.0拥有多个版本(如 1.x, 2.1, 3.x, 4.x, 4.6等)
管线仅支持固定管线(Fixed-Function Pipeline)早期版本支持固定管线,现代版本(3.1+)主推可编程管线(Programmable Pipeline)
使用方式QOpenGLWidget 中继承并调用 initializeOpenGLFunctions() 方法后,即可直接使用 gl* 函数,无需手动加载。你需要通过显卡驱动程序提供的特定机制(如 GLAD、GLEW 或 Qt 提供的类)来获取函数指针,才能调用它们。
移植性跨平台,由 Qt 负责处理底层差异。规范是跨平台的,但你需要依赖具体平台的工具来访问它。

总结

QOpenGLFunctions_2_1 实际上是 Qt 为你提供的一座“桥梁”,它将你编写的 C++ 代码与底层的 OpenGL 标准实现连接起来。

当你使用 QOpenGLFunctions_2_1 时,你调用的 glBegin()glVertex3f() 等函数,实际上是这个类在幕后帮你找到了显卡驱动程序中对应的函数地址,并进行了调用。这使得你的代码更加简洁,并且确保了在不同操作系统上的兼容性。

简而言之,你不能“使用”OpenGL,你只能使用一个实现了 OpenGL 规范的库或类。而 QOpenGLFunctions_2_1 就是 Qt 为你提供的最方便、最常用的一个。

简单流程:
1、继承QOpenGLFunctions_2_1(OpenGL 2.1 功能)

2、初始化 initializeGL(),核心initializeOpenGLFunctions(),必须调用初始化所有opengl2.1的指针

3、处理窗口尺寸变化

  • 函数会在窗口第一次显示或每次被调整大小时被调用。在这里,你应该设置你的视口(Viewport)和投影矩阵(Projection Matrix),以确保场景能够正确地适配窗口的宽高比。

4、paintGL() 函数是你的主渲染循环。Qt 会在需要更新窗口内容时自动调用它。你所有的绘制逻辑都应该放在这里。

5、画图形,立方体的绘制逻辑

一个立方体由 6 个面组成,每个面都是一个四边形。如果使用 GL_QUADS,每个面需要 4 个顶点。如果使用 GL_TRIANGLES,每个面需要 6 个顶点(两个三角形)。在 QOpenGLFunctions_2_1 的示例中,使用 GL_QUADS 是最直观的方式。

下面是 drawCube() 函数的实现细节:

  1. 开始绘制:调用 glBegin(GL_QUADS),告诉 OpenGL 接下来我们将要定义四边形。
  2. 定义每个面
  • 为每个面设置一个唯一的颜色 (glColor3f)。
  • 按逆时针或顺时针顺序定义该面的 4 个顶点 (glVertex3f)。这个顺序很重要,因为它决定了面的“正面”(Face Culling,如果你启用了这个功能)。
  1. 结束绘制:调用 glEnd(),结束四边形的定义。

代码:
myopenglwidget.h

#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions_2_1>
#include <QTimerEvent>
#include <QKeyEvent>
const double M_PI = 3.14159265358979323846;// 继承 QOpenGLWidget 和 QOpenGLFunctions_2_1
// 这样我们既可以使用 Qt 的 OpenGL 窗口,又可以直接调用 OpenGL 2.1 的函数
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_2_1
{Q_OBJECTpublic:explicit MyOpenGLWidget(QWidget *parent = nullptr) : QOpenGLWidget(parent) {// 启用计时器以实现动画效果startTimer(16); // 大约 60 FPSm_angle = 0.0f;}protected:// 初始化 OpenGL 状态void initializeGL() override {// 必须调用此函数,它会加载 QOpenGLFunctions_2_1 提供的所有函数指针initializeOpenGLFunctions();// 设置背景色为深蓝色glClearColor(0.2f, 0.2f, 0.4f, 1.0f);// 启用深度测试,以确保正确的 3D 渲染效果glEnable(GL_DEPTH_TEST);}// 处理窗口尺寸变化void resizeGL(int w, int h) override {// 设置视口大小,使其与窗口尺寸匹配glViewport(0, 0, w, h);// 选择投影矩阵glMatrixMode(GL_PROJECTION);// 重置矩阵为单位矩阵glLoadIdentity();// 设置透视投影// fovy: 视野角度, aspect: 宽高比, zNear: 近剪裁平面, zFar: 远剪裁平面// 这里我们使用一个简单的透视投影来模拟3D效果GLdouble aspect = (GLdouble)w / (GLdouble)h;gluPerspective(45.0, aspect, 0.1, 100.0);}// 绘制场景void paintGL() override {// 清空颜色缓冲区和深度缓冲区glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 选择模型视图矩阵glMatrixMode(GL_MODELVIEW);// 重置矩阵glLoadIdentity();// 将模型平移到屏幕中央glTranslatef(0.0f, 0.0f, -5.0f);// 根据角度旋转模型,实现动画效果glRotatef(m_angle, 1.0f, 1.0f, 0.0f);// 使用固定管线绘制一个彩色立方体drawCube();}// 绘制立方体的辅助函数void drawCube() {glBegin(GL_QUADS);// 前面glColor3f(1.0f, 0.0f, 0.0f); // 红色glVertex3f(-1.0f, -1.0f,  1.0f);glVertex3f( 1.0f, -1.0f,  1.0f);glVertex3f( 1.0f,  1.0f,  1.0f);glVertex3f(-1.0f,  1.0f,  1.0f);// 后面glColor3f(0.0f, 1.0f, 0.0f); // 绿色glVertex3f(-1.0f, -1.0f, -1.0f);glVertex3f(-1.0f,  1.0f, -1.0f);glVertex3f( 1.0f,  1.0f, -1.0f);glVertex3f( 1.0f, -1.0f, -1.0f);// 顶部glColor3f(0.0f, 0.0f, 1.0f); // 蓝色glVertex3f(-1.0f,  1.0f, -1.0f);glVertex3f(-1.0f,  1.0f,  1.0f);glVertex3f( 1.0f,  1.0f,  1.0f);glVertex3f( 1.0f,  1.0f, -1.0f);// 底部glColor3f(1.0f, 1.0f, 0.0f); // 黄色glVertex3f(-1.0f, -1.0f, -1.0f);glVertex3f( 1.0f, -1.0f, -1.0f);glVertex3f( 1.0f, -1.0f,  1.0f);glVertex3f(-1.0f, -1.0f,  1.0f);// 右侧glColor3f(1.0f, 0.0f, 1.0f); // 品红glVertex3f( 1.0f, -1.0f, -1.0f);glVertex3f( 1.0f,  1.0f, -1.0f);glVertex3f( 1.0f,  1.0f,  1.0f);glVertex3f( 1.0f, -1.0f,  1.0f);// 左侧glColor3f(0.0f, 1.0f, 1.0f); // 青色glVertex3f(-1.0f, -1.0f, -1.0f);glVertex3f(-1.0f, -1.0f,  1.0f);glVertex3f(-1.0f,  1.0f,  1.0f);glVertex3f(-1.0f,  1.0f, -1.0f);glEnd();}// 计时器事件处理器void timerEvent(QTimerEvent *event) override {// 每次定时器触发时,增加旋转角度m_angle += 1.0f;// 请求重新绘制,这将触发 paintGL()update();}private:float m_angle; // 旋转角度// gluPerspective 的实现,QOpenGLFunctions_2_1 默认不提供// 这里为了示例完整性手动实现一个简单的版本void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) {GLdouble ymax = zNear * tan(fovy * M_PI / 360.0);GLdouble ymin = -ymax;GLdouble xmax = ymax * aspect;GLdouble xmin = ymin * aspect;glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);}
};
#endif // MYOPENGLWIDGET_H

main.cpp

#include <QApplication>
#include "myopenglwidget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);MyOpenGLWidget widget;widget.setWindowTitle("QOpenGLFunctions_2_1 示例");widget.setMinimumSize(800, 600);widget.show();return a.exec();
}
http://www.dtcms.com/a/353586.html

相关文章:

  • 【系统架构设计(四)】软件工程:从瀑布到敏捷的演进之路
  • 【系统架构设计(三)】系统工程与信息系统基础下:企业信息化与电子商务-数字化转型的核心驱动力
  • 【Django + Pure Admin】基于Django+Vue3的前后端分离管理系统框架设计
  • 服务器硬件电路设计之 SPI 问答(六):如何提升服务器硬件电路中的性能?如何强化稳定性?
  • MySQL explain命令的作用
  • 什么是AI+?什么是人工智能+?
  • 济南大学杨波与济南青盟信息技术有限公司杨华伟
  • 北京国标竞品调查,知己知彼(竞品调查研究)
  • Java全栈开发面试实战:从基础到微服务的深度探索
  • Linux学习-TCP并发服务器构建
  • XState
  • 第五章:循环
  • Playwright之脱离元素,页面操作大全!
  • 2026 年美国国际太阳能展(RE+)
  • 如何在 Docker 和AKS上使用 IIS
  • 【Redis 进阶】Redis 典型应用 —— 分布式锁
  • F008 vue+flask 音乐推荐评论和可视化系统+带爬虫前后端分离系统
  • Android中APK包含哪些内容?
  • k8s集群Prometheus部署
  • 【Python办公】快速比较Excel文件中任意两列数据的一致性
  • 【Rust】 1. 变量学习笔记
  • DWT域进行视频信息隐藏的原理及优缺点
  • 洞悉Oracle数据库的基石:深入剖析其核心物理存储结构
  • 2025软件测试面试八股文(完整版)
  • 【Redis 进阶】Redis 典型应用 —— 缓存(cache)
  • day2_softmax回归的实现 李沐动手学深度学习pytorch记录
  • 云蝠智能AI语音智能体:破解企业电话接听难题
  • 第五章:Go运行时、内存管理与性能优化之Go调度器 (GMP模型) 详解
  • 【工具】基于LabelImg标注数据安装运行全流程
  • 运算符(3)