?? gp_alpha.cpp
字號:
//********************************************
// 像素級的操作相關處理函數
// softboy 創(chuàng)建于2000年1月25日
//********************************************
#include <windows.h>
#include <fstream.h>
#include <math.h>
#include <ddraw.h>
#include "gp_draw.h"
#include "gp_input.h"
#include "gp_alpha.h"
//==============================alpha=============================
// alpha混合相關函數
//================================================================
WORD RMask, GMask, BMask; //顏色遮罩
BYTE RMove,GMove; //移動到最右邊的位數
DWORD rgbMask, rgbTemp;
//****************************
//功能:兩個點的ALPHA混合(0-31)
//參數:源點,目標點,ALPHA級別
//返回:混合后的點
WORD Alpha_Pixel(WORD sour, WORD dest, int alpha)
{
//C++版 :看下面的匯編版的注釋
rgbTemp = ((((sour<<16)|sour) & rgbMask ) * alpha +
(((dest<<16)|dest) & rgbMask ) * (32-alpha) ) >> 5;
rgbTemp = rgbTemp & rgbMask;
return (WORD)((rgbTemp>>16)|rgbTemp);
/*
//匯編版
int ialpha=32-alpha;
_asm{
movzx eax, sour //零擴展成32位
mov bx, ax //把sour放到bx中
sal eax, 16 //算術左移16位,低位填0
mov ax, bx //把sour放到ax中,現在的eax中放的是兩個sour
and eax, rgbMask //與上rgbMask
mul alpha //乘上alpha值
mov esi, eax //保存到esi
movzx eax, dest //同樣的方法
mov bx, ax
sal eax, 16
mov ax, bx
and eax, rgbMask
mul ialpha
add eax, esi //加上剛剛的值
shr eax, 5 //邏輯右移5位,高位填0
//rgbTemp = rgbTemp & rgbMask;
and eax, rgbMask //與上rgbMask
mov esi, eax //放到esi中
shr eax, 16 //邏輯右移動16位,高位填0
or eax, esi //或上esi
mov rgbTemp, eax //返回
}
return (WORD)rgbTemp;
*/
/*--------------------------------------------------------
多說點點,看看rgbMask的形式是什么:比如是655格式
00000|gggggg|00000|rrrrr|000000|bbbbb
5個0 六位的 5個0 |五位 |6個0 |五位
綠掩碼 |紅掩碼 |藍掩碼
好了,看看是個什么結果
要是將他與一個數與的話,也只是保留grb位的數
如果把這個數右移動16位,再與原數或,再去掉高位的話
結果是什么呢?16位的rgb的值
明白了就好辦多了。:)
那又是怎么做到alpha混合的呢?
主要是在那個乘法上面,注意先乘了一個alpha,然后有個右移5位
也就是除以32了。所以各個顏色成分的值算出來了也不會有越位,
各個顏色還是對齊了的。
然后就是上面說的那個了,還原成16位的顏色值
----------------------------------------------------------*/
}
//***************************
//功能:兩個表面的Alpha混合
//參數:(SS:目標表面 DS:源表面 Color_Key:透明色[0:無] iAlpha:alpha值)
void ABlt(LPDIRECTDRAWSURFACE SS,int x,int y, LPDIRECTDRAWSURFACE DS,RECT rcRect, WORD Color_Key, char iAlpha)
{
if( iAlpha <= 0 )
{ //不要驚奇:)看看下面就知道了,想想true和false的值
Blt(SS, x, y, DS, rcRect, true); //#define DDBLTFAST_NOCOLORKEY 0x00000000
return; //#define DDBLTFAST_SRCCOLORKEY 0x00000001
} //明白了嗎?用的是SRCCOLORKEY
else if( iAlpha >= 31 )
{
return;
}
WORD *Dest,*Sour;
int t1,t2;
int DestWidth, SourWidth;
//取源頁面指針
if( BeginDraw(DS) )
{
Dest=(WORD *)GraphBuffer;
DestWidth=GraphPitch;
EndDraw(DS);
}
//取目標頁面指針
if( BeginDraw(SS) )
{
Sour=(WORD *)GraphBuffer;
SourWidth=GraphPitch;
EndDraw(SS);
}
//邊界檢查
if( x<0 )
{
rcRect.left = rcRect.left - x;
x=0;
}
if( y<0 )
{
rcRect.top = rcRect.top - y;
y=0;
}
if( x+ rcRect.right - rcRect.left > ScreenWidth )
{
rcRect.right = rcRect.left + ScreenWidth - x;
}
if( y+ rcRect.bottom - rcRect.top > ScreenHeight )
{
rcRect.bottom = rcRect.top + ScreenHeight - y;
}
//相關的坐標計算
t1=SourWidth*y+x;
t2=DestWidth*rcRect.top+rcRect.left;
int rectWidth=rcRect.right-rcRect.left;
int SW=SourWidth-rectWidth; //想想跨度和寬度的區(qū)別
int DW=DestWidth-rectWidth;
if( Color_Key == 0 ) //無透明色檢查
{
for(int i=0; i<rcRect.bottom-rcRect.top; i++)
{
for( int j=0; j<rectWidth; j++)
{
Sour[t1]=_Alpha_Pixel(Sour[t1], Dest[t2], iAlpha);//alpha混合
t1++;
t2++;
}
t1+=SW; //跳過跨度和寬度的差值
t2+=DW;
}
}
else //透明色檢查
{
for(int i=0; i<rcRect.bottom-rcRect.top; i++)
{
for( int j=0; j<rectWidth; j++)
{
if( Dest[t2] != Color_Key ) //不進行透明色的混合
Sour[t1]=_Alpha_Pixel(Sour[t1], Dest[t2], iAlpha);
t1++;
t2++;
}
t1+=SW;
t2+=DW;
}
}
}
//***********************************************************
//功能:把一個表面上的特定顏色Alpha混合到另一個表面,其他不變
//參數:(SS:目標表面 DS:源表面 Color_Key:透明色[0:無] Color:混合色 iAlpha:alpha值)
void AlphaColorBlt(LPDIRECTDRAWSURFACE SS,int x,int y, LPDIRECTDRAWSURFACE DS,RECT rcRect, WORD Color_Key, WORD Color, char iAlpha)
{
if( iAlpha <= 0 )
{
Blt(SS, x, y, DS, rcRect, true); //有不明白的看看上一個函數的注釋
return;
}
else if( iAlpha >= 31 )
{
return;
}
WORD *Dest,*Sour;
int t1,t2;
int DestWidth, SourWidth;
//取源頁面指針
if( BeginDraw(DS) )
{
Dest=(WORD *)GraphBuffer;
DestWidth=GraphPitch;
EndDraw(DS);
}
//取目標頁面指針
if( BeginDraw(SS) )
{
Sour=(WORD *)GraphBuffer;
SourWidth=GraphPitch;
EndDraw(SS);
}
//邊界檢查
if( x<0 )
{
rcRect.left = rcRect.left - x;
x=0;
}
if( y<0 )
{
rcRect.top = rcRect.top - y;
y=0;
}
if( x+ rcRect.right - rcRect.left > ScreenWidth )
{
rcRect.right = rcRect.left + ScreenWidth - x;
}
if( y+ rcRect.bottom - rcRect.top > ScreenHeight )
{
rcRect.bottom = rcRect.top + ScreenHeight - y;
}
//計算相應的坐標
t1=SourWidth*y+x;
t2=DestWidth*rcRect.top+rcRect.left;
int rectWidth=rcRect.right-rcRect.left;
int SW=SourWidth-rectWidth; //跨度和寬度
int DW=DestWidth-rectWidth;
if( Color_Key == 0 ) //無透明色檢查
{
for(int i=0; i<rcRect.bottom-rcRect.top; i++)
{
for( int j=0; j<rectWidth; j++)
{
if( Dest[t2]==Color ) //只混合一種顏色
Sour[t1]=_Alpha_Pixel(Sour[t1], Dest[t2], iAlpha);
else
Sour[t1]=Dest[t2];
t1++;
t2++;
}
t1+=SW;
t2+=DW;
}
}
else //透明色檢查
{
for(int i=0; i<rcRect.bottom-rcRect.top; i++)
{
for( int j=0; j<rectWidth; j++)
{
if( Dest[t2] != Color_Key )
{
if( Dest[t2]==Color )
Sour[t1]=_Alpha_Pixel(Sour[t1], Dest[t2], iAlpha);
else
Sour[t1]=Dest[t2];
}
t1++;
t2++;
}
t1+=SW;
t2+=DW;
}
}
}
//**************************
//功能:表面連續(xù)漸變Blt
//參數:(背景頁面,源頁面,x, y, 起始ALPHA值,步長,步數,延時,透明色)
void ChangeBlt(LPDIRECTDRAWSURFACE BackSurface, LPDIRECTDRAWSURFACE suf, int x, int y, int BeginAlpha, int StepSize, int Step,int Time, WORD Color_Key)
{
long T1=0, T2=0;
int W,H;
int bAlpha=BeginAlpha;
T1=T2=timeGetTime();
//取表面寬高
GetSurfaceSize(suf, W, H);
RECT rect={0,0,W,H};
RECT rect2={0,0,ScreenWidth, ScreenHeight};
for( int j=0; j<Step+1; j++)
{
//延時
while( T1-T2<Time )
{
T1=timeGetTime();
}
T2=T1;
//先把BackSurface以NOCOLORKEY方式blt到Back表面上
Blt(lpDDSBack, 0,0, BackSurface, rect2, false);
//再把suf按照alpha的值和透明色blt到Back表面上
ABlt(lpDDSBack, x, y, suf, rect, ColorKey16, bAlpha);
//更新屏幕
_UpdateScreen();
//alpha的值增加一個單位
bAlpha+=StepSize;
//越界檢查
if( bAlpha<0 )
bAlpha=0;
if( bAlpha>31 )
bAlpha=31;
//一次到位
if( Mouse.IsButton(0) ) //左鍵按下
{
//看上面的……
bAlpha=BeginAlpha+StepSize*Step;
if( bAlpha<0 )
bAlpha=0;
if( bAlpha>31 )
bAlpha=31;
Blt(lpDDSBack, 0,0, BackSurface, rect2, false);
ABlt(lpDDSBack, x, y, suf, rect, ColorKey16, bAlpha);
_UpdateScreen();
return;
}
}
}
//***************************
//功能:表面和光圈的Alpha混合
//參數:(SS:目標表面 DS:光圈表面)
void Alpha_Blt(LPDIRECTDRAWSURFACE SS,int x,int y, LPDIRECTDRAWSURFACE DS,RECT rcRect)
{
WORD d=0x0000; //想想是什么顏色:)黑
WORD *Dest,*Sour;
int t1, t2;
int DestWidth, SourWidth;
//取源頁面指針
if( BeginDraw(DS) )
{
Dest=(WORD *)GraphBuffer;
DestWidth=GraphPitch;
EndDraw(DS);
}
//取目標頁面指針
if( BeginDraw(SS) )
{
Sour=(WORD *)GraphBuffer;
SourWidth=GraphPitch;
EndDraw(SS);
}
//邊界檢查
if( x<0 )
{
rcRect.left = rcRect.left - x;
x=0;
}
if( y<0 )
{
rcRect.top = rcRect.top - y;
y=0;
}
if( x+ rcRect.right - rcRect.left > ScreenWidth )
{
rcRect.right = rcRect.left + ScreenWidth - x;
}
if( y+ rcRect.bottom - rcRect.top > ScreenHeight )
{
rcRect.bottom = rcRect.top + ScreenHeight - y;
}
//恩…………
t1=SourWidth*y+x;
t2=DestWidth*rcRect.top+rcRect.left;
int rectWidth=rcRect.right-rcRect.left;
int SW=SourWidth-rectWidth; //不說了,這個……
int DW=DestWidth-rectWidth;
for(int i=0; i<rcRect.bottom-rcRect.top; i++)
{
for( int j=0; j<rectWidth; j++)
{
//看好哦,光圈表面的藍色是alpha值,d是黑色
Sour[t1]=_Alpha_Pixel(Sour[t1], d, Dest[t2]&BMask );
t1++;
t2++;
}
t1+=SW;
t2+=DW;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -