Qt 如何在QQuickFramebufferObject中呈现文本?
动机:目前,我的QML场景中有1000个简单项目,其中一个项目以60fps的速度制作动画,因此整个场景以60fps的速度重新绘制。在我的电脑上,我的4个虚拟内核的Cpu使用率平均为15%。在目标硬件上,情况更糟——4个物理内核的Cpu使用率为60%,导致过热,导致冻结。请注意,我已经实现了一个优化:通过Qt 如何在QQuickFramebufferObject中呈现文本?,qt,opengl,text,qml,qtquick2,Qt,Opengl,Text,Qml,Qtquick2,动机:目前,我的QML场景中有1000个简单项目,其中一个项目以60fps的速度制作动画,因此整个场景以60fps的速度重新绘制。在我的电脑上,我的4个虚拟内核的Cpu使用率平均为15%。在目标硬件上,情况更糟——4个物理内核的Cpu使用率为60%,导致过热,导致冻结。请注意,我已经实现了一个优化:通过Loaders,卸载(滚动)视口之外的所有项目(因此,在任何给定时间只有~18个项目被加载)。我报告的性能统计是有了这个优化-没有它,情况会更糟 我的解决方案是开始在一个QQuickFramebu
Loader
s,卸载(滚动)视口之外的所有项目(因此,在任何给定时间只有~18个项目被加载)。我报告的性能统计是有了这个优化-没有它,情况会更糟
我的解决方案是开始在一个QQuickFramebufferObject中绘制所有1000个项,并停止将它们作为实际的QML项。这样,我就不会因为只有1000件(未卸载!)物品而受到Qt的惩罚
我的困境是:如何在OpenGL中绘制项目的文本部分
方法1:我知道QPainter可以直接将文本呈现到QOpenGLWidget中,但QQFBO中似乎没有这个选项
方法2:在具有层的QML中使用单个无父文本
项。启用:true
,设置其文本
属性,等待1帧(使其渲染),然后获取纹理。有些丑陋和迂回;也可能是缓慢的
方法3:查看QQuickText的源代码,看看它有什么魔力,然后复制它。可能很难,我必须遵守许可证限制
方法4:使用QPaint将软件渲染到QImage,然后将该图像上载到纹理。优雅,但可能太慢
有什么建议可以解决这些方法中的问题吗?不完全清楚为什么渲染一个项目会使整个场景重新绘制。但如果只有一个项目正在设置动画,则可能需要分割场景。那些不移动的应该放在父项中,移动的可以放在外部 有一种相当简单的方法可以将子树渲染到FBO,只需将子树渲染到不执行任何操作的FBO即可 此示例使用灰度着色器()渲染图像: ShaderEffect只是一个“渲染到纹理”(render to texture),您可以看到一个矩形中填充了对象的图片。在本例中,错觉仍然存在,但动画对象仅处理单个纹理矩形 我不知道这是否是解决办法,因为问题似乎在别处。请详细说明你的问题,我可能会根据需要更新答案
我知道这似乎是你的第二种方法,但在这种情况下,你渲染纹理你的整个不变的子树。如果我可能猜到,你似乎有一次又一次的滚动文本批处理到GPU,因为一些滚动动画,如果你使用ShaderEffect和一长条项目,你可以只设置滚动窗口的动画,并始终保持文本静态,避免批处理。不完全清楚为什么渲染一个项目会使整个场景重新绘制。但如果只有一个项目正在设置动画,则可能需要分割场景。那些不移动的应该放在父项中,移动的可以放在外部 有一种相当简单的方法可以将子树渲染到FBO,只需将子树渲染到不执行任何操作的FBO即可 此示例使用灰度着色器()渲染图像: ShaderEffect只是一个“渲染到纹理”(render to texture),您可以看到一个矩形中填充了对象的图片。在本例中,错觉仍然存在,但动画对象仅处理单个纹理矩形 我不知道这是否是解决办法,因为问题似乎在别处。请详细说明你的问题,我可能会根据需要更新答案
我知道这似乎是你的第二种方法,但在这种情况下,你渲染纹理你的整个不变的子树。如果我可能猜到,你似乎有一次又一次的滚动文本批处理到GPU,因为一些滚动动画,如果你使用ShaderEffect和一长条项目,你可以只设置滚动窗口的动画,并始终保持文本静态,避免批处理。您是否查看过QML profiler的输出,以了解什么占用了这么多的处理时间?@KubaOber:是的,我查看过;在QML中花费的时间微不足道。因此,我在C++剖析器(CODEXL)中运行了应用程序,发现绝大多数时间都花在了视频卡的驱动程序中,无论是什么奇怪的原因。这在Windows和Linux中都发生过。当我使用我的AMD视频卡时,我使用我的英特尔视频卡(我有可切换的图形)。C++分析器无法计算出在驱动程序中花费的时间。这些时间到底花在了什么特别的功能上?@KubaOber:奇怪,这次它给了我不同的结果。大部分时间花在
QSGRootNode::~QSGRootNode()
,因为它调用QSGNodeUpdater::isnodeblock(QSGNode*,QSGNode*)const
。我查看了Qt源代码,但还没有弄清楚为什么它会调用前者。我将在另一个问题中发布一个测试用例,并为您提供一个链接。@KubaOber:请查看测试用例。您是否查看了QML profiler的输出,以了解什么占用了这么多的处理时间?@KubaOber:是的;在QML中花费的时间微不足道。因此,我在C++剖析器(CODEXL)中运行了应用程序,发现绝大多数时间都花在了视频卡的驱动程序中,无论是什么奇怪的原因。这在Windows和Linux中都发生过。当我使用我的AMD视频卡时,我使用我的英特尔视频卡(我有可切换的图形)。C++分析器无法计算出在驱动程序中花费的时间。这些时间到底花在了什么特别的功能上?@KubaOber:奇怪,这次它给了我不同的结果。大部分时间都花在QSGRootNode::~QSGRootNode()
,因为它调用QSGNodeUpdater::isnodeblock(QSGNode*,
import QtQuick 2.0
Rectangle {
width: 200; height: 100
Row {
Image { id: img;
sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
ShaderEffect {
width: 100; height: 100
property variant src: img
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 coord;
void main() {
coord = qt_MultiTexCoord0;
gl_Position = qt_Matrix * qt_Vertex;
}"
fragmentShader: "
varying highp vec2 coord;
uniform sampler2D src;
uniform lowp float qt_Opacity;
void main() {
lowp vec4 tex = texture2D(src, coord);
gl_FragColor = vec4(vec3(dot(tex.rgb,
vec3(0.344, 0.5, 0.156))),
tex.a) * qt_Opacity;
}"
}
}
}