我一直在使用 java 中具有透明度的图像,我注意到的一件事是这种图像(荒谬)会影响性能。
例如:如果您正在绘制具有白色背景的图像,则您有 100fps。如果您将其更改为具有透明背景的相同图像,则它会降低到 30 fps。
在互联网上搜索,我找到了一些解决方案,但我没有找到对此的解释。有人可以解释一下为什么会这样吗?
我一直在使用 java 中具有透明度的图像,我注意到的一件事是这种图像(荒谬)会影响性能。
例如:如果您正在绘制具有白色背景的图像,则您有 100fps。如果您将其更改为具有透明背景的相同图像,则它会降低到 30 fps。
在互联网上搜索,我找到了一些解决方案,但我没有找到对此的解释。有人可以解释一下为什么会这样吗?
我不确定在什么上下文图像中(swing?awt?slick2d?javaFX?lwjgl?)所以我会在原则上回答。
请记住,Java 通常在 JIT 启动之前进行解释(仅在某些平台上发生),因此 CPU 密集型操作比其他语言更明显。
让我们来看一个简单的例子,我们需要查看堆叠在每个之上的图像,并且它们很方便地是一维的。
钥匙:
[CAMERA]
不言自明|
是来自相机的想象的视觉光线:
是通过部分透明像素后的此类光线。让我们处理单个不透明图像的最简单情况:
[ CAMERA ]
||||||||||
RGBRG
在最好的情况下,图像可以被复制到视图缓冲区并缩放。现在,到多个图像:
[CAMERA]
|||||||||||||
|||RGBRGB||||
||| ||||
YYYYYYYYYYYYY
在这种情况下,视图可以在转换黄色后将其复制到缓冲区中,然后遮盖顶部图像覆盖的所有区域。
现在,为了透明:
[CAMERA]
|||||||||||||
|||RG||GB||||
||| || ||||
YYYYYYYYYYYYY
在这里,您不能只复制缓冲区。您必须检查上图的每个像素,然后根据透明度有条件地透支或不透支,从而导致性能下降。
请注意,这是一个基本概述,在实际情况下会更加复杂和优化。
至于部分透明度(完整的 Alpha 通道),情况更糟:
[CAMERA]
|||||||||||||
|||RGggGB||||
||| :: ||||
YYYYYYYYYYYYY
正如您在此处看到的,我们仍然需要确定中间像素下方的颜色,这些像素是部分透明的。对于这样的每个像素,都需要进行完整的混合计算,如果倾斜,可能涉及多个像素,具体取决于渲染策略。这显然是此处显示的所有操作中最昂贵的操作。
我想原因很简单:
绘制不透明图像意味着简单地用其他东西替换一个区域(只是一堆内存复制操作)。
绘制透明图像意味着将旧图像与新图像结合起来,其中包括大量的像素颜色计算。
使用GPU可以大大加快上述每个操作。GPU 非常愚蠢,只能进行专门的操作,但它可以并行处理许多像素。这意味着使用 GPU 对上述操作来说是一个巨大的速度优势。
您在抱怨为什么 Java 的减速比 C# 更大。答案很可能是缺少驱动程序。没有它们,必须使用效率较低的 GPU 操作,或者 CPU 必须完成这项工作。