1+1=10

扬长避短 vs 取长补短

Qt与OpenGL小记

最近关于Qt3D模块去留的问题,社区讨论的火热。官方有意去掉这个由KDAB公司开发和维护的采用LGPL授权的Qt3D模块,并建议用户使用非LGPL授权的QtQuick3D模块。感觉Qt越来越不友好了...

简单捋一捋OpenGL的东西,尽管之前没用过,以后也不一定用...

Qt 与 OpenGL

Qt 的早期版本就开始提供对 OpenGL 的支持。

Qt2.x/Qt3.x

Qt 2.x和Qt3.x中,OpenGL的支持类QGLWidget就已经存在,允许开发者将 OpenGL 渲染集成到 Qt 应用程序中。

Qt4.x

在Qt4中,对 OpenGL 的支持上做了大量的改进。QGLWidget 依然是 OpenGL 集成的核心,但 Qt 提供了更多的工具和 API,以便更好地管理 OpenGL 资源和执行更复杂的渲染任务。比如

  • Qt4.2 引入 QGLFramebufferObject 允许离屏渲染
  • Qt4.6 引入 QGLShader 着色器支持
  • Qt4.8 引入 QGLFunctions 来封装OPenGL/ES2.0 API

Qt5.x

Qt 5 带来了对现代 OpenGL 的更好支持,并且重构了存在于旧版本中的许多 OpenGL 类和方法。

Qt5中,OpenGL作为核心功能包含在QtGui中,作为QtQuick的基础。源自Qt4的Qt OpenGL模块被边缘化,官方不再建议在新代码中使用。

  • QtGui中包含一堆QOpenGL开头的类,如 QOpenGLWidgetQOpenGLContextQOpenGLBufferQOpenGLShaderProgram 等,这些类提供了对底层 OpenGL API 的更直接访问

  • QtWidgets中包含 QOpenGLWidget。

OpenGL看起来很美好,用起来,还挺复杂...

OpenGL后端选择???

为解决Windows平台下OpenGL支持不佳的问题,Qt引入 ANGLE,将Direct3D转换为OpenGL ES接口。

编译Qt源码时,可以选择OpenGL

  • configure -opengl desktop
  • configure -opengl es2
  • configure -opengl es2 -no-angle
  • configure -opengl dynamic

用于控制使用系统自带的opengl驱动,使用angle转换的opengl/es2,使用系统自带的opengl的es2,动态选择。

对于dynamic,Qt程序先尝试系统opengl32.dll是否满足要求,复合要求就使用,不符合要求就尝试用Angle,当Qt程序所在环境不能提供合适的OpenGL2.0实现时,它会自动使用软件实现版本opengl32sw.dll。

用户程序使用的OpenGL,可以通过环境变量QT_OPENGL指定

  • desktop
  • angle
  • software

使用系统自带,angle转换的,还是软件实现的OpenGL接口。

还可以通过代码指定

  • Qt::AA_UseDesktopOpenGL
  • Qt::AA_UseOpenGLES
  • Qt::AA_UseSoftwareOpenGL

另外,通过json文件还可以根据运行时显卡进一步配置:

  • disable_desktopgl
  • disable_angle
  • disable_d3d11
  • disable_d3d9

反正,OpenGL要用好,足够烧脑。

  • https://phabricator.kde.org/T6728

Qt6.x

随着Vulkan出现,OpenGL的地位不在。

在 Qt 6 中,QOpenGLWidget 和相关的 OpenGL 类仍然可用,但已经不再QtGui中,在Qt中不再具有核心地位。

Qt 开始引入一个名为 RHI (Rendering Hardware Interface) 的新抽象层。RHI 旨在提供一个统一的 API,它可以映射到 OpenGL、Direct3D、Metal 或 Vulkan 等不同的底层图形 API,使得 Qt 应用程序可以更好地在不同平台上运行,同时利用各平台的本地图形接口。

QRhi

QRhi是Qt Rendering Hardware Interface缩写,它是Qt内部3D接口的抽象层,提供对OpenGL、Vulkan、Metal、Direct3D等抽象。

Qt6使用QRhi取代了Qt5中OpenGL的核心地位。

QtQuick、QtQuick3D 默认都使用QRhi

私有、半公开

  • 在Qt6.6之前,QRhi都是私有的。

  • Qt6.6中,类似qpa,变成半公开的API

  • Qt6.7中,增加公开类 QRhiWidget(注意QRhi其他位于gui模块的类仍然是半公开的)

  • 在Qt6.7之前,使用QWindow进行绘制

Qt6.6之前,官方手册不包含qrhi,有人使用qdoc从qt源码生成对应的qrhi对应的Qt手册

  • https://alpqr.github.io/
  • https://github.com/alpqr/qrhibasis

QRhi后端

通过环境变量QSG_RHI_BACKEND选择:

  • vlukan
  • metal
  • opengl
  • d3d11
  • d3d12

也可以通过代码QSGRendererInterface::GraphicsApi配置:

  • QSGRendererInterface::Software
  • QSGRendererInterface::OpenVG
  • QSGRendererInterface::OpenGL
  • QSGRendererInterface::Direct3D11
  • QSGRendererInterface::Direct3D12
  • QSGRendererInterface::Vulkan
  • QSGRendererInterface::Metal

补遗

Qt官方封装 Widget,能正常处理Widget叠加问题。

以QQuickWindow和QQuickWidget,后者之上可以叠加半透明的Widget,而前者不行。

Qt3D

Qt3D的开发始于Qt在Nokia时期,初始版本使用Qt4.8进行开发,当时由demo可以运行于三大桌面系统和Nokia的N9手机。

Qt5.0 alpha版本发布时,Qt3D是作为essential模块包含着在内的,开发团队似乎在澳大利亚的布里斯班。但是随着Nokia突然转舵,这个团队似乎被就地解散了。所以Qt5.0正式发布时是已经没有这个模块了。

Qt5.5 中出现的 Qt3D是KDAB 公司开发的,和一开始的Qt3D没有多大关系了。

但是,现在,Qt6.8还没有发布。Qt官方已经计划要干掉 Qt3D了(KDAB和官方都没兴趣再维护它)....

  • https://www.qt.io/blog/2012/04/11/qt-3d-and-qt5-qt4-news-and-releases
  • https://www.kdab.com/qt3d-technology-preview-released-qt-5-5-0/

QtQuick3D

不同于Qt3D支持LGPL协议,QtQuick3D和其他后出现的模块一样,不支持LGPL!!!

  • 2017年?,Qt 吸收了 NVIDIA DRIVE Design Studio 这一个3D设计工具
  • 2017年,Qt发布了基于NVIDIA的 Qt 3D Studio 1.0
  • 2018年,Qt 3D Studio 2.0。使用Qt引擎,取代 NVIDIA 渲染引擎。
  • 2019年,Qt Quick 3D 引入到 Qt5.14 中,进而 Qt Design Studio 中
  • 2020年,Qt 3D Studio 2.6。后面还有过2.8版本。最终融入Qt Quick 3D 和 Qt Design Studio 中

API

既然OpenGL相关,不妨放一个API表格:

年份 OpenGL OpenGL ES WebGL Direct3D Direct3D 12 Vulkan Metal
1992 OpenGL 1.0
1995 OpenGL 1.1
1995 DirectX 1.0
1996 DirectX 2.0
1997 DirectX 3.0
1997 DirectX 5.0
1998 OpenGL 1.2
1998 DirectX 6.0
1999 DirectX 7.0
2000 DirectX 8.0
2001 OpenGL 1.3
2002 OpenGL 1.4
2003 OpenGL 1.5 OpenGL ES 1.0
2004 OpenGL 2.0 DirectX 9.0
2006 OpenGL 2.1 DirectX 10
2007 OpenGL ES 2.0
2008 OpenGL 3.0
2009 OpenGL 3.1/3.2 DirectX 11
2010 OpenGL 4.0/3.3
2010 OpenGL 4.1 MacOS和iOS最后支持版本
2011 WebGL 1.0
2012 OpenGL 4.2 OpenGL ES 3.0 DirectX 11.1
2012 OpenGL 4.3
2013 OpenGL 4.4 DirectX 11.2
2014 OpenGL ES 3.1
2015 OpenGL 4.5 Vulkan 1.0 Metal
2016 WebGL 2.0 DirectX 12
2017 OpenGL ES 3.2
2018 Vulkan 1.1
2019 Metal 2
2020 Vulkan 1.2
2021 Metal 3
2022 Vulkan 1.3
2023