DirectDraw Tutorial 2
DirectDraw Tutorial 2
Alpha混合
一、 基本alpha混合
Alhpa混合有多種算法,基本的計算公式如下:
result = ALPHA * srcPixel + ( 1 - ALPHA ) * destPixel
其中ALHPA的範圍從0.0到1.0,result爲混合後的顏色,srcPixel爲前景色,destPixel爲背景色。也就是說較大的ALPHA值意味着更多得源顏色。
上述公式中出現了兩個乘法,可以通過合併來優化它:
result = ALPHA * ( srcPixel - destPixel ) + destPixel
現在ALPHA是一個浮點數,因此可以將它轉化爲整數:
result = ( ALPHA * ( srcPixel - destPixel ) ) / 256 + destPixel
現在ALPHA的取值範圍爲0到256,對於除法可以通過右移來代替:
result = ( ALPHA * ( srcPixel - destPixel ) ) >>8+ destPixel
根據上面的公式,可以得到ALHPHA混合的代碼:
//DESC:Blt a surface pdds to (x,y) of backbuffer
//This function just can be used to blt a 32bit bitmap,if you want to blt a 8bit,16bit or 24bit
//you should rewrite this function, and int this version the parameter RECT* prc is not be used
//you should pass a NULL as value, alpha from 0 to 255, pdds is the source surface
HRESULT CDisplay::AlphaBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds,
RECT* prc, USHORT alpha )
{
HRESULT hr;
//Get the desc
DDSURFACEDESC2 ddsdSrc;
DDSURFACEDESC2 ddsdDest;
ZeroMemory( &ddsdSrc, sizeof( ddsdSrc ) );
ddsdSrc.dwSize = sizeof(ddsdSrc);
ZeroMemory( &ddsdDest, sizeof( ddsdDest ) );
ddsdDest.dwSize = sizeof(ddsdDest);
//Get the mask info
DDPIXELFORMAT ddpf;
ZeroMemory( &ddpf, sizeof(ddpf) );
ddpf.dwSize = sizeof(ddpf);
pdds->GetPixelFormat(&ddpf);
DWORD rMask = ddpf.dwRBitMask;
DWORD bMask = ddpf.dwBBitMask;
DWORD gMask = ddpf.dwGBitMask;
if( FAILED( hr = pdds->Lock( NULL, &ddsdSrc, DDLOCK_WAIT, NULL )))
return hr;
//the target area
RECT rect = {x, y, x+ddsdSrc.dwWidth, y+ddsdSrc.dwHeight} ;
if( FAILED( hr = m_pddsBackBuffer->Lock( &rect, &ddsdDest, DDLOCK_WAIT, NULL )))
return hr;
BYTE* srcPt = (BYTE*)ddsdSrc.lpSurface;
DWORD srcPitch = ddsdSrc.lPitch;
BYTE* destPt = (BYTE*)ddsdDest.lpSurface;
DWORD destPitch = ddsdDest.lPitch;
//the width and height of area need to process
int iWidth = ddsdSrc.dwWidth;
int iHeight = ddsdSrc.dwHeight;
DWORD dwDestPad = ddsdDest.lPitch - ( iWidth * 4 );
DWORD dwSrcPad = ddsdSrc.lPitch - ( iWidth * 4 );
for( int i = 0; i < ddsdSrc.dwHeight; i++ )
{
for( int j = 0; j < ddsdSrc.dwWidth; j++ )
{
DWORD dwSourceTemp = *((DWORD*)srcPt);
//if the source pixel is not black
if(( dwSourceTemp & 0xffffff ) != 0 )
{
DWORD dwTargetTemp = *((DWORD*)destPt);
// Extract the red channels.
DWORD dwTgtRed = dwTargetTemp & rMask;
DWORD dwSrcRed = dwSourceTemp & rMask;
// Extract the green channels.
DWORD dwTgtGreen = dwTargetTemp & gMask;
DWORD dwSrcGreen = dwSourceTemp & gMask;
// Extract the blue channel.
DWORD dwTgtBlue = dwTargetTemp & bMask;
DWORD dwSrcBlue = dwSourceTemp & bMask;
// Calculate the destination pixel.
dwTargetTemp =
( ( ( ( alpha * ( dwSrcRed - dwTgtRed ) >> 8 ) + dwTgtRed ) & rMask ) |
( ( ( alpha * ( dwSrcGreen - dwTgtGreen ) >> 8 ) + dwTgtGreen ) & gMask ) |
( ( alpha * ( dwSrcBlue - dwTgtBlue ) >> 8 ) + dwTgtBlue ) );
*((DWORD*)destPt) = dwTargetTemp;
}
//move to next pixel
srcPt += 4;
destPt += 4;
}
//move to next line
srcPt += dwSrcPad;
destPt += dwDestPad;
}
pdds->Unlock(NULL);
m_pddsBackBuffer->Unlock(&rect);
return hr;
}
二、 代碼優化
可以使用MMX、SSE來優化上述代碼,下面給出一些網上關於alpha混合的主題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.