使用任意 QML 项目作为缓存图像源 [英] Using arbitrary QML items as cached image source

查看:16
本文介绍了使用任意 QML 项目作为缓存图像源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

原始问题仍包含在下面,但我决定重新命名为在各种情况下对开发人员更有用的表单,其中一些在我下面的回答中描述,作为解决原来的问题提供了更广泛的应用领域.

The original question is still contained below, but I decided to re-title to a form that will be more useful to developers in a variety of cases, some of which described in my answer below, as the solution to the original problem turned out to provide a much wider area of application.

我有一组用于应用程序的灰度图标,并且要求用户可以更改图标颜色.

I have a set of greyscale icons for an application, and a requirement that the icon color can be changed by the user.

因此,显而易见的解决方案是使用 QtGraphicalEffects 中的常规 Colorize 元素.

So, the obvious solution is to use the stock Colorize element from QtGraphicalEffects.

效果本身有一个 cached 属性 - 它缓存特定效果的结果,因此不会连续计算.但是,这只适用于效果的特定实例,这意味着如果有多个图标实例,并且每个实例都有着色效果,则此缓存不会在不同实例之间共享.

The effect itself has a cached property - which caches the result of that particular effect so that it is not continuously calculated. However, this only applies to that particular instance of the effect, meaning if there are multiple icon instances, and every one has a colorize effect, this cache will not be shared between the different instances.

显然,一个缓存就足够了,考虑到所有图标的大小和颜色都相同,可以重复使用来自 VRAM 的数据,从而节省 VRAM 和 GPU 时间.

Obviously, one single cache would be enough, considering that all icons are the same size and color, that data from VRAM can be reused, saving on VRAM and GPU time.

所以最大的问题是如何重用单个效果的单个缓存并多次显示它而没有任何开销.

So the big question is how to reuse that single cache of that single effect and display it multiple times without any overheads.

另外,上一个问题是关于我目前使用着色图标所学的课程.但是,我可能缺少另一种方法.

Also, the previous question is regarding the current course I've taken with colorizing icons. However, there might be another approach I am missing.

当然,效率是关键,但也需要简单,我的意思是我可以想到几种低级方法来非常有效地做到这一点,但它们都需要更复杂的低级实现,而在 QML 中是不可能的.

Naturally, efficiency is key, but simplicity is also desired, I mean I can think of several low level ways to do that very efficiently, but they all require more complex low level implementations, they are not possible to do in QML.

推荐答案

结果出乎意料的简单.

在这种情况下,特定于 OP - 即为图标着色,最有效的方法是简单地使用自定义 ShaderEffecttrivial 片段着色器 - 设置 gl_FragColor 到所需的颜色,作为 vec4 和源图像的 alpha 值传递.真的不需要缓存任何东西,因为着色器真的很简单,而且速度很快.

In the case, specific to the OP - that is colorize icons, the most efficient way is to simply use a custom ShaderEffect with a trivial fragment shader - set gl_FragColor to the desired color, passed as a vec4 and the alpha value from the source image. There is really no need to cache anything, as the shader is really simple and fast, as fast as it gets.

只有一件事需要考虑 - QML 场景图可能会在纹理图集中分配原始图像,然后默认实现会将纹理从图集中复制到另一个纹理.我们不希望这样做,因为它违背了目的 - VRAM 使用会增加,因为这将针对每个实例"进行,并且新分配的纹理也有可能大于它们需要的大小应该是,因为在某些平台上,纹理的大小是有限制的,在这种情况下,我们谈论的是图标,所以它们不会那么大.

There is only one thing to consider - the possibility that the QML scenegraph might allocate the original image in a texture atlas, the default implementation will then copy the texture from the atlas to another texture. We do not want this as it defeats the purpose - VRAM usage will rise, as this will be done for every "instance" and there is also the possibility that the newly allocate textures will be larger than they need to be, since on some platforms, there is a limitation to how small a texture can be, and in this case we are talking icons, so they won't be all that big.

解决方案是将 supportsAtlasTextures 显式设置为 true.这意味着您还必须在图集中传递纹理的偏移量并计算偏移量 - 仍然很少有开销.这将确保效率,来自图集的纹理不会在内存中重复,此外,渲染引擎实际上将允许使用来自同一图集的不同纹理的不同着色器效果在一次调用中批处理在一起.

The solution is to explicitly set supportsAtlasTextures to true. This means you must also pass the offset of the texture in the atlas and calculate the offset - still very little overhead. This will ensure efficiency, textures from atlases will not be duplicated in memory, and furthermore, the render engine will actually allow different shader effects using different texture from the same atlas to be batched together in one call.

类似的方法可用于缓存几乎所有内容,并使用该缓存来显示图像" - 使用 ShaderEffectSource 来捕获"所需的图像,然后使用 ShaderEffect 带有更简单的片段着色器 - 只需从源采样器输出数据.立即想到几个非常有用的用例:

A similar approach can be used to cache pretty much anything, and use that cache to display an "image" - use a ShaderEffectSource to "capture" the desired image, and then use a ShaderEffect with an even more trivial fragment shader - simply output the data from the source sampler. Several extremely useful use-cases immediately come to mind:

  • 它可用于实例化"图像,这是计算密集型着色器的结果,请记住 ShaderEffectSourceShaderEffect 可以以任意顺序链接
  • 它可以用于实例化程序生成的图像,再次使用着色器,例如可以用作平铺纹理,甚至可以非常有效地制作动画
  • 它可以与 QML Canvas 一起使用,将复杂的画布绘图用作多个图像"的缓存和源
  • 它可以用作图像,由复杂的 QML Items 组成——这些实际上在 RAM 上相当重,想象一下你有 1000 个对象的场景,并且它们中的每一个都由 20 个不同的 QML 项目组成——矩形、文本、图像、上帝禁止的动画,内存中有 20000 个对象——根据我的测试,这就像 500 MB 的 RAM 使用量,但如果它们相同,单个对象可以用于提供缓存,所有其他对象只能使用单个着色器效果来显示该缓存.它也对 CPU 时间有影响 - 比如说你的设计必然会改变值 - 一个非常常见的场景,如果你在内存中有 20000 个对象,那就是 20000 个评估绑定 - 即使对于微不足道的表达式,这在移动设备上也可能需要几秒钟,在这段时间内冻结屏幕.缓存将冻结时间减少 1000 倍,几乎不存在.

  • it can be used to "instantiate" images, the result of computationally intenssive shaders, keep in mind that ShaderEffectSources and ShaderEffects can be chained in arbitrary order
  • it can be used to instantiate procedurally generated images, once again using shaders, such can be used as tiling textures, and even animated very efficiently
  • it can be used together with a QML Canvas to use a complex canvas drawing as a cache and source for multiple "images"
  • it can be used as an image, produced by the composition of complex QML Items - those are actually quite heavy on RAM, imagine a scenario where you have a 1000 objects, and each of them is made out of 20 different QML items - rectangles, texts, images, god forbid animations, that's 20000 object in memory - that's like 500 MBs of RAM usage based on my tests, but if they are identical, a single object can be used to provide cache, and all the other objects can only use a single shader effect to display that cache. It has implications on CPU time as well - say your design is bound to changing values - a very usual scenario, if you have 20000 objects in memory, that's 20000 evaluated bindings - even for trivial expressions this may take several seconds on a mobile device, freezing the screen for that duration. Caching that will reduce the freeze time 1000 times, practically to non-existent.

它还可用于缓存和实例化动画,显着减少所需的 CPU 时间,还可以处理视频

it can can also be used to cache and instantiate animations, significantly reducing the needed CPU time, and also it can work with video as well

这篇关于使用任意 QML 项目作为缓存图像源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆