图形擦除技术及编程应用 统一教学网 日期:2001-10-9 0:31:00 出处:赛迪网 作者:周鸣扬 | |
图形擦除是图形特技处理中最为常见的一种,在各种游戏中图形擦除技术有着广泛的应用。图形擦除在本质上是图形的消隐,即在两幅图片之间进行图片的平滑过渡显示。过渡的方式决定了图形擦除的不同视觉效果,其中最为常见的一种就是图片淡入淡出的更新:两幅图片由明到暗、由暗到明的循环交替显示。这种特技效果在编程中的实现,往往是通过DirectX技术实现的:DirectX Transform为我们提供了一个“
解决方案 不同于Windows 95中的GUI(图形用户接口),在Windows 98以后的版本中,GUI增加了对Alpha Blending(通道混合)的支持,Alpha Blending在概念上最为明显的就是对“通道”的应用。熟悉图形处理的朋友对“通道”这个概念并不会感到陌生, Alpha通道是用来表示数字图像的透明度,改变各种通道的特性,就相当于改变各种基本颜色的浓度。通常情况下,Alpha通道使用8位(Byte)二进制数,可以表示256级灰度,即256级的透明度。假设我们想要在目标区(Dst)里显示一个像素(Src:Alpha通道值为Src.Alpha),并且要求系统进行“通道合成”运算,那么,进行合成运算的具体公式为: Dst.Red = Src.Red+ (1 - Src.Alpha) Dst.Red Dst.Green = Src.Green+ (1 - Src.Alpha) Dst.Green Dst.Blue = Src.Blue + (1 - Src.Alpha) Dst.Blue 从上面的公式可以看出,在进行合成运算之后,更新显示后的目标区域颜色值(RGB)并不完全是源位图的RGB值的拷贝,而是源位图和目标区域进行了“合成”之后的RGB值。和BitBlt函数的像素运算不同,Alpha Blending强调的是源位图的透明度,正是利用这样一种合成运算,我们能够达到图像“透明”的效果。 在VC中,系统提供了AlphaBlend函数来实现位图的通道合成运算,AlphaBlend 函数主要用来显示透明或半透明的位图,其调用格式如下: BOOL AlphaBlend( HDC hdcDest, // 目标设备环境句柄 int nXOriginDest, // 目标坐标x int nYOriginDest, // 目标坐标y int nWidthDest, // 目标宽度 int nHeightDest, //目标高度 HDC hdcSrc, //源设备环境句柄 int nXOriginSrc, // 源坐标x int nYOriginSrc, // 源坐标y int nWidthSrc, //源宽度 int nHeightSrc, //源高度 BLENDFUNCTION blendFunction // 合成方式具体数据结构 ); BLENDFUNCTION定义了在源位图和目标位图之间进行合成的具体方式,其具体数据成员及含义如下: typedef struct _BLENDFUNCTION { BYTE BlendOp; BYTE BlendFlags;//必须为零 BYTE SourceConstantAlpha;//位图使用的透明度,0为完全透明、255为正常方式显示 BYTE AlphaFormat;//通常为零,如果源位图为32位真彩色,此值可取为AC_SRC_ALPHA }BLENDFUNCTION, PBLENDFUNCTION, LPBLENDFUNCTION; 由上面的函数说明我们知道,AlphaBlend能够以特定的透明度来显示一幅位图,那么,如果让AlphaBlend以不同的通道值(从0到255)不断地交替显示两幅图片,这样就实现了“擦除”效果。 编程实现 了解了上述原理,编程中的具体运用就不会再是难事了,下面以在VC中为例,说明这种图形处理技术在编程中的具体实现。 首先在VC中新建一基于对话框的项目WipeImage。准备好两幅等大的图片(IDB_CROSS、IDB_LANTERN),并将图片引入资源管理器。在CWipeImageDlg类中加入以下的全局成员变量声明: class CWipeImageDlg : public CDialog { // Construction public: BLENDFUNCTION m_bf; CBitmap cross,lantern; BITMAP bmp; int bmpWidth,bmpHeight; CDC dcForCross,dcForLantern; CDC dc; BOOL bShowLantern; ………(系统自动生成部分) }; 接着在类向导中加入对WM_INITDIALOG和WM_TIMER消息的响应,其响应代码分别如下: BOOL CWipeImageDlg::OnInitDialog() { ………(系统自动生成部分) // TODO: Add extra initialization here //初始化全局成员变量 this->bShowLantern=TRUE; m_bf.BlendOp = AC_SRC_OVER; m_bf.BlendFlags = 0; m_bf.SourceConstantAlpha =10; m_bf.AlphaFormat = 0; //为节约篇幅,以下代码中略去对操作不成功的处理代码 if(!cross.LoadBitmap(IDB_CROSS)) { AfxMessageBox("装载位图出错!"); return FALSE; } cross.GetBitmap(&&bmp); lantern.LoadBitmap(IDB_LANTERN); cross.GetBitmap(&&bmp); //获得位图的大小信息 bmpWidth=bmp.bmWidth; bmpHeight=bmp.bmHeight; dc=this->GetDC(); dcForCross.CreateCompatibleDC(dc); dcForLantern.CreateCompatibleDC(dc); //将位图装入设备环境句柄 dcForCross.SelectObject(&&cross); dcForLantern.SelectObject(&&lantern); //打开计时器 SetTimer(1000,50,NULL); return TRUE; } void CWipeImageDlg::OnTimer(UINT nIDEvent) { //图片透明度每次递增5点 m_bf.SourceConstantAlpha+=5; //当第一幅图片完全可见之后,显示另一张图片 if(m_bf.SourceConstantAlpha>=200) { m_bf.SourceConstantAlpha=10; //将bShowLantern做为显示标志,确认应该显示哪一张图片 bShowLantern=!bShowLantern; } if(bShowLantern) { //按透明度递增的方式显示“吊灯”图片 AlphaBlend(dc,0,0,bmpWidth,bmpHeight,dcForLantern,0,0,bmpWidth,bmpHeight,m_bf); } else { //按透明度递增的方式显示“背景”图片 AlphaBlend(dc,0,0,bmpWidth,bmpHeight,dcForCross,0,0,bmpWidth,bmpHeight,m_bf); } CDialog::OnTimer(nIDEvent); } 编译说明 由于AlphaBlend函数是在“Msimg32.dll”(对应于Msimg32.lib库文件)中定义的。所以,为了避免LNK2001错误,在编译前应该将“Msimg32.lib”文件加入FadeImage项目,然后运行上面的程序,你会发现,在或明或暗之间,你的两幅位图已经出现在屏幕之上了。 |
图形擦除技术及编程应用
最新推荐文章于 2018-07-31 19:44:29 发布