DirectDraw中alpha混合的简单实现
最近自己在写游戏,需要用到半透明的效果,于是研究了一下关于alpha混合的知识。
现在许多游戏为了达到光影或图象的透明效果都会采用AlphaBlend 技术。所谓AlphaBlend技术,其实就是按照"Alpha"混合向量的值来混合源像素和目标像素,一般用来处理半透明效果。在计算机中的图象可以用R(红色),G(绿色),B(蓝色)三原色来表示。假设一幅图象是A,另一幅透明的图象是B,那么透过B去看A,看上去的图象C就是B和A的混合图象,设B图象的透明度为alpha(取值为0-1,0为完全透明,1为完全不透明),Alpha混合公式如下:
R(C)=alpha*R(B)+(1-alpha)*R(A)
G(C)=alpha*G(B)+(1-alpha)*G(A)
B(C)=alpha*B(B)+(1-alpha)*B(A)
R(x)、G(x)、B(x)分别指颜色x的RGB分量原色值。从上面的公式可以知道,Alpha其实是一个决定混合透明度的数值。应用Alpha混合技术,可以实现游戏中的许多特效,比如火光、烟雾、阴影、动态光源等半透明效果。
根据这个思想我们可以写出以下算法:
注:lpdds1和lpdds2是两个经过再次封装的表面对象
void myAlphaBlend(CXDDR &lpdds1, CXDDR &lpdds2,float AlphaValue)
{
HDC hdc1,hdc2;
LPDIRECTDRAWSURFACE7 lps1=lpdds1.Get_lpDDS();//获得离屏表面
LPDIRECTDRAWSURFACE7 lps2=lpdds2.Get_lpDDS();
BYTE R1,G1,B1;
BYTE R2,G2,B2;
BYTE R,G,B;
COLORREF rgb1,rgb2;
if (lps1->GetDC(&hdc1) == DD_OK && lps2->GetDC(&hdc2)==DD_OK)//获得设备句柄
{
for(int t=0;t<=lpdds1.Get_lpDDS_W();++t)
for(int j=0;j<=lpdds1.Get_lpDDS_H();++j)
{
rgb1 = GetPixel(hdc1, t, j);
rgb2 = GetPixel(hdc2, t+50, j+50);
//if(rgb1==RGB(255,255,255))continue;
R1=GetRValue(rgb1);
G1=GetGValue(rgb1);
B1=GetBValue(rgb1);
R2=GetRValue(rgb2);
G2=GetGValue(rgb2);
B2=GetBValue(rgb2);
R=AlphaValue * ( R2 - R1 ) + R1;
G=AlphaValue * ( G2 - G1 ) + G1;
B=AlphaValue * ( B2 - B1 ) + B1;
SetPixel(hdc1, t, j,RGB(R,G,B));
}
lps1->ReleaseDC(hdc1);//释放句柄
lps2->ReleaseDC(hdc2);
}
}
{
HDC hdc1,hdc2;
LPDIRECTDRAWSURFACE7 lps1=lpdds1.Get_lpDDS();//获得离屏表面
LPDIRECTDRAWSURFACE7 lps2=lpdds2.Get_lpDDS();
BYTE R1,G1,B1;
BYTE R2,G2,B2;
BYTE R,G,B;
COLORREF rgb1,rgb2;
if (lps1->GetDC(&hdc1) == DD_OK && lps2->GetDC(&hdc2)==DD_OK)//获得设备句柄
{
for(int t=0;t<=lpdds1.Get_lpDDS_W();++t)
for(int j=0;j<=lpdds1.Get_lpDDS_H();++j)
{
rgb1 = GetPixel(hdc1, t, j);
rgb2 = GetPixel(hdc2, t+50, j+50);
//if(rgb1==RGB(255,255,255))continue;
R1=GetRValue(rgb1);
G1=GetGValue(rgb1);
B1=GetBValue(rgb1);
R2=GetRValue(rgb2);
G2=GetGValue(rgb2);
B2=GetBValue(rgb2);
R=AlphaValue * ( R2 - R1 ) + R1;
G=AlphaValue * ( G2 - G1 ) + G1;
B=AlphaValue * ( B2 - B1 ) + B1;
SetPixel(hdc1, t, j,RGB(R,G,B));
}
lps1->ReleaseDC(hdc1);//释放句柄
lps2->ReleaseDC(hdc2);
}
}
运行效果:
若对颜色键进行处理则可去掉上面卡通图案的白色背景,这里没有去掉是为了能看得更清楚。