gpt4 book ai didi

java - 混合像素(半透明)的更有效方法?

转载 作者:行者123 更新时间:2023-12-01 14:31:56 27 4
gpt4 key购买 nike

我正在为一款小型 2d 游戏在其他图像之上绘制半透明图像。目前要混合图像,我正在使用此处找到的公式:https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending

我的实现如下;

private static int blend(int source, int dest, int trans)
{
double alpha = ((double) trans / 255.0);
int sourceRed = (source >> 16 & 0xff);
int sourceGreen = (source >> 8 & 0xff);
int sourceBlue = (source & 0xff);
int destRed = (dest >> 16 & 0xff);
int destGreen = (dest >> 8 & 0xff);
int destBlue = (dest & 0xff);

int blendedRed = (int) (alpha * sourceRed + (1.0 - alpha) * destRed);
int blendedGreen = (int) (alpha * sourceGreen + (1.0 - alpha) * destGreen);
int blendedBlue = (int) (alpha * sourceBlue + (1.0 - alpha) * destBlue);

return (blendedRed << 16) + (blendedGreen << 8) + blendedBlue;
}

现在,它工作正常,但它有相当高的开销,因为它在每一帧的每个像素上都被调用。与只渲染图像而不混合相比,我的性能下降了大约 30% FPS。

我只是想知道是否有人能想出更好的方法来优化这段代码,因为我可能做了太多的位操作。

最佳答案

不是 java 编码员(所以带着偏见阅读)但你做的一些事情确实是错误的(从我的 C++ 和低级 gfx 的角度来看):

  1. 混合整数和 float

    这需要有时非常昂贵的转换...使用 <0..255> 范围内的整数权重(alpha)要好得多然后除以 255 或位移位除以 8。这很可能会快得多。

  2. 位移/屏蔽以获得字节

    是的,它很好,但有更简单、更快速的方法,只需使用

    enum{
    _b=0, // db
    _g=1,
    _r=2,
    _a=3,
    };

    union color
    {
    DWORD dd; // 1x32 bit unsigned int
    BYTE db[4]; // 4x8 bit unsigned int
    };

    color col;
    col.dd=some_rgba_color;
    r = col.dd[_r]; // get red channel
    col.dd[_b]=5; // set blue channel

    体面的编译器可以在内部自行优化代码的某些部分,但我怀疑它是否可以在任何地方做到这一点......

    您也可以使用指针代替 union以同样的方式...

  3. 函数开销

    您获得了混合单个像素的功能。这意味着它会被调用很多。每次调用混合区域(矩形)通常比基于每个像素调用东西快得多。因为你以这种方式丢弃堆栈。要限制这一点,您可以尝试这些(对于被大量调用的函数):

    重新编码您的应用程序,以便您可以混合区域而不是像素,从而减少函数调用。

    通过降低被调用函数的操作数、返回值和内部变量来减少堆栈垃圾,以限制每次调用分配/释放/覆盖/复制的 RAM 量...例如通过使用静态或全局变量,例如 Alpha很可能不会有太大变化。或者你可以直接使用颜色编码的 alpha 而不是 alpha作为操作数。

    使用inline或类似 #define 的宏将源代码直接放在代码中而不是函数调用。

对于初学者,我会尝试将您的函数体重新编码为如下内容:

enum{
_b=0, // db
_g=1,
_r=2,
_a=3,
};

union color
{
unsigned int dd; // 1x32 bit unsigned int
unsigned char db[4]; // 4x8 bit unsigned int
};

private static unsigned int blend(unsigned int src, unsigned int dst, unsigned int alpha)
{
unsigned int i,a,_alpha=255-alpha;
color s,d;
s.dd=src;
d.dd=dst;
for (i=0;i<3;i++)
{
a=(((unsigned int)(s.db[i]))*alpha) + (((unsigned int)(d.db[i]))*_alpha);
a>>=8;
d.db[i]=a;
}
return d.dd;
}

但是,如果您想要真正的速度,请使用 GPU(OpenGL 混合)。

关于java - 混合像素(半透明)的更有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62329939/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com