首页 > 其他分享 >Qt 一文带你了解qt的三种 渲染引擎,包括栅格引擎(Raster)、OpenGL 和本地绘图系统

Qt 一文带你了解qt的三种 渲染引擎,包括栅格引擎(Raster)、OpenGL 和本地绘图系统

时间:2023-08-11 14:14:43浏览次数:33  
标签:Qt OpenGL 渲染 栅格 引擎 绘图 qt

概述
  Qt 提供了多种渲染引擎,包括栅格引擎(Raster)、OpenGL 和本地绘图系统。选择哪种引擎主要取决于你的应用程序需求和你的硬件环境。

  • 栅格引擎(Raster):这是 Qt 的软件渲染引擎,它在 CPU 上执行所有的绘图操作。栅格引擎在所有平台上都提供了一致的视觉效果,但可能会比硬件加速的引擎慢。
  • OpenGL:这是一个跨平台的硬件加速渲染 API,它在 GPU 上执行绘图操作。OpenGL 可以提供更快的渲染速度和更丰富的视觉效果,但需要支持 OpenGL 的硬件和驱动程序。
  • 本地绘图系统:这是使用操作系统的绘图 API,如 Windows 的 GDI 或 Direct2D,macOS 的 Quartz,Linux 的 X11 或 Wayland。本地绘图系统可以提供与操作系统一致的视觉效果,但可能会受到操作系统和硬件的限制。

  如果你的应用程序需要最快的渲染速度和最丰富的视觉效果,你应该使用 OpenGL。如果你的应用程序需要与操作系统一致的视觉效果,你应该使用本地绘图系统。如果你的应用程序需要在所有平台上提供一致的视觉效果,或者你的硬件不支持 OpenGL,你应该使用栅格引擎。

引擎详解
栅格引擎(Raster)
  栅格引擎(Raster Engine)是 Qt 的一种渲染引擎,它在 CPU 上执行所有的绘图操作。这种引擎使用了一种称为栅格化(Rasterization)的技术,将矢量图形(如线、曲线、多边形)转换为像素网格(即栅格)。

  栅格引擎的主要优点是它在所有平台上都提供了一致的视觉效果,因为它完全由 Qt 控制,不依赖于操作系统或硬件的特性。这使得它在跨平台应用程序中非常有用,因为你可以确保你的应用程序在所有平台上看起来都一样。

  此外,栅格引擎不需要特殊的硬件支持,因此它可以在任何支持 Qt 的设备上运行,包括一些老旧或低端的设备,这些设备可能不支持硬件加速的渲染。

  然而,栅格引擎的主要缺点是它可能会比硬件加速的引擎慢,因为它在 CPU 上执行所有的绘图操作,而不是在 GPU 上。CPU 通常比 GPU 更擅长处理复杂的逻辑和控制流,而不是大量的并行计算,这是图形渲染所需要的。因此,如果你的应用程序需要进行大量的图形渲染,或者需要实现复杂的视觉效果,你可能会发现栅格引擎的性能不足。

  总的来说,栅格引擎是一种灵活且可靠的渲染引擎,适合于需要跨平台一致性或在低端硬件上运行的应用程序。然而,对于需要高性能图形渲染的应用程序,你可能需要考虑使用硬件加速的渲染引擎,如 OpenGL。
  Qt::AA_ForceRasterWidgets 属性可以强制 Qt 使用栅格引擎来绘制所有的窗口和控件,而不是使用本地的绘图系统。这可能会影响你的应用程序的性能和视觉效果,所以你应该根据你的应用程序需求和你的硬件环境来决定是否设置这个属性。

OpenGL
  Qt 对 OpenGL 的支持是内建的,也就是说,只要你的 Qt 版本支持 OpenGL,你就可以在你的 Qt 应用程序中使用 OpenGL,无需额外安装 OpenGL。

  然而,要在你的 Qt 应用程序中使用 OpenGL,你的系统需要有一个支持 OpenGL 的图形驱动。这通常意味着你需要在你的系统上安装一个支持 OpenGL 的图形卡驱动。大多数现代的桌面系统(包括 Windows、macOS 和大多数 Linux 发行版)都自带了支持 OpenGL 的图形驱动,所以你通常不需要手动安装。

  如果你的系统没有支持 OpenGL 的图形驱动,或者你的图形驱动不支持你需要的 OpenGL 版本,你可能需要手动安装一个新的图形驱动。这通常涉及到从你的图形卡制造商的网站下载驱动程序,并按照他们的指示进行安装。

  请注意,虽然 Qt 支持 OpenGL,但并不是所有的 Qt 功能都需要 OpenGL。大多数 Qt 功能(包括 Qt Widgets 和 Qt Quick 2D)都可以在没有 OpenGL 的系统上运行。只有一些特定的功能(如 Qt Quick 3D 和一些 Qt 3D 功能)需要 OpenGL。

  Qt 提供了对 OpenGL 的深度集成,使得开发者可以利用 OpenGL 的强大功能来创建具有丰富视觉效果的应用程序。以下是一些关于 Qt 中 OpenGL 的关键点:

  1. QOpenGLWidget 和 QOpenGLWindow: 这两个类提供了一个可以使用 OpenGL 进行绘制的窗口或者控件。你可以重写它们的 initializeGL、resizeGL 和 paintGL 方法来执行你的 OpenGL 代码。
  2. QOpenGLFunctions: 这个类提供了跨平台的 OpenGL API。你可以使用这个类来调用 OpenGL 函数,而不需要直接包含 OpenGL 头文件或者链接 OpenGL 库。
  3. QOpenGLBuffer, QOpenGLVertexArrayObject, QOpenGLFramebufferObject: 这些类提供了对 OpenGL 的缓冲区、顶点数组对象和帧缓冲对象的封装。你可以使用这些类来管理你的 OpenGL 数据。
  4. QOpenGLShader and QOpenGLShaderProgram: 这两个类提供了对 OpenGL 的着色器和着色器程序的封装。你可以使用这些类来编译、链接和使用你的着色器。
  5. QOpenGLTexture: 这个类提供了对 OpenGL 的纹理的封装。你可以使用这个类来加载、生成和使用你的纹理。
  6. Qt Quick and QML: Qt Quick 是 Qt 的一个模块,它使用 QML 语言和 OpenGL 来创建动态的、硬件加速的用户界面。你可以使用 Qt Quick 和 QML 来创建具有丰富动画和视觉效果的应用程序,而不需要直接编写 OpenGL 代码。
  7. Thread Support: Qt 支持在多线程环境中使用 OpenGL。你可以在不同的线程中创建和使用 OpenGL 上下文和资源,但你需要注意 OpenGL 的线程安全问题。
  8. Extension Support: Qt 支持 OpenGL 的扩展。你可以使用 QOpenGLContext::hasExtension 和 QOpenGLContext::getProcAddress 方法来检查和使用 OpenGL 的扩展。
  9. Debug Support: Qt 支持 OpenGL 的调试。你可以使用 QOpenGLDebugLogger 类来获取 OpenGL 的调试消息。

  总的来说,Qt 提供了一套完整的工具和类来使用 OpenGL,使得开发者可以更容易地创建具有丰富视觉效果的应用程序。

本地绘图系统
  在 Qt 中,"本地绘图系统"通常指的是使用操作系统的原生绘图 API 来渲染用户界面。这些 API 可以提供与操作系统一致的视觉效果,但可能会受到操作系统和硬件的限制。

  Qt 支持多种操作系统,因此它的本地绘图系统也有多种。以下是一些例子:

  在 Windows 上,Qt 可以使用 GDI(Graphics Device Interface)或 Direct2D。GDI 是 Windows 的传统绘图 API,它在 CPU 上执行所有的绘图操作。Direct2D 是 Windows 的新绘图 API,它在 GPU 上执行绘图操作,可以提供更快的渲染速度和更丰富的视觉效果。

  在 macOS 上,Qt 可以使用 Quartz。Quartz 是 macOS 的绘图 API,它在 GPU 上执行绘图操作,可以提供与 macOS 一致的视觉效果。

  在 Linux 上,Qt 可以使用 X11 或 Wayland。X11 是 Linux 的传统绘图 API,它在 CPU 上执行所有的绘图操作。Wayland 是 Linux 的新绘图 API,它在 GPU 上执行绘图操作,可以提供更快的渲染速度和更丰富的视觉效果。

  Qt 的本地绘图系统通常用于绘制窗口和控件。但是,Qt 也提供了一些更高级的绘图功能,如 QPainter,它可以在任何绘图设备上绘制复杂的 2D 图形。QPainter 可以使用本地绘图系统,也可以使用其他的渲染引擎,如栅格引擎或 OpenGL。

  如果你的应用程序需要与操作系统一致的视觉效果,你应该使用本地绘图系统。但是,如果你的应用程序需要在所有平台上提供一致的视觉效果,或者你的应用程序需要复杂的 2D 图形,你可能需要使用 QPainter 或其他的渲染引擎。

通过策略模式来选择不同的引擎
  在 C++ 中,你可以通过继承和重写虚函数来实现一个抽象基类。在这个例子中,RasterEngineStrategy、OpenGLEngineStrategy 和 NativeEngineStrategy 都是 ApplicationEngineStrategy 的子类,它们都重写了 setEngine 函数。以下是具体的实现:

 1 #include <QApplication>
 2 #include <QSurfaceFormat>
 3 #include <memory>
 4 
 5 class ApplicationEngineStrategy {
 6 public:
 7     virtual void setEngine(QApplication& app) = 0;
 8 };
 9 
10 class RasterEngineStrategy : public ApplicationEngineStrategy {
11 public:
12     void setEngine(QApplication& app) override {
13         app.setAttribute(Qt::AA_ForceRasterWidgets, true);
14     }
15 };
16 
17 class OpenGLEngineStrategy : public ApplicationEngineStrategy {
18 public:
19     void setEngine(QApplication& app) override {
20         QSurfaceFormat format;
21         format.setVersion(3, 2);
22         format.setProfile(QSurfaceFormat::CoreProfile);
23         QSurfaceFormat::setDefaultFormat(format);
24     }
25 };
26 
27 class NativeEngineStrategy : public ApplicationEngineStrategy {
28 public:
29     void setEngine(QApplication& app) override {
30         app.setAttribute(Qt::AA_ForceRasterWidgets, false);
31     }
32 };
33 
34 class Application {
35 private:
36     std::unique_ptr<ApplicationEngineStrategy> strategy;
37 public:
38     void setEngineStrategy(std::unique_ptr<ApplicationEngineStrategy> newStrategy) {
39         strategy = std::move(newStrategy);
40     }
41     void applyEngineStrategy(QApplication& app) {
42         if (strategy) {
43             strategy->setEngine(app);
44         }
45     }
46 };
47 
48 int main(int argc, char *argv[])
49 {
50     QApplication a(argc, argv);
51 
52     Application app;
53     // 根据需要选择不同的策略
54     app.setEngineStrategy(std::make_unique<RasterEngineStrategy>());
55     app.applyEngineStrategy(a);
56 
57     // ...
58     return a.exec();
59 }

  在这个例子中,RasterEngineStrategy::setEngine 函数设置了 Qt::AA_ForceRasterWidgets 属性为 true,这会强制 Qt 使用栅格引擎。OpenGLEngineStrategy::setEngine 函数设置了默认的 QSurfaceFormat,这会使 Qt 使用 OpenGL 引擎。NativeEngineStrategy::setEngine 函数设置了 Qt::AA_ForceRasterWidgets 属性为 false,这会使 Qt 使用本地绘图系统。

  在这个例子中,ApplicationEngineStrategy 是一个抽象基类,它定义了一个虚函数 setEngine。这个函数接受一个 QApplication 引用,并设置其渲染引擎。

  Application 类有一个 ApplicationEngineStrategy 的唯一指针成员 strategy。它有一个 setEngineStrategy 函数,用于设置策略,和一个 applyEngineStrategy 函数,用于应用策略。

  这样,你可以在运行时根据需要选择不同的渲染引擎。例如,你可以这样使用这个策略模式:

 1 int main(int argc, char *argv[])
 2 {
 3     QApplication a(argc, argv);
 4 
 5     Application app;
 6     if (useRasterEngine) {
 7         app.setEngineStrategy(std::make_unique<RasterEngineStrategy>());
 8     } else if (useOpenGLEngine) {
 9         app.setEngineStrategy(std::make_unique<OpenGLEngineStrategy>());
10     } else {
11         app.setEngineStrategy(std::make_unique<NativeEngineStrategy>());
12     }
13     app.applyEngineStrategy(a);
14 
15     // ...
16 }

  在这个例子中,useRasterEngine、useOpenGLEngine 和 useNativeEngine 是你的应用程序的配置选项,你可以根据需要设置它们的值。

默认行为
  Qt 默认会尝试使用最佳的渲染引擎,这通常是本地绘图系统或者 OpenGL,取决于你的硬件和操作系统。如果你没有特别的需求,你通常不需要手动设置渲染引擎。

  然而,有些情况下你可能需要手动设置渲染引擎。例如,如果你的应用程序需要一些特殊的渲染效果,你可能需要强制使用 OpenGL。或者,如果你的硬件不支持 OpenGL,你可能需要强制使用栅格引擎。

  至于获取当前的渲染引擎,Qt 没有直接的 API 可以做到这一点。但你可以通过检查一些相关的属性或状态来推测出当前的渲染引擎。例如,你可以检查 Qt::AA_ForceRasterWidgets 属性,如果它是 true,那么 Qt 应该正在使用栅格引擎。或者,你可以检查一个 QWidget 的 paintEngine 方法返回的 QPaintEngine 对象的类型,如果它是 QOpenGLPaintEngine,那么 Qt 应该正在使用 OpenGL。但请注意,这些方法都不是 100% 可靠的,因为 Qt 可能会在不同的窗口或控件中使用不同的渲染引擎。

结语
  在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

  这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

  我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

标签:Qt,OpenGL,渲染,栅格,引擎,绘图,qt
From: https://www.cnblogs.com/ybqjymy/p/17622804.html

相关文章

  • Qt 渲染
    1)Qt::AA_UseDesktopOpenGL使用显卡的openGL库,且要求支持openGL2.1及以上的版本。因此很多老旧设备是不满足版本要求的(windows默认的驱动版本只支持openGL1.1)。(依赖硬件,即硬件加速渲染)2)Qt::AA_UseOpenGLES使用Angle库来将DirectX11或者DirectX9的接口转成OpenGLES2.0的API,从......
  • QT网络通信
    QT进行TCP网络通信:1.TCP是C/S模式的需要建立连接的网络通信架构,建立连接需要进行三次握手,断开连接需要四次握手。2.服务器模式:需要先创建监听套接字,通过bind函数进行ip和端口绑定,通过listen函数监听客户端的连接请求,通过accept函数处理客户端的连接请求并返回通信套接字进行通信......
  • 轻量的工作流引擎:告别低效,创造新高!
    伴随着日益激烈的市场竞争,作为新时代的企业,如何在众多同质化竞争中脱颖而出,占有更多的市场份额,实现更大发展?此时此刻就需要拥有不同寻常的头脑,寻找不平常的路径,轻量的工作流引擎是低代码技术平台中的重要功能,可以满足业务量激增的业务发展需求,帮助不同行业的客户告别低效率工作,再......
  • 驱动物联双引擎 构筑合作新赛道丨计讯物联应邀出席创新发展沙龙,共谋发展促双赢
    8月8日,由厦门市物联网行业协会主办,中国联通厦门分公司承办的“驱动物联双引擎构筑合作新赛道”创新发展沙龙盛大开启。此次沙龙邀请了数字科技、物联网等多名企业管理者、专家及代表汇聚一堂,围绕物联网连接技术、物联网连接安全等话题进行探讨,并就技术产品、实践方案及生态合作等......
  • 字节跳动基于火山引擎DataLeap的一站式数据治理架构实践
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群在7月22日举行的ArchSummit全球架构师峰会(深圳站)上,来自火山引擎DataLeap的技术专家为大家带来了字节跳动基于火山引擎DataLeap的全域数据治理方案分享。本次分享共分为机遇挑战、字节数......
  • 《C++ GUI Qt4编程》第2章——创建对话框——深入介绍信号和槽
    槽和普通的C++成员函数几乎是一样的——可以是虚函数;可以被重载;可以是公有的、保护的或者私有的,并且也可以被其他C++成员函数直接调用,它们的参数可以是任意类型。唯一不同的是:槽还可以和信号连接在一起,在这种情况下,每当发射这个信号的时候,就会自动调用这个槽。connect(sender,SI......
  • QT鼠标图标显示与隐藏
    1.如果只希望在某个widget中不显示鼠标指针,那么在该widget的构造函数中调用QWidget::setCursor(QCursor(Qt::BlankCursor))2.如果希望整个应用程序不显示鼠标指针,那么在实例化Application后调用QApplication::setOverrideCursor(Qt::BlankCursor);3.可以在任一控件......
  • Drools 7.67.0 + DMN 1.2 + SpringBoot3 构建规则引擎
    背景:基于项目工作的需要,要建立一个规则引擎的应用集中式的管理业务中的规则流程等,所以先探索一个MVP1.什么是规则引擎,同类竟品?规则引擎的主要思想是将应用程序中的业务决策部分分离出来,并使用预定义的语义模板编写业务决策(业务规则),由用户或开发者在需要时进行配置、管理。需......
  • 一个轻量级的脚本规则引擎工具 Aviator Script
    告别ifelse!试试这款轻量级流程引擎吧,跟SpringBoot绝配!(qq.com) println("HelloAviatorScript!");a=b+c;println("a="+a);执行:packagecom.yuyi.advanced.pis;importcom.googlecode.aviator.AviatorEvaluator;importcom.googlecode.aviator.Expression......
  • 火山引擎开发者社区一周资讯精选(8.5-8.11)
    ......