Qt Quick WebGL在Qt 5.12中正式发布

作者:Richard Lin | Dec 5, 2018 5:58:50 AM

本文翻译自Qt Quick WebGL release in Qt 5.12 原文作者:Artem Sidyakin 校审:Richard Lin Qt 5.12一个新功能是Qt Quick WebGL平台插件(之前称为WebGL streaming)。之前曾在Qt 5.10中发布了技术预览版,从Qt 5.12开始,它是一个正式发布的功能。 这篇文章有点长,所以列个目录先。

简而言之

$ ./your-qt-application -platform webgl:port=8998

介绍

推荐您参考以下几篇介绍WebGL英文版博文:

软件开发和UX设计供应商ICS的Jeff Tranter也曾经写过一篇不错的文章。 本文是从普通的Qt“用户”角度出发的“拆箱”体验描述 —— 我从未亲自试用过Qt Quick WebGL streaming,也没有参与其开发。

什么是WebGL streaming

如果您曾阅读上面提到的几篇博文,请跳过此段落。但我仍然建议阅读相应手册。 WebGL streaming是一个QPA插件,它通过网络发送Qt Quick应用程序的OpenGL调用(“流式”),然后将这些调用转换为WebGL格式的调用,从而可以在HTML5 Canvas中渲染。这就让您可以在远程主机上运行应用程序,并在本地Web浏览器中呈现其GUI。 以下是它的示意图: 这里还有一个来自KDE Akcademy的视频,以及来自Jesus Fernandez的详细讲解。 但因为我是初级Qt“用户”,所以并不关心其中隐藏的细节,我的理解如下: 我可以在某些设备上运行基于Qt的应用程序,或者说在我的iPad上使用Safari运行Qt程序。听上去不错。 当然,这个设备(此处指树莓派)可能是指一台“托管”应用程序的桌面电脑,但我认为WebGL streaming主要用于嵌入式平台(参见之后的用例章节)。 现在让我来重点介绍一下前面说到的几个特性:

  • 应用程序本身不在 Web浏览器中运行。Web浏览器仅渲染其GUI;
  • 所以它既不是视频流,也不是镜像。它是在Web浏览器中显示的“解耦”的应用程序的GUI;
  • 由于它仅适用于OpenGL(ES),因此WebGL流不适用于Widgets或任何其他非OpenGL内容。

事实上如果您尝试使用WebGL QPA启动某些“不兼容”的Qt应用程序,很可能会出现以下的错误:

qt.qpa.webgl: WebGL QPA platform plugin: Raster surfaces are not supported

如何使用

您只需要安装它: 如果您不是利用安装包安装,请照常从源代码构建Qt,构建过程无需特殊配置。实际上在早期版本中,必须使用-opengl es2选项,但是现在不再需要了,因为即使安装了更高版本的OpenGL,Qt Quick Scene Graph仍可以使用ES这个子集。 安装Qt后,您可以构建任何Qt Quick应用程序,并使用以下命令行参数启动它:

$ ./your-qt-application -platform webgl

您不需要在源代码中进行任何修改,它就能运行。在Web浏览器中打开以下地址:127.0.0.1:8080,127.0.0.1是运行应用程序的主机IP地址。 如果要使用其他端口,可以像下面这样指定:

$ ./your-qt-application -platform webgl:port=8998

毋庸置疑,Qt WebGL是跨平台的,它可以很好的兼容Linux,Mac OS和Windows。只是启动应用程序的方式有一些差异: Linux:

./your-qt-application -platform webgl:port=8998

MacOS:

QT_QPA_PLATFORM=webgl:port=8998 ./your-qt-application.app/Contents/MacOS/your-qt-application

...因为我现在用的这版Qt显然忽略了-platform选项(这听上去像是需要报告的bug)。 Windows:

your-qt-application.exe -platform webgl:port=8998

当然您也可以使用一种跨平台的方式(讲究)来实现,在main.cpp中使用qputenv()方法

// ...
qputenv("QT_QPA_PLATFORM", "webgl:port=8998");
QGuiApplication app(argc, argv);
// ...

在网络浏览器的支持方面,我尝试了几个浏览器(除了某个用trident内核的和他的小兄弟之外)都能运行,看起来WebGL在现代浏览器中得到了很好的支持。虽然我确实偶尔经历了几次页面重新加载,并且在基于Android的平板电脑上,Chrome甚至崩溃了一次。显然它不算完美,但这确实超出了Qt的覆盖范围。 关于性能,最“忙”的时间是在web浏览器正在接收缓冲区、纹理、字形、地图集等数据的初始化阶段。在第一次绘制调用之后,带宽使用率就非常低。顺便说一句,由于OpenGL ES调用是作为二进制数据发送的,因此它应该比VNC更“轻量级”。我实际上正在考虑再写一篇博文在网络利用率方面把WebGL streaming和VNC做一次比较。

示例

在以前的博文中已经有相当数量的演示视频,这里也有一个不错的集合,今天我来补充几个我自己的。

设备信息

这是一个相当简单的演示应用程序。它收集了一些系统信息。例如,这是我在Mac上运行它时显示的内容: [embed]http://git.qt.io/arsidyak/webgl-release/raw/master/webgl-release-blog/img/di.mp4[/embed] 现在让我们使用WebGL streaming插件在树莓派上运行它,从同一台Mac上的Web浏览器连接到它,非常确定它不再将Mac OS报告为操作系统,现在平台是webgl。这儿还要注意一件事- 当改变“屏幕”分辨率时: [embed]https://git.qt.io/arsidyak/webgl-release/raw/master/webgl-release-blog/img/webgl-different-canvas-sizes.mp4[/embed] 您可以看到,当我调整浏览器窗口大小时,应用程序(在很好地调整其布局的同时)也报告了屏幕分辨率的更改值。这是因为它需要根据canvas的尺寸调整分辨率。我们在Web浏览器检查器中检查一下: 我们也可以在这里看看用户的输入事件: 因此应用程序确实在树莓派上运行,而我在浏览器中所拥有的只是它的“流式”GUI。

相机

这个演示更加实用:由机器人手臂控制的相机安装在树莓派设备上: 目的是通过设备端基于Qt的程序来控制摄像机(平移和倾斜),而现在是通过某个平板电脑上的Web浏览器远程执行此操作。我们希望看到相机的取景器内容,或者用机拍照也很不错。 以下是此类设置所需的硬件列表:

这就是我用来组装它的手册。 现在我说点题外话(剧透:接下来我要安利Qt商业版功能)。您可能已经注意到,对于设备信息的演示,我使用了Boot to Qt的镜像。在它的帮助下,在向树莓派构建和部署基于Qt的应用程序的过程中节省了我相当多的时间和精力。 但Boot to Qt是商业版特性,如果没有它,您必须采取更多步骤来设置系统环境。以常规Raspbian Stretch Lite镜像为例,您需要做如下工作:

  • 由于使用了Qt Multimedia模块,您需要确保系统中已安装GStreamer,并且您已安装了正确的插件;
  • 获取树莓派的最新Qt版本(12)。在桌面上设置交叉编译工具链或在设备上构建它。直接在树莓派上从源代码构建Qt实际上是一个不错的选择(特别是如果您使用交叉编译工具链遇到错误),虽然编译本身需要大约10个小时并且需要增加可用的swap分区尺寸(1 GB的RAM真心不够);
  • 构建V4L驱动程序,使GStreamer和Qt可以发现相机;
  • 想出一种在设备上构建/部署应用程序的便捷方法。

虽然这个步骤列表看起来不是太长,但实际上它可能需要您几天的时间,如果使用Boot to Qt镜像,您将获得开箱即用的体验,并且您可以在Qt Creator上直接连接设备,运行您的应用程序。商业推广结束,让我们回到演示上来。 GUI布局如下所示: 第一个选项卡上的大部分空间由相机的取景器占据,该取景器通过VideoOutputCamera本身实现:

Camera { id : camera }
 
VideoOutput {
     anchors.fill: parent
     fillMode: VideoOutput.PreserveAspectCrop
     source : camera
}

它有一个水平和一个垂直的滑块 —— 用于控制摄像机云台的左右和上下:

Slider {
id: sliderTilt
orientation: Qt.Vertical
from: root.maxValue
value: 0
stepSize: 1
to: -root.maxValue

onPressedChanged: {
if (!pressed)
{
backend.movePanTilt(basePath, sliderPan.value, sliderTilt.value)
}
}
}

Pan-Tilt HAT伺服系统是通过I2C接口工作的,由于时间原因,我使用Pimoroni的Python库来快速解决。在某些时候,我甚至想用C / C ++优雅地重构该功能,但它并非此次演示的重点。 还有一个控制CameraCapture拍照的按钮

Button {
scale: hovered ? (pressed ? 0.9 : 1.1) : 1

background: Rectangle {
color: "transparent"
}

Image {
anchors.fill: parent
source: "/img/camera.png"
}

onClicked: {
camera.imageCapture.captureToLocation(basePath + "shots/" + getCurrentDateTime() + ".jpg");
}
}

第二个标签包含了拍摄的照片列表: ...用FolderListModel实现:

ListView {
FolderListModel {
folder: "file:" + basePath + "shots/"
nameFilters: ["*.jpg"]
}

model: folderModel

delegate: ItemDelegate {
text: model.fileName
}
}

此处提供完整的应用程序源代码。 现在让我们看看它的实际效果。我的桌子上围着相机放着3个精灵头像,我想拍几张照片。我在设备上用参数-platform webgl构建并运行应用程序,并通过iPad上的Safari通过Wi-Fi连接到应用程序: 正如您所看到的,结果很好,看到相机的取景器,我可以远程控制它的位置并拍摄我感兴趣的物体的照片。

用例

WebGL streaming最有用的用例是能够为一些具有有限计算能力的低端设备提供合适的GUI且无需GPU,甚至很多情况下这些设备根本没有任何显示功能。例如,在工业自动化领域常见的场景中,您可以在整个工厂安装大量无显示的设备:它们可以分布在相当大的区域,甚至可以安装在有危险环境的地方 —— 如果能够对这些设备进行远程控制和配置那就非常实用了。 在读Hacker News上的讨论时,我突然产生了一个“相反”的想法:如果“设备”实际上是一个非常强大的服务器,您可以在常规电脑上的Web浏览器中使用GUI时在服务器上执行一些繁重的计算(实际上需要基于HTML的前端,将在下一个章节中详细讨论)。 另一个可能的用例是反盗版措施。假设您希望保护您的软件不被“破解”或“盗版”。显然,如果客户端上没有运行,那么没有什么可以破解,因为您的用户只在其浏览器中呈现GUI,并且应用程序本身正在您的服务器上运行。听起来不错但是有几个缺点:

  • 虽然WebGL streaming在本地网络中表现良好,但通过互联网使用它会导致显著的延迟;
  • 连接未加密,因此不安全;
  • 目前,一次只支持一个连接(也就是说只有一个用户)。

总的来说,一次仅支持一个连接大幅减少了应用场景,遗憾的是,该功能当前在实现中不太可能得到改进,这可能是Qt 6中需要完成的一个任务。顺便补充一点,流式传输可以实现屏幕镜像功能,因为在某些场景下,镜像功能非常重要。 谈到屏幕镜像,我想提一下我们最近与韬睿合办的网络研讨会。在那里,您可以看到WebGL streaming和Remote Objects的有趣组合,它允许您实现上述所有功能。 WebGL streaming的另一个值得注意的方面是所谓的“零安装”概念 —— 您不必在客户端(台式机/平板电脑/智能手机/等)上安装/部署任何东西,因为唯一需要的只是一个Web浏览器。但是,Qt WebAssembly似乎更适合这个目的。 WebGL streaming与传统web技术的比较 有些人可能会问,WebGL streaming存在的根本价值在哪里?因为它是运行在web浏览器上的技术,人们完全可以使用常规的web服务器并创建一个web应用程序 —— 结果几乎是相同的:后端托管在远程设备上,基于HTML的前端在web浏览器中渲染GUI。 这是一个非常好也很公平的问题。我实际上有一些网络开发的经验,所以我自己提出了这个问题。让我试着回答一下,希望不要引起另一场圣战。 实际上,在某些情况下,只需要一个简单的REST API就足够了,特别是如果您只需要获得一些纯文本数据值。因此,在此类场景中基于Qt的WebGL streaming应用可能会被秒杀。 但是,在更复杂的场景中(例如,当您需要控制某些硬件时),可能更适合使用基于Qt WebGL streaming的 GUI应用程序,因为这样您将获得强大的后端(基于C ++ / Qt),使用Qt Quick比HTML / CSS / JS 创建一个复杂、有吸引力且高性能的前端更容易(相当简单),但这个结论看起来像是另一场圣战的开始,所以我会把它当作我的个人意见。 最后值得一提的是,如果您已经拥有一个基于Qt的应用程序,那么WebGL streaming是一个显而易见的选择,因为它可以让您不需要花费任何成本地拥有一个远程GUI。

许可/定价

WebGL streaming插件可在商业和开源许可下使用(但仅限GPLv3)。对于商业客户而言,它包含在应用程序开发和设备创建产品中,无需额外费用。

结论

您现在可以毫不费力地将web浏览器用作Qt Quick应用程序的远程GUI客户端:它只需要一个命令行参数。 在未来开发方面,我认为接下来要做的是WebSocket和WebServer的连接安全/加密。WebSocket部分应该非常简单,因为QWebSocket已经支持安全连接(wss://)。WebServer部分,如果您还记得,它从一开始就是一个临时解决方案,对正确实现(包括支持HTTPS)的研究仍在进行中。 同时,如果您有任何其他功能请求或可能要报告的错误,请使用我们的项目追踪:http://bugreports.qt.io/选择QPAWebGL组件)。您的反馈意见将有助于我们的产品管理团队确定功能的路线图。

 
 
G
M
T
 
  Detect language Afrikaans Albanian Amharic Arabic Armenian Azerbaijani Basque Belarusian Bengali Bosnian Bulgarian Catalan Cebuano Chichewa Chinese (Simplified) Chinese (Traditional) Corsican Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Frisian Galician Georgian German Greek Gujarati Haitian Creole Hausa Hawaiian Hebrew Hindi Hmong Hungarian Icelandic Igbo Indonesian Irish Italian Japanese Javanese Kannada Kazakh Khmer Korean Kurdish Kyrgyz Lao Latin Latvian Lithuanian Luxembourgish Macedonian Malagasy Malay Malayalam Maltese Maori Marathi Mongolian Myanmar (Burmese) Nepali Norwegian Pashto Persian Polish Portuguese Punjabi Romanian Russian Samoan Scots Gaelic Serbian Sesotho Shona Sindhi Sinhala Slovak Slovenian Somali Spanish Sundanese Swahili Swedish Tajik Tamil Telugu Thai Turkish Ukrainian Urdu Uzbek Vietnamese Welsh Xhosa Yiddish Yoruba Zulu   Afrikaans Albanian Amharic Arabic Armenian Azerbaijani Basque Belarusian Bengali Bosnian Bulgarian Catalan Cebuano Chichewa Chinese (Simplified) Chinese (Traditional) Corsican Croatian Czech Danish Dutch English Esperanto Estonian Filipino Finnish French Frisian Galician Georgian German Greek Gujarati Haitian Creole Hausa Hawaiian Hebrew Hindi Hmong Hungarian Icelandic Igbo Indonesian Irish Italian Japanese Javanese Kannada Kazakh Khmer Korean Kurdish Kyrgyz Lao Latin Latvian Lithuanian Luxembourgish Macedonian Malagasy Malay Malayalam Maltese Maori Marathi Mongolian Myanmar (Burmese) Nepali Norwegian Pashto Persian Polish Portuguese Punjabi Romanian Russian Samoan Scots Gaelic Serbian Sesotho Shona Sindhi Sinhala Slovak Slovenian Somali Spanish Sundanese Swahili Swedish Tajik Tamil Telugu Thai Turkish Ukrainian Urdu Uzbek Vietnamese Welsh Xhosa Yiddish Yoruba Zulu          
 
 
 
Text-to-speech function is limited to 200 characters
 
    Options : History : Feedback : Donate Close