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混合的主题
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值