分享
 
 
 

游戏开发学堂:2D模式下的alpha混合

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

alpha混合是一种常见的颜色处理,是把源点的颜色值和目标点的颜色值按照一定的算法进行运算,得到一个透明的效果.

alpha混合的基本公式:

result = ALPHA * srcPixel + ( 1 - ALPHA ) * destPixel

其中:

ALPHA:0到1之间的一个数,表示混合时的透明程度,为0的时候结果就是目标点的原值,为1的时候是源点的原值

srcPixel:源点颜色值

destPixel:目标点颜色值

result:结果,将会赋给目标点

这个是最基本的公式,但是我们在写程序的时候可以做一些优化.公式里面有两个乘号,乘法消耗的时钟周期要多得多,我们要想方法去掉它.做一个变换.

alpha混合的改进公式1:

result = ALPHA * ( srcPixel - destPixel ) + destPixel

然后我们也看到ALPHA是一个浮点数,我们可以把它转换成整数,因为一种颜色最多占8bit,所以ALPHA的值也最多到256,那我们把ALPHA的值先乘上256,然后运算的时候再除以256就得到下面的公式:

alpha混合的改进公式2:

result = ALPHA * ( srcPixel - destPixel )/256 + destPixel

其中:

ALPHA是一个0到256的数

有了这个公式,我们的第一份code也就出来了.

alpha混合代码1:

//16位565格式

i = height;?// 混合矩形高度

do

{

j = width; ?// 混合矩形宽度

do

{

sTemp = *((WORD*)lpSour);// 源点颜色值,16位--WORD类型,(lpSour和lpDest都是BYTE*)

if ( sTemp != sColorKey ) ? // 不是colorkey

{

dTemp = *((WORD*)lpDest); // 目标点

sb = sTemp & 0x1f; ? // 蓝色分量

db = dTemp & 0x1f;

sg = (sTemp 5) & 0x3f; // 绿色分量

dg = (dTemp 5) & 0x3f;

sr = (sTemp 11) & 0x1f;// 红色分量

dr = (dTemp 11) & 0x1f;

blue = (ALPHA * (sb - db) 8) + db;// 按照改进公式2运算三个分量

green = (ALPHA * (sg - dg) 8) + dg;

red = (ALPHA * (sr - dr) 8) + dr;

*((WORD*)lpDest) = blue | (green

}

lpDest += 2; // 下一个点,16位占2个字节

lpSour += 2;

}while ( --j 0 );

lpDest += dPadding; // 下一行

lpSour += sPadding;

}while (--i 0);

到此alpha混合也就差不多了,但是不得不说说MMX版本的alpha混合.上面的方式进行alpha混合的时候效率不高,而MMX使用64位的MMX寄存器,一次操作8(byte)/4(word)/2(dword)个数据单元,也就是所谓的\"单指令多数据SIMD结构\".这样我们就可以一次处理几个点.下面的代码是写给16位565模式的.

因为是16位模式,那么我们可以一次处理4个点,但是因为编译器不会主动的生成MMX代码,所以我们使用inline asm的方式进行.因为我们的点是定义成无符号的word型,不能出现负数,所以我们要修改我们的alpha混合公式:

alpha混合mmx版公式:

result = ( ALPHA * ( ( srcPixel+ 64 ) - destPixel) ) / 256 + destPixel- (ALPHA / 4)

这个公式是这样来的:因为16位模式下每个点的分量最多6位,换成10进制也就是63,那么我们在srcPixel上面加上64然后再减去destPixel,就不会出现负数了.加了之后当然要减回来,那这个公式就是这样的:

result = ( ALPHA * ( ( srcPixel+ 64 -64) - destPixel) ) / 256 + destPixel

然后把紫色的-64提出来也就得到了上面的公式了.

好了我们可以动手写code了,看起来的code应该如下:

alpha混合code2:

MASKRED = 0xF800F800F800F800;?// 三种颜色的掩码的64位扩展

MASKGREEN = 0x07E007E007E007E0;

MASKBLUE = 0x001F001F001F001F;

__int64 ALPHA64, COLORKEY64, ALPHABY4;

__int64 MASKRED, MASKGREEN, MASKBLUE;

__int64 ADD64 = 0x0040004000400040;

_asm

{

movd mm2,ALPHA // ALPHA值放入mm2

punpcklwd mm2,mm2

// mm2 - 0000 0000 00aa 00aa

punpckldq mm2,mm2

// mm2 - 00aa 00aa 00aa 00aa,生成alpha的64位扩展

movq ALPHA64,mm2 ?// 结果放入到 ALPHA64

psrlw mm2, 2 ?// 每个ALPHA 除以4

movq ALPHABY4,mm2

// 放到 ALPHABY4

movd mm4,ColorKey

// ColorKey - mm4

punpcklwd mm4,mm4

// mm4 - 0000 0000 cccc cccc

punpckldq mm4,mm4

// mm4 - cccc cccc cccc cccc,生成Colorkey的64位扩展

movq COLORKEY64,mm4 ;

// 结果放到 COLORKEY64

}

i = height;

do

{

j = width/4;

// 两行写在一起表示假设他们同时在uv管道里面执行

_asm

{

push edi ? // 保存edi和esi

push esi

mov edi,lpDest

// edi指向dest缓冲区

mov esi,lpSour; // esi指向sour缓冲区

SPAN_RUN_565:

movq mm7,[edi]

// dest的8 bytes 到 mm7--4个dest点到mm7

movq mm6,[esi]

// sour的8 bytes 到 mm6--4个sour点到mm6

movq mm2,ALPHA64 ? // ALPHA64 - mm2

movq mm0,mm7 ? // 红色 - 复制 mm7 到 mm0,目标点

pand mm0,MASKRED ? // 红色 - 与上红色掩码 - [0r00 0r00 0r00 0r00],目标点

movq mm1,mm6 ? // 红色 - 复制 mm6 到 mm1,源点

pand mm1,MASKRED ? // 红色 - 与上红色掩码 - [0r00 0r00 0r00 0r00],源点

psrlw mm0,11 ? // 红色 - 右移 11 位 - [000r 000r 000r 000r],目标点

movq mm5,mm7 ? // 绿色 - 复制 mm7 到 mm5,目标点

psrlw mm1,11 ? // 红色 - 右移 11 位 - [000r 000r 000r 000r],源点

paddw mm1, ADD64// 红色 - 源点加上64

movq mm3,mm6 ? // 绿色 - 复制 mm6 到 mm3,源点

psubsw mm1,mm0

// 红色 - 减去目标点

pand mm5,MASKGREEN

// 绿色 - 与上绿色掩码 - [00g0 00g0 00g0 00g0],目标点

pmullw mm1,mm2

// 红色 - 乘以ALPHA

pand mm3,MASKGREEN

// 绿色 - 与上绿色掩码 - [00g0 00g0 00g0 00g0],源点

psrlw mm5,5 // 红色 - 右移 5 位 - [000g 000g 000g 000g],目标点

psrlw mm3,5 // 红色 - 右移 5 位 - [000g 000g 000g 000g],源点

nop // 空操作 - 指令配对

paddw mm3, ADD64// 绿色 - 源点加上64

psrlw mm1,8 // 红色 - 除以 256 (右移8位)

psubsw mm3,mm5

// 绿色 - 减去目标点

pmullw mm3,mm2

// 绿色 - 乘以ALPHA

paddw mm1,mm0 ?// 红色 - 加上目标点

psubw mm1, ALPHABY4 // 红色 - 减去alpha的四分之一

psllw mm1,11 ? // 红色 - 左移11位,还原[0r00 0r00 0r00 0r00]

movq mm0,mm7 ? // 蓝色 - 复制 mm7 到 mm0,目标点

pand mm0, MASKBLUE

// 蓝色 - 与上蓝色掩码 - [000b 000b 000b 000b],目标点

psrlw mm3,8 // 绿色 - 除以 256 (右移8位)

paddw mm3,mm5 ?// 绿色 - 加上目标点

movq mm4, mm6 ?// 蓝色 - 复制 mm6 到 mm4,源点

psubw mm3, ALPHABY4 // 绿色 - 减去alpha的四分之一

pand mm4, MASKBLUE?// 蓝色 - 与上蓝色掩码 - [000b 000b 000b 000b],源点

psllw mm3,5 // 绿色 - 左移5位,还原[00g0 00g0 00g0 00g0]

paddw mm4, ADD64// 蓝色 - 加上64

psubsw mm4,mm0

// 蓝色 - 减去目标点

por mm1,mm3 // 组合红色和绿色分量

pmullw mm4,mm2

// 蓝色 - 乘以alpha

movq mm3,COLORKEY64 // COLORKEY64 - mm3

psrlw mm4,8 // 蓝色 - 除以256(右移8位)

pcmpeqw mm3,mm6 // 比较 colorKey 和原来的sour,如果相等,则相应的mm3的位为1

paddw mm4,mm0 ?// 蓝色 - 加上目标点

movq mm5,mm3 ? // mm3 - mm5

psubw mm4, ALPHABY4 // 蓝色 - 减去alpha的四分之一

por mm1,mm4 // 合成3种颜色

pand mm5,mm7 ? // mm5与上目标点 - 取出源点是colorkey的点的目标点的颜色值

pandn mm3,mm1 ?// mm3取反然后与上mm1,mm1放的是运算结果,这样就把源点是colorkey的点的结果清0

por mm3,mm5 // mm3或上mm5,一个是源点是colorkey的点的目标点一个是源点不是colorkey的结果,两个 ? ? ? ? ? ? ? ? ? ? ? ? // 对立位都是0,这样就组合乘一个结果点

movq [edi],mm3 ? ? ? // 最终结果放回目标点

add edi,8 ?// 下一个目标点,一次64 bits = 8 bytes

mov eax,dword ptr [j] ?// j - eax

add esi,8 ?// 下一个源点

sub eax,1 ?// j--

mov dword ptr [lpDest], edi // 保存lpDest

mov dword ptr [j],eax ?// 赋回 j

mov dword ptr [lpSour], esi // 保存lpSour

cmp eax,0 ?// 这一行是不是处理完了

jg SPAN_RUN_565 // 下一个点

emms ? // 清除mmx寄存器

pop esi

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有