100分IDirectDrawSurface:AlphaBlt的例子
100分求一个IDirectDrawSurface::AlphaBlt的例子
如题,需要实现alpha通道的半透明效果。
另外要给出如何把一张带alpha通道的位图(HBITMAP)加载到DirectDrawSurface的方法。
唉,我快崩溃了,弄不出来。
------最佳解决方案--------------------
首先标准的DDraw7中是没有AlphaBlt的,你应该说的是DirectXMobile上面的,它倒是为了给移动设备提供AlphaBlend的功能而实现了一个AlphaBlt。
然后不巧的是DirectXMobile省略了CreateSurfaceFromFile函数,你只好自己写贴图加载代码了。
使用GDI加载一个位图然后BitBlt或AlphaBlend到一个Surface上,如果你想要100%原始ARGB信息的话,使用GetDIBits获取DIB的ARGB信息然后调用IDirectDraw::CreateSurface创建一个表面,在SURFACEDESC中传入ARGB数据的地址即可。或者就是创建空的表面之后Lock起来再往上面写数据。
其实标准GDI的AlphaBlend也比较快了,不过如果你的其它部分已经用了DDraw,还是用AlphaBlt比较方便。
------其他解决方案--------------------
我晕,你怎么就断定AlphaBlend函数很慢?你这只是初始化位图,又不是让你在以后的运算中一直用它,即使是3D游戏,初始加载纹理也是一步一步从系统内存转移到显卡内存里的。
你还可以通过IDirectDraw3::GetSurfaceFromDC从你的DC位图里直接创建表面。
------其他解决方案--------------------
我有现成的代码:
DrawTransAlpha(HDC hdcBack,int nXBack,int nYBack,int nWidthBack,int nHeightBack,
int nXFore,int nYFore,int nAlpha,COLORREF crTrans)
{
if(m_hbm!=NULL)
{
HDC hdcMem=CreateCompatibleDC(hdcBack);
RECT rBackRect={nXBack,nYBack,nWidthBack,nHeightBack};
HBITMAP hbmTmp=CreateCompatibleBitmap(hdcBack,nWidthBack,nHeightBack);
HBITMAP hbmBK=(HBITMAP)SelectObject(hdcBack,hbmTmp);
RECT rForeRect={nXFore,nYFore,nXFore+m_nWidth,nYFore+m_nHeight};
RECT rTransRect,rTransRect2;
if(IntersectRect(&rTransRect,&rBackRect,&rForeRect))
{
BITMAP bm,bmBK;
GetObject(m_hbm,sizeof(BITMAP),&bm);
BYTE *px=new unsigned char[bm.bmHeight*bm.bmWidthBytes];
GetBitmapBits(m_hbm,bm.bmHeight*bm.bmWidthBytes,px);
GetObject(hbmBK,sizeof(BITMAP),&bmBK);
BYTE *pxBK=new unsigned char[bmBK.bmHeight*bmBK.bmWidthBytes];
GetBitmapBits(hbmBK,bmBK.bmHeight*bmBK.bmWidthBytes,pxBK);
rTransRect2=rTransRect;
OffsetRect(&rTransRect2,-rForeRect.left,-rForeRect.top);
int pb=bm.bmBitsPixel/8;
int pbBK=bmBK.bmBitsPixel/8;
int dx1,dx2,dy1,dy2;
for(dy1=rTransRect.top,dy2=rTransRect2.top;dy1<rTransRect.bottom;dy1++,dy2++)
for(dx1=rTransRect.left,dx2=rTransRect2.left;dx1<rTransRect.right;dx1++,dx2++)
{
int nBackRGB_B=dy1*bmBK.bmWidthBytes+dx1*pbBK;
int nForeRGB_B=dy2*bm.bmWidthBytes+dx2*pb;
if(RGB(px[nForeRGB_B+2],px[nForeRGB_B+1],px[nForeRGB_B])!=crTrans)
{
pxBK[nBackRGB_B]=(px[nForeRGB_B]*nAlpha+pxBK[nBackRGB_B]*
(256-nAlpha))/256;
pxBK[nBackRGB_B+1]=(px[nForeRGB_B+1]*nAlpha+pxBK[nBackRGB_B+1]*
(256-nAlpha))/256;
pxBK[nBackRGB_B+2]=(px[nForeRGB_B+2]*nAlpha+pxBK[nBackRGB_B+2]*
(256-nAlpha))/256;
}
}
SetBitmapBits(hbmTmp,bmBK.bmHeight*bmBK.bmWidthBytes,pxBK);
HBITMAP hbmOld=(HBITMAP)SelectObject(hdcMem,hbmTmp);
BitBlt(hdcBack,0,0,rBackRect.right,rBackRect.bottom,hdcMem,0,0,SRCCOPY);
delete[]px;
delete[]pxBK;
SelectObject(hdcMem,hbmOld);
}
DeleteObject(hbmTmp);
DeleteObject(hdcMem);
}
}
说明:这是一个自定义绘图函数,功能是画半透明镂空图,你自己仔细研究下,
其中nAlpha是不透明度(注意:不是“透明度”),crTrans是被镂空的颜色
------其他解决方案--------------------
DirectX SDK不是自带很多例子么
------其他解决方案--------------------
……
not easy.
------其他解决方案--------------------
如题,需要实现alpha通道的半透明效果。
另外要给出如何把一张带alpha通道的位图(HBITMAP)加载到DirectDrawSurface的方法。
唉,我快崩溃了,弄不出来。
------最佳解决方案--------------------
首先标准的DDraw7中是没有AlphaBlt的,你应该说的是DirectXMobile上面的,它倒是为了给移动设备提供AlphaBlend的功能而实现了一个AlphaBlt。
然后不巧的是DirectXMobile省略了CreateSurfaceFromFile函数,你只好自己写贴图加载代码了。
使用GDI加载一个位图然后BitBlt或AlphaBlend到一个Surface上,如果你想要100%原始ARGB信息的话,使用GetDIBits获取DIB的ARGB信息然后调用IDirectDraw::CreateSurface创建一个表面,在SURFACEDESC中传入ARGB数据的地址即可。或者就是创建空的表面之后Lock起来再往上面写数据。
其实标准GDI的AlphaBlend也比较快了,不过如果你的其它部分已经用了DDraw,还是用AlphaBlt比较方便。
------其他解决方案--------------------
我晕,你怎么就断定AlphaBlend函数很慢?你这只是初始化位图,又不是让你在以后的运算中一直用它,即使是3D游戏,初始加载纹理也是一步一步从系统内存转移到显卡内存里的。
你还可以通过IDirectDraw3::GetSurfaceFromDC从你的DC位图里直接创建表面。
------其他解决方案--------------------
我有现成的代码:
DrawTransAlpha(HDC hdcBack,int nXBack,int nYBack,int nWidthBack,int nHeightBack,
int nXFore,int nYFore,int nAlpha,COLORREF crTrans)
{
if(m_hbm!=NULL)
{
HDC hdcMem=CreateCompatibleDC(hdcBack);
RECT rBackRect={nXBack,nYBack,nWidthBack,nHeightBack};
HBITMAP hbmTmp=CreateCompatibleBitmap(hdcBack,nWidthBack,nHeightBack);
HBITMAP hbmBK=(HBITMAP)SelectObject(hdcBack,hbmTmp);
RECT rForeRect={nXFore,nYFore,nXFore+m_nWidth,nYFore+m_nHeight};
RECT rTransRect,rTransRect2;
if(IntersectRect(&rTransRect,&rBackRect,&rForeRect))
{
BITMAP bm,bmBK;
GetObject(m_hbm,sizeof(BITMAP),&bm);
BYTE *px=new unsigned char[bm.bmHeight*bm.bmWidthBytes];
GetBitmapBits(m_hbm,bm.bmHeight*bm.bmWidthBytes,px);
GetObject(hbmBK,sizeof(BITMAP),&bmBK);
BYTE *pxBK=new unsigned char[bmBK.bmHeight*bmBK.bmWidthBytes];
GetBitmapBits(hbmBK,bmBK.bmHeight*bmBK.bmWidthBytes,pxBK);
rTransRect2=rTransRect;
OffsetRect(&rTransRect2,-rForeRect.left,-rForeRect.top);
int pb=bm.bmBitsPixel/8;
int pbBK=bmBK.bmBitsPixel/8;
int dx1,dx2,dy1,dy2;
for(dy1=rTransRect.top,dy2=rTransRect2.top;dy1<rTransRect.bottom;dy1++,dy2++)
for(dx1=rTransRect.left,dx2=rTransRect2.left;dx1<rTransRect.right;dx1++,dx2++)
{
int nBackRGB_B=dy1*bmBK.bmWidthBytes+dx1*pbBK;
int nForeRGB_B=dy2*bm.bmWidthBytes+dx2*pb;
if(RGB(px[nForeRGB_B+2],px[nForeRGB_B+1],px[nForeRGB_B])!=crTrans)
{
pxBK[nBackRGB_B]=(px[nForeRGB_B]*nAlpha+pxBK[nBackRGB_B]*
(256-nAlpha))/256;
pxBK[nBackRGB_B+1]=(px[nForeRGB_B+1]*nAlpha+pxBK[nBackRGB_B+1]*
(256-nAlpha))/256;
pxBK[nBackRGB_B+2]=(px[nForeRGB_B+2]*nAlpha+pxBK[nBackRGB_B+2]*
(256-nAlpha))/256;
}
}
SetBitmapBits(hbmTmp,bmBK.bmHeight*bmBK.bmWidthBytes,pxBK);
HBITMAP hbmOld=(HBITMAP)SelectObject(hdcMem,hbmTmp);
BitBlt(hdcBack,0,0,rBackRect.right,rBackRect.bottom,hdcMem,0,0,SRCCOPY);
delete[]px;
delete[]pxBK;
SelectObject(hdcMem,hbmOld);
}
DeleteObject(hbmTmp);
DeleteObject(hdcMem);
}
}
说明:这是一个自定义绘图函数,功能是画半透明镂空图,你自己仔细研究下,
其中nAlpha是不透明度(注意:不是“透明度”),crTrans是被镂空的颜色
------其他解决方案--------------------
DirectX SDK不是自带很多例子么
------其他解决方案--------------------
……
not easy.
------其他解决方案--------------------