`
java-mans
  • 浏览: 11738312 次
文章分类
社区版块
存档分类
最新评论

DirectX学习手记(二)

 
阅读更多
			DirectX学习手记(二)
			happyfire 2002/8/11

此回说说怎样用DirectDraw向表面上贴图,包括创建离屏表面,设置调色板,载入位图到表面,透明色,页面丢失等。

二. 用DirectDraw贴图
	先让我们回忆一下上一回的内容。为了初始化DirectDraw我们首先创建了一个DirectDraw对象,然后
设置了协作模式(全屏+独占),设置显示模式,然后创建主表面,提取后台缓冲表面指针。至此可以在后台
表面上进行操作,然后flip到前台显示出来。最后程序结束前释放所有的directdraw对象。好了,现在说说怎
样向后台表面贴图,即让屏幕显示图片。

第一步:创建离屏表面
	离屏表面是你永远看不到的表面(所谓离屏),它通常被用来存放位图。通常的做法是把离屏表面
上的位图用Blt的方法贴到后台表面,后台表面再flip为前台表面。看看它的创建方法:

	//声明用来存放图像的离屏表面(声明为全局变量)
	LPDIRECTDRAWSURFACE lpDDSPic ;	

	//在InitDDraw()中创建保存图像的离屏表面
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH ;
	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN ;
	ddsd.dwHeight = 480 ;
	ddsd.dwWidth = 640 ;
	if ( lpDD->CreateSurface(&ddsd,&lpDDSPic,NULL)!=DD_OK )
		return FALSE ;

首先要声明一个表面,然后填充DDSURFACEDESC表面描述结构体。dwFlags填DDSD_CAPS表示ddsCaps域有效,
DDSD_HEIGHT和DDSD_WIDTH表示要指定页面的大小。ddsCaps.dwCaps填DDSCAPS_OFFSCREENPLAIN表示创建
的是离屏表面。dwHeight和dwWidth填页面的大小,单位是像素。然后就可以用DirectDraw对象的CreateSurface
方法创建lpDDSPic了。注意CreateSurface的第三个参数必须填NULL,该参数将允许与今后的 COM 集合特性相兼容。
整个创建过程和创建主表面非常相似,只是ddsd的填充不同。这里稍微谈一下离屏表面的大小问题。
在 DirectX 5.0 以前的版本中,离屏表面的宽度的最大值不能超出于主表面的宽度.而从 DirectX 5.0 版开始,你
可以创建任何宽度的离屏页面,只要你的显存和内存足够大.缺省情况下,离屏表面是被创建在显存中的,但如果
显存不够用,它就会被置于内存中,当然你可以指明只在显存中创建表面(可在 DDSCAPS 结构的 dwCaps 成员中
包含进 DDSCAPS_SYSTEMMEMORY 或 DDSCAPS_VIDEOMEMORY 标志符,以明确的表明你希望将表面置于何处),如果
这样的话,当表面太大而超出显存的容纳范围时,就会创建失败。
另外,以上面的方法创建的离屏表面的像素格式(可以简单理解为表示几位的颜色)是和主表面相同的,当然
也可以创建一个像素格式与主表面不同的离屏表面.然而,在这种情况下,该离屏表面将被限制于系统内存中。具体的
做法有点烦,各位感兴趣的可以查一下手册,:) 。

第二步:读入调色板并设置上
我们的主表面被设置为基于调色板(8位色深度)。一个基于调色板的表面是一些数字的集合,
其中的每一个数字代表一个像素.每一个数字的值都对应于一个色彩表(color table)中的项,这个表告诉 DirectDraw 
对这个像素使用什么样的颜色. 这个表就是调色板(Palette)。使用调色板是为了尽量降低对显存的需求,它用一个
颜色索引(Color Index)来代表各个像素点的颜色,而不是直接用红,绿,蓝三基色的亮度值来确定每个像素点的颜色。
调色板包含了若干颜色索引和该索引所对应的真实颜色值。调色板的颜色索引主要采用4或8两种位深度。要在表面上
正常显示图像就必须将表面的调色板设置为该图像的调色板。如下面的代码片断:
//先声明调色板对象(其实是指针类型,就这么说吧,上面提到的各个对象都是这样的)
LPDIRECTDRAWPALETTE lpDDPal ;	

//从位图设置调色板
lpDDPal = DDLoadPalette(lpDD, szBitmap);
if (lpDDPal)
 	lpDDSPrimary->SetPalette(lpDDPal);
else
	return FALSE ;

DDLoadPalette是DDutil.cpp里面的函数,happyfire也不大懂,作为初学者拿来用就是了。


第三步:将位图文件读入已创建好的离屏表面中
	这一步我们用DirectDraw APIs里面的一个函数DDLoadBitmap来实现,具体用法是:
lpDDSPic = DDLoadBitmap ( lpDD, szBitmap, 0, 0 ) ; //szBitmap是位图文件名,例如".//pic//background.bmp"
使用了DDLoadBitmap这一步变得非常简单,但是要把Ddutil.cpp和Ddutil.h加到工程中才行。你可以看看
Ddutil.cpp中该函数的实现,它调用了Windows的API LoadImage,并且用作为参数传进来的directdraw对象
创建了一个表面并返回了它的指针。

第四步:使用blit的方法,将离屏表面上的图片传送到后台缓冲
	何谓blit?Bit block transfer(位块传送),即将内存中的数据块从一处传送到另一处。DirectDraw
提供了两个方法,Blt和BltFast。Blt功能强大,BltFast速度较快。这里我们先不讨论Blt,只用BltFast。看如何实现:

RECT rcRect ;

rcRect.left= 0;
rcRect.top= 0 ;
rcRect.right= 640;
rcRect.bottom=480;
lpddsBack->BltFast( 0, 0, lpddsPic, &rcRect, DDBLTFAST_SRCCOLORKEY|DDBLTFAST_WAIT);

RECT是windows的矩形结构(所以要包含windows.h),rcRect这个矩形用来确定源表面(这里是离屏表面)上的哪
一块区域要被传送到目标表面(这里是后台缓冲表面)上去。BltFast的前两个参数是两个DWORD值,表示目标表面
上的一个点的坐标x和y,它决定了传送过去的图形在目标表面上所处的位置。你可以改变x,y和rcRect看看效果。
最后一个参数是传送类型:
DDBLTFAST_DESTCOLORKEY 
指定进行一次带透明的位块传送,使用目标表面的关键色(color key)。 
DDBLTFAST_NOCOLORKEY 
指定进行一次普通的复制,不带透明成分。 
DDBLTFAST_SRCCOLORKEY 
指定进行一次带透明的位块传送,使用源表面的关键色。 
DDBLTFAST_WAIT 
如果位块传送器正忙,延迟 DDERR_WASSTILLDRAWING 消息的发送,直到位块传送器准备好或发生其它错误时才返回。

看看这个color key,这可是很有用的!所谓关键色,即我们说的透明色,如果在源表面上指定了一个颜色为关键色,
那么在blit操作中,将视具有这种颜色的区域为透明,不会被传送到目标页面上。这样的话,虽然传送过去的是一个
矩形,但矩形上是关键色的部分是不会传送的,从而看上去是有轮廓的图形,比如一个精灵。

当然必须先为一个表面设置关键色才行。在InitDDraw中我们用DDSetColorKey ( lpDDSPic, RGB(255,0,255) ) ;为
创建好的离屏表面lpDDSPic设置了紫红色的关键色。你可以在图片中画一个精灵,然后把所有非精灵的部分用紫红色
填充。然后将BltFast的最后一个参数设为DDBLTFAST_SRCCOLORKEY.这样传送过去的就是一个精灵的样子了。

用DDBLTFAST_DESTCOLORKEY可以为目标表面设置关键色,有所不同的是,目标表面上颜色只有为关键色才能被覆盖,即
染色。

最后在说说目标表面和原表面的区别。其实它们都是相对的。调用BltFast的为目标表面,作为参数的为源表面。一般的
用法,后台表面调用BltFast,参数为离屏表面。

贴图的问题就说这么多吧,其实这里面的内容还是挺多的。还有非调色板模式的16位,24位,32位RGB格式,16位RGB对应于
不同的显卡还有555,565两种模式。但我们是初学者嘛,这些东西...:) 有待研究。(如果你真的立志于作游戏,呵呵,
准备学汇编吧,以后还要和MMX处理器的指令什么的打交道啊)

最后要说的是第四步的操作要放在MainLoop中,这样让它不停的Blt再Flip,如果你在程序中设计按了某个键贴不同的图并改
变贴图的位置,就可以做出精灵动画了,基本的原理就是这样的。

三.浅谈表面丢失的处理
	如果你的程序从全屏模式下用Alt+Tab切出去,再切回来,你可能发现图片不见了。因为当代表页面内存的
DirectDrawSurface对象被不得已的释放时,与该对象相关联的页面内存也会被释放。当一个DirectDrawSurface对象丢失其
页面内存的时候,它的许多函数将返回DDERR_SURFACELOST,并且不进行任何其它操作。先看一下这个片断:
		while (1){
			hRst = lpDDSPrimary->Flip(NULL,0) ;
				
			if ( hRst==DD_OK )
				break ;

			if ( hRst==DDERR_SURFACELOST ){
			
				if ( RestoreAllDDS()!=DD_OK )
					break ;
			}
	
			if (hRst != DDERR_WASSTILLDRAWING){
	                break;
			}
		}

上回flip中没提到flip有失败的可能,上面的片断是解决的方法。如果flip返回DDERR_WASSTILLDRAWING,那么是由于上一次flip
操作尚未完成(flip指令已发出,但directX还没有完成操作),我们可以做的只能是让while循环下去,直到
hRst != DDERR_WASSTILLDRAWING。如果flip返回DD_OK,那表示flip操作完成,可以break出去了。如果flip返回
DDERR_SURFACELOST,表示发生了表面失效,这时我们需要自己处理它。看看我的RestoreAlDDS()函数是怎么工作的:

HRESULT RestoreAllDDS( void )
{
    HRESULT	hRst ;
  
    hRst = lpDDSPrimary->Restore();
    if (hRst)    
	hRst = lpDDSBack->Restore () ;
    if (hRst)    
	hRst = lpDDSPic->Restore() ;
	
    DDReLoadBitmap ( lpDDSPic,szBitmap ) ;
	

    return hRst ;
} 
 

在这个函数里面,我们先后调用了主表面,后台表面,离屏表面的Restore方法。Restore方法可以为这些丢失了内存的页面重新
分配内存,并且将这些内存与DirectDrawSurface对象联系上。但重建内存并不会使以前存在于该页面上的图象重新显现出来,
因此在调用Restore函数重建之后,必须亲手重新绘制所有的图象。在这里我用了DDReLoadBitmap函数,这个函数也是
Ddutil.cpp里面的。需要说明的是,如果用DDLoadBitmap代替DDReLoadBitmap是不行的!你可以看看这两个函数的实现,比较一下。

分享到:
评论

相关推荐

    DirectX学习全解

    二、DirectX学习的重要性 1. 提升游戏性能:通过DirectX,开发者可以直接控制GPU,实现高效的图形渲染,提升游戏帧率。 2. 兼容性:DirectX是Windows平台的标准,确保游戏能在各种硬件配置上运行。 3. 跨平台开发:...

    directx 学习的相关网站

    directx 学习的相关网站 仔细找啊 很多好东东

    从头学习DirectX 9

    在从头学习DirectX 9的过程中,首先你需要理解其核心组件: 1. **Direct3D**:这是DirectX中最重要的部分,用于3D图形编程。它允许开发者创建复杂的3D模型,进行光照、纹理、渲染等处理,并通过GPU执行高效的计算。...

    directx学习指南

    ### DirectX 学习指南 DirectX 是一套专为游戏开发者设计的强大 API 集合,由微软开发并维护。它提供了高性能的多媒体编程接口,尤其是针对 Windows 平台上的游戏和视频应用程序。DirectX 主要包括 Direct3D、...

    DirectX11学习资料

    标题“DirectX11学习资料”表明本文将介绍DirectX 11的使用和学习资源,DirectX 11是微软公司推出的一款用于Windows平台下的应用程序接口(API),专门用于增强计算机图形处理能力,尤其是在3D游戏开发领域中。...

    DirectX学习笔记1-10

    "DirectX学习笔记1-10"这个压缩包很可能是对DirectX的学习教程或实战指南,内容可能涵盖DirectX的基本概念、安装配置、Direct3D的使用方法、图形渲染流程、纹理映射、动画处理、输入设备的管理以及声音处理等各个...

    DirectX修复工具V4.3增强版

    DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题设计,可以完美修复该问题。本程序中包含...

    一个在学习过程中的DirectX资料

    这个压缩包文件包含了丰富的DirectX学习资源,可能是教程文档、源代码示例、工具软件或者相关教程视频。 在深入探讨DirectX之前,我们需要了解它的重要性。DirectX广泛应用于游戏开发,因为它能提供硬件加速,提高...

    [DirectX]日本的DirectX教材

    通过分析和运行这些源码,学习者可以直观地看到DirectX API是如何被调用来创建3D场景和交互的,这将极大地加速学习过程。 而"可执行文件"很可能是书中示例程序的预编译版本,用户可以直接运行,观察实际的3D效果,...

    directx修复工具增强版.zip

    directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复工具增强版directx修复...

    DirectX角色扮演游戏编程第二版Part II

    这是Jim Adams的《Programming Role Playing Games with DirectX》第二版的中文版的第二部分。一共两部分。

    Directx修复工具_DirectX Repair 4.1高级增强版(供大家学习研究参考)

    Directx修复工具_DirectX Repair 4.1高级增强版 Directx修复工具_DirectX Repair 4.1高级增强版 Directx修复工具_DirectX Repair 4.1高级增强版

    Directx12 游戏开发

    DirectX 12游戏开发的知识点涵盖了3D...该教程适合初学者,内容涵盖了DirectX 12游戏开发的基础知识和技能,不仅包括理论知识,还着重于实际操作和代码编写,使得学习者可以快速入门并掌握DirectX 12的3D游戏开发技术。

    DirectX学习教程

    这个"DirectX学习教程"包含了一系列关于如何使用DirectX的知识点和实践代码,帮助开发者深入理解和应用DirectX。 1. **DirectX组件**:DirectX由多个组件构成,包括Direct3D(3D图形)、DirectDraw(2D图形)、...

    DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南

    DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX 游戏开发终极指南DirectX ...

    《Programming Role Playing Games with DirectX》第二版chap 2的Draw2D和Draw3D代码

    通过阅读和理解这两个模块的源代码,开发者可以学习如何有效地利用 DirectX API 创建动态、交互式的 2D 和 3D 游戏场景,这对于任何希望从事游戏开发,尤其是角色扮演游戏开发的人来说,都是非常宝贵的实践经验和...

    DirectX 修复工具 DirectX Repair v4.3.0

    DirectX异常修复工具(DirectX Repair)是一款系统级工具软件,本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题设计,可以完美修复该问题。本程序中包含了最新版的...

    DirectX修复工具 V3.3增强 绿色版

    DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题...

    学习directX实用的x文件模型

    学习DirectX时,掌握`.x`文件模型的读取和解析是非常实用的技能。这涉及到理解文件结构、数据类型以及如何将这些信息转换为DirectX可以理解的格式。例如,你需要知道如何从文件中提取顶点数据,如何解析纹理信息,...

Global site tag (gtag.js) - Google Analytics