Qt 4/5和Opengl API之间的opengl速度差异

use*_*637 17 c++ opengl qt qt4 qt5

我已经阅读了关于qt 4和5 opengl的所有关于SO的问题.这是Qt 5中最接近的OpenGL vs QOpenGL/QtOpenGL:差异和局限?,我不知道为什么它被关闭,因为它是一个很好的问题.我看到它缺少的唯一方面是速度差异.

我也读过这个https://qt-project.org/forums/viewthread/22921 ,它有类似的问题,但是来回约4比5,主要讨论新功能.

我的问题是,使用QT5的内置方法比直接使用opengl API制作自定义小部件要快吗?如果我担心性能,那么使用QT是一个糟糕的选择

编辑:

更具体一点,我需要使用physx,tcp/ip通信,以及大量快速更新顶点和网格.目标是尽可能接近实时.像渲染这样的东西不是一个问题,但qt的任何开销都是有害的.(一切都是使用C++的3D)

pep*_*ppe 55

我已经阅读了关于qt 4和5 opengl的所有关于SO的问题.这是Qt 5中最接近的OpenGL vs QOpenGL/QtOpenGL:差异和局限?,我不知道为什么它被关闭,因为它是一个很好的问题.我看到它缺少的唯一方面是速度差异.

更具体一点,我需要使用physx,tcp/ip通信,以及大量快速更新顶点和网格.目标是尽可能接近实时.像渲染这样的东西不是一个问题,但qt的任何开销都是有害的.(一切都是使用C++的3D)

您的问题中有多个问题.

"原始"OpenGL与"Qt"OpenGL

这个问题很糟糕,因为没有"Qt OpenGL"这样的东西.OpenGL是Khronos标准拥有和发布的标准.Qt只是使用它.

Qt可以为您做的是帮助您的应用程序管理多个事情.

窗口/上下文创建

你有没有试过在Win32下创建一个OpenGL上下文?它需要一堆样板代码(参见此处此处),其中包括创建临时上下文以检查WGL功能,然后最终创建实际上下文...

您是否尝试过在X11下创建OpenGL上下文?它需要一堆样板代码(参见此处),其中包括检查GLX_ARB_create_context存在,然后使用它来创建上下文,或者回退到GLX 1.3代码路径并...

您是否曾尝试在Mac OS X下创建OpenGL上下文?

您是否曾尝试在Android下创建OpenGL上下文?

您是否尝试过在QNX下创建OpenGL上下文?

您是否曾尝试在DirectFB/EGLFS下创建OpenGL上下文?

等一下.问:Qt:

class Window : public QWindow {
    QOpenGLContext *context;
public:
    Window() {
        QSurfaceFormat format;
        format.setVersion(3,3);
        format.setProfile(QSurfaceFormat::CoreProfile);

        setSurfaceType(OpenGLSurface);
        setFormat(format);
        create();

        context = new QOpenGLContext;
        context->setFormat(format);
        context->create();
    }
...
Run Code Online (Sandbox Code Playgroud)

是的,就是这样.这创建了一个(顶级)OpenGL窗口和一个3.3核心配置文件上下文.将它与QTimer结合使用,您就拥有了可行的渲染器.这当然适用于所有上述平台:Win32,Mac,X11,Linux/EGLFS,QNX,iOS,Android.


你需要支付所有这些费用吗?当然是.但这绝对可以忽略不计; 并且您只需支付一次,即创建窗口和上下文时.

真正重要的东西来自OpenGL绘图本身,它完全在您的控制之下:您在窗口上创建上下文并开始发出原始OpenGL命令.Qt不在那里.Qt和OpenGL再次见面的唯一时刻是交换缓冲时间; 但这是一项几乎没有成本的操作.

所以:Qt不会增加任何可衡量的开销.

窗口管理

当然,与上述捆绑在一起的事实是,您可以在任何这些平台上使用相同的代码处理键盘和鼠标输入.或者调整窗口大小.或者全屏.或者关闭它.

OpenGL助手

Qt并不"只是"提供一种创建OpenGL表面和上下文的方法(以及相关操作:设置为当前,交换缓冲区等).它(更进一步),并提供了一整套辅助类和函数:

  • QMatrix4x4是一个... 4x4矩阵.其中有你在OpenGL程序需要很好的功能:lookAt(),ortho(),perspective(),normalMatrix(),等.
  • QOpenGLContext :: hasExtensionQOpenGLContext :: getProcAddress是解决OpenGL入口点的独立于平台的方法.
  • QOpenGLContext :: versionFunctions返回一个对象,其中包含已解析的给定版本/配置文件的所有OpenGL入口点.
  • QOpenGLBuffer包装一个缓冲对象.
  • QOpenGLVertexArrayObject包装顶点数组对象(并具有RAII帮助程序以绑定和取消绑定VAO).
  • QOpenGLTexture包装纹理对象.
  • QOpenGLFrameBufferObject包装帧缓冲区对象.
  • QOpenGLShaderQOpenGLShaderProgram包装着色器和着色器程序,提供了将QMatrix4x4设置为统一变量的便捷方法.因此,您可以使用上述方法计算CPU上给定网格的MVP,然后将其设置为统一.
  • QOpenGLDebugLogger包装GL_KHR_debug用于调试OpenGL应用程序.
  • 和另一堆我现在不记得的东西.

有开销吗?是的,但它再次是最小的,它不涉及如何在OpenGL代码中使用这些对象.如果您的OpenGL代码快速且结构良好,您会发现这些帮助程序对管理它很有用,并且它们不会使它运行得更慢.

("有用于管理它"的示例:QOpenGLVertexArrayObject将允许您在OpenGL 3.0上使用VAO,或在任何GL_ARB_vertex_array_object存在扩展的桌面OpenGL版本上使用VAO ,或者在OpenGL ES2 上使用VAO(如果GL_OES_vertex_array_object存在).您无需解析权限一组函数取决于运行时.Qt将为您执行此操作并提供用于创建,绑定,释放和销毁VAO的相同API.

一切都那么好吗?不,我必须在这里说实话,有一点点可以从一些爱中受益.

例如,QOpenGLFrameBufferObject具有有限的API,不支持任何数量的颜色附件.QOpenGLBuffer需要一些工作来支持更多的缓冲区类型/绑定目标.仍然没有对程序管道的支持.仍然不支持统一缓冲区.

另一方面,你有像QOpenGLTexture这样的东西,它支持最近的功能,如不可变存储和纹理视图.

这是否意味着您无法使用这些功能?当然可以.如果你需要功能,请回到原始的OpenGL代码Qt现在没有给你.或者,考虑将这些功能贡献给Qt!

Qt的

当然,一旦你走Qt路径,你就有了Qt.这意味着,仅在QtCore和QtGui库中:

  • 事件循环
  • 计时器
  • 信号和插槽
  • 线程
  • Unicode字符串+ i18n
  • 集装箱
  • 常用表达
  • 文件处理
  • 插件加载
  • 设置
  • MIME类型
  • 输入处理
  • 图像I/O.
  • 使用光栅引擎进行2d命令式绘画
  • JSON
  • XML
  • 和另一堆我现在不记得的东西.

当然,以上所有都是跨平台的.

顺便说一下,Qt还有:

  • 用于跨平台2d小部件的QtWidgets
  • QtSql用于数据库访问
  • QtNetwork for TCP/UDP/SSL套接字,以及高级HTTP/FTP引擎
  • QtTest进行单元测试
  • 用于嵌入webkit的QtWebkit
  • 和另一堆我现在不记得的东西

Qt 4中的OpenGL与5

在Qt 4和Qt 5中如何处理OpenGL之间是否存在巨大差异?并不是的...

在Qt 4中,用于进行OpenGL渲染的类是QGLWidget.它存在于QtOpenGL模块中(而不是QtGui中 - 请记住Qt 4中的小部件也存在于QtGui中).另外,我上面列出的Qt 5 OpenGL助手的实际部分是QGLFoo名称(fi QGLBuffer而不是QOpenGLBuffer).

在Qt 5中,QtOpenGL模块仍然用于保持旧应用程序的工作.但:

  • QtGui和QtWidgets分道扬 .. QtGui现在包含处理WM的低级别位,创建GL上下文和曲面,2d绘画,以及基本上我上面列出的内容.相反,QtWidgets包含小部件本身.

  • QtOpenGL仍然包含QGL*类,但现在链接到QtWidgets(因为它包含QGLWidget).这意味着使用QGLWidget意味着即使您根本不使用小部件,也会链接到某个大型库(因为您的应用程序是纯OpenGL).

  • 正如我之前所展示的,QtGui足以创建一个顶级的OpenGL窗口.但是如果你想将它嵌入基于小部件的应用程序中该怎么办?然后你仍然可以使用QGLWidget或嵌入QWindow通过QWidget::createWindowContainer.除了QGLWidget之外,您不应该使用任何其他QtOpenGL(即QGL)类.使用QtGui中的对应项(即QOpenGL类).

  • 所有上面的QOpenGL*类都在QtGui中,而不在QtOpenGL中 ; 它们不仅仅是QGL*对应物(例如没有QGLVertexArrayObject),它们有更多的功能(例如QOpenGLShader支持几何和曲面细分着色器,QGLShader没有),以及一般使用的(因为它们会看到错误修正和改进) ,QGL*不会).

  • 鉴于现在QtGui提供OpenGL支持,期望QGLWidget替换直接出现在QtWidgets中是很自然的.事实上,它有望在5.4(准备工作进入5.3;但不幸的是,功能本身将错过功能冻结).


是否有理由期待Qt 4和Qt 5之间存在巨大的性能差异?不,我希望您的GL代码执行完全相同.最后Qt并没有真正妨碍你.

桌面GL/ES 2

您可以通过配置时间开关使用"Desktop GL"或"ES 2"支持编译Qt 5.它显然会改变QtGui在编译时将使用哪些头文件,以及它将链接到哪些库(libGL或libGLES2等).它还将改变默认的表面格式:上面的QWindow代码将创建一个漂亮的OpenGL ES2表面(并且可能无法创建上下文,因为没有OpenGL ES 3.3,哦,好吧).

但是你明白了:使用相同的代码你也可以支持ES2.

问题(在我看来)是它也将改变一些其他更微妙的东西:例如QOpenGLShader将插入一些宏,如

#define highp
#define mediump
#define lowp
Run Code Online (Sandbox Code Playgroud)

如果您正在使用Desktop GL,请在所有着色器之前.原因是它允许您在ES2和Desktop GL中重复使用相同的着色器,这些着色器缺少精度限定符; 因此它们会被扩展为空的宏擦除.

我认为这些小事并不是真正的收获.也许它们会减少非常小而简单的着色器(以及仅由顶点和碎片着色器制作的程序)的维护.如果Qt不会那么聪明,那会更好.

但您的Desktop GL代码路径可能正在使用更多着色器阶段; 或者通常只使用ES2上没有的功能.最终,它将与您的ES2代码路径明显不同.(想想在3.3核心中你必须使用VAO,而ES2本身并不知道VAO是什么.)

个人咆哮:我讨厌,讨厌,讨厌ES2不像OpenGL配置文件那样的事实,而是自己独立.并且基本上必须有一个不同的代码库才能让ES2满意.Bah bah bah.

视窗

进入痛苦的世界!也称为Windows下的OpenGL驱动程序状态.

基本上,除NVIDIA之外的任何人都在Windows上发布破碎的OpenGL驱动程序.

至少,"开箱即用".升级驱动程序通常有效,但您并不总是要求用户升级其驱动程序.他们是最终用户,而不是职业玩家.也许他们甚至没有管理员权限.

这对于OpenGL应用程序来说是一个问题,特别是对于Qt最强大的工具之一:Qt Quick 2. Qt试图通过使用ANGLE来解决这个问题,ANGLE是一个OpenGL ES2 - > Direct3D转换层.因此,在Windows下,您可以选择

  • 桌面OpenGL构建
  • 通过ANGLE构建OpenGL ES2

选择不相同 - ES2当然意味着忘记做任何严肃的现代GL.但除此之外,这里提供一种或另一种方式的原因.

Qt Quick 2

这很重要,我认为值得一提.

但首先让我们澄清一下:您是否需要使用Qt Quick 2在Qt下构建OpenGL应用程序?不,不,不. Qt Quick 2是一种完全独立的技术,它也利用OpenGL进行渲染.因此,您可以忽略它,只需构建您的OpenGL应用程序.

但Qt Quick 2究竟是什么?它是一个建立在QML语言之上的库,一种用于创建动态UI的声明性语言(现在用于构建系统 ......哦).

请记住区别:QML是语言,Qt Quick 2是一个包含一组可视项目(以及用于创建自己的C++ API)的库,您可以使用QML编程.

Qt Quick 2使用OpenGL来绘制那些视觉项目.这可以保证60 FPS的无撕裂效果,非常低的CPU使用率,各种基于着色器的视觉效果,等等.

所以呢?好吧,你可能有兴趣给它一个踢.例如,API允许它叠加到您绘制的任何纯OpenGL内容上.所以你可以考虑使用Qt Quick 2来处理更传统的UI位 - 按钮,滑块等,同时你可以控制主要内容的渲染.

或者,您可以忽略它存在的事实并继续使用OpenGL.

  • @ user1095108 Peppe是正确的球场.对我来说,一个小的Windows 7应用程序,[静态]编译(http://stackoverflow.com/q/21862989/1329652),在MSVC2012下使用LTCG和RTTI,使用Qt5.2的核心,gui和widgets模块重量大约UPX压缩后10MB或4.5MB.这是一个完整的独立应用程序,它不依赖于除Windows自身库存之外的任何DLL.它比用Qt 4.8编译的相同代码多大约1.5MB.我不会称之为巨大的. (3认同)
  • @user1095108 如果您编写原始的 openGL,您最终会自己重新实现这些好东西,并且没有理由期望它们会比 Qt 更少“错误”。Qt 附带了一个相当广泛的测试套件,其中包括性能回归测试。许多人使用这些好东西,并且主要错误很快就会被压扁。 (2认同)
  • 你的评论不具有建设性.您仍未提供任何技术论据或事实证据来支持您的观点.你带来的那些("巨大的DLL","越野车")是如此公然虚假,很容易被证实.那么我们为什么要相信你是可靠的,"你的经历"说实话呢? (2认同)