CSDN博客

img holyfire

DirectX5.0最新游戏编程指南 DirectDraw篇 三、DirectDraw的要素(四)

发表于2001/4/14 12:59:00  1407人阅读

5、调色板(Palette)
    调色表面需要有调色板才能正确地显示出来。一个调色表面(既颜色索引标)是一些数字的简单集合,其中每个每个数字都表征了一个像素。数字的值是一个颜色表的索引,它告诉DirectDraw显示每个像素时该使用什么颜色。DirectDrawPalette对象通常称为调色板,它提供了管理颜色表的简单方法。使用16位或更高位数的像素格式的表面不使用调色板。
     DirectDrawPalette对象表征了具有2、4、16或256个实体的用于颜色索引表面的索引颜色表。调色板中的每个实体都是一个RGB三元组,描述了显示表面内像素所使用的颜色。颜色表可以包含16位和24位RGB三元组来表征所用的颜色。对于16色的调色板,颜色表也能包含另一个256色的调色板的索引。调色板可以应用在纹理、屏外表面和覆盖表面中,它们都不要求具有和主表面相同的调色板。
你可以调用IDirectDraw2::CreatePalette方法创建一个调色板,该方法取得调色板对象的IDirectDrawPalette接口的指针。然后就可以利用该接口的方法处理调色板的实体,获取有关对象能力的信息或初始化对象(若调色板是用COM函数CoCreateInstance创建的)。
    调用IDirectDrawSurface3::SetPalette方法可将一个调色板附加在一个表面上。一个单一的调色板可以应用到多个表面上。DirectDrawPalette对象对8位的调色板保留实体0和实体255,除非你指定了 DDPCAPS_ALLOW256标志要求这两个实体可用。你可以用IDirectDrawPalette::GetEntries方法获得调色板实体,用IDirectDrawPalette::SetEntries方法修改调色板实体。
5.1、调色板类型
    DirectDraw支持1位、2位、4位和8位的调色板。一个调色板只能附给具有相同像素格式的表面。例如,一个由DDPCAPS_1BIT标志创建的2实体调色板只能附给用 DDPF_PALETTEINDEXED1标志创建的1位表面。另外,也可以创建完全不包含颜色表的调色板,即索引调色板。同颜色表不同的是,索引调色板包含了索引值,这些值表征了另一个调色板颜色表的位置。
    要创建一个索引调色板,需调用IDirectDraw2::CreatePalette方法,指定 DDPCAPS_8BITENTRIES标志。例如,要创建一个4位调色板,还需要指定DDPCAPS_4BIT和DDPCAPS_8BITENTRIES标志。当创建索引调色板时,要将一个指针传递给字节数组。
5.2、设置非主表面上的调色板(Setting Palettes on Nonprimary Surfaces)
    调色板能够附在任意的调色表面(主表面,后台缓冲区,屏外表面和纹理贴图)上,但只有附在主表面上的调色板才能影响系统调色板。
必须注意的是,DirectDraw位块传输不会执行颜色变换操作,任何附于位块传输的源表面和目的表面都被忽略。非主表面上的调色板主要用于Direct3D应用程序。
5.3、共享调色板(Sharing Palettes)
    调色板可以在多个表面之间共享。同一个调色板可以附于一个翻转链的前台缓冲区和后台缓冲区,也可以共享于多个纹理表面。当使用IDirectDrawSurface3::SetPalette方法将一个调色板附于一个表面时,该表面就会增加该调色板的索引值,当表面的索引值达到0时,该表面就会减少附着的调色板的索引值。另外,如果一个调色板同一个表面分离开,该表面的调色板的索引值也会减少。
5.4、调色板动画(Palette Animation) 
    调色板动画是指在显示时通过改变表面的调色板来更改表面的外观的过程。重复地改变调色板,表面看起来就象是改变了,但实际上,表面的真实内容并无变化。因此,调色板动画提供了一种改变表面的显示表现而不改变表面的具体内容的方法。对于直线式的调色板动画可以提供两种办法:
   i. 在单一的调色板修改调色板实体
   ii. 在多个调色板之间切换 
使用前一种方法,你可以改变耽搁调色板中那些相关颜色的实体,然后调用 IDirectDrawPalette::SetEntries方法一次复位这些实体。第二种方法要求2个或多个DirectDrawPalette对象,然后调用IDirectDrawSurface3::SetPalette方法将一个接一个的调色板对象附给表面对象从而产生
动画。两种方法都同硬件无关,因此使用哪种方法主要是看是否适合应用程序。

6、剪切板(Clipper)
    剪切板或DirectDrawClipper对象允许位块传输到表面中选定的部分。一个剪切板对象拔海内一个或多个剪切板列表。一个剪切板列表就是一个有界矩形或几个有界矩形列,它是表面中允许位块传输到的一块或几块区域。这些区域都由RECT结构以屏幕坐标的方式来表示。
    剪切列表是一个非常有用的工具,其中最常用的是禁止应用程序将数据块写到超出屏幕边界的地方。例如,若要显示一个精灵从屏幕边界进入,你不希望精灵一下子就弹出出现在屏幕上,而是平滑地慢慢从屏幕边界一点一点移动到屏幕中央。若没有剪切板对象,就需要包含限制位块操作以保护表面内存的逻辑。下图显示了这一类的剪切。
 
     你可以使用剪切板对象来芝麻一个目的矩形的一定区域是可写的,DirectDraw将在这些区域对位块传输加以剪切以保护指定的剪切矩形之外的像素。这种剪切方式如下图所示:
 
6.1、剪切列表(Clip List)
     DirectDraw用DirectDrawClipper对象来管理剪切列表。一个剪切列表就是描述表面可见区域的一系列矩形。一个DirectDrawClipper对象可以附在任何表面之上。一个窗口句柄也可以附在DirectDrawClipper对象上,在这种情况下,DirectDraw将使用窗口中更新的剪切列表来修改DirectDrawClipper剪切列表。
    尽管DirectDraw HAL中剪切列表可见,DirectDraw也只在用矩形位块传输时才调用HAL来满足剪切列表要求。例如,若一个表面的左上角矩形被剪切掉了,在应用程序将该表面块写到主表面时,DirectDraw将使用HAL执行两次位块传输操作,第一次是传输表面的左上角,第二次操作是传输表面的下半部分。
    通过 IDirectDrawClipper::SetClipList方法可以将这个剪切列表传送给驱动程序(如果该驱动程序支持剪切),而不是多次调用驱动程序。
另外,还能通过指定目的窗口的句柄,调用 IDirectDrawClipper::SetHWnd方法将剪切板设到一个单一的窗口。只有当覆盖硬件支持剪切或者目的Color Key还没有被激活时,覆盖表面才支持剪切功能。
6.1、共享DirectDrawClipper对象
    DirectDrawClipper对象能在多个表面之间共享。例如,同一个DirectDrawClipper对象可以同时用于翻转链的前台和后台缓冲区。当应用程序用IDirectDrawSurface3::SetClipper方法将一个DirectDrawClipper对象附于一个表面时,次表面就增加该对象的索引值。如果一个DirectDrawClipper对象同一个表面(该表面是用IDirectDrawSurface3::SetClipper方法由一个空剪切板接口指针创建的)分离,该表面的
DirectDrawClipper对象的索引值就会递减。
6.3、独立的剪切板对象
    你可以创建一个不直接从属于任何一个DirectDraw对象的DirectDrawClipper对象。这种剪切板对象可以在多个DirectDraw对象之间共享。驱动程序独立性的剪切板对象可用新的DirectDraw函数DirectDrawCreateClipper创建,应用程序可在创建任何DirectDraw对象之前调用该函数。
    因为DirectDraw对象不能拥有这些独立的DirectDrawClipper对象,所以当应用中的对象释放后,这些DirectDrawClipper对象并不会自动释放。若应用程序没有显式地释放这些剪切板对象,DirectDraw将在程序结束时释放它们。
当然,你还是可以用 IDirectDraw2::CreateClipper方法创建DirectDrawClipper对象,用这种方法创建的剪切板对象在与其相关的DirectDraw对象释放后会自动释放。
6.4、用COM函数创建DirectDrawClipper对象
    DirectDrawClipper对象完全支持COM应用。除了使用标准的IDirectDraw2::CreateClipper方法和DirectDrawCreateClipper函数外,还可以用COM函数 CoGetClassObject 创建来创建剪切板对象。下面是用CoCreateInstance函数和IDirectDrawClipper::Initialize方法创建剪切板对象的实例:
 ddrval = CoCreateInstance(&CLSID_DirectDrawClipper,
    NULL, CLSCTX_ALL, &IID_IDirectDrawClipper, &lpClipper);
if (!FAILED(ddrval))
    ddrval = IDirectDrawClipper_Initialize(lpClipper,lpDD, 0UL);
     在对CoCreateInstance的调用中,第一个参数CLSID_DirectDrawClipper是剪切板对象类的类标志, IID_IDirectDrawClipper参数表明了当前支持的接口,lpClipper参数是剪切板对象的指针。
    应用程序必须必须使用IDirectDrawClipper::Initialize方法来初始化剪切板对象, 0UL是dwFlags参数的值,本例中表示没有使用任何标志。lpDD是拥有该剪切板对象的DirectDraw对象;若用NULL代替lpDD,将会创建一个独立的DirectDrawClipper对象,也将等价于用DirectDrawCreateClipper函数创建的剪切板对象。关闭应用程序之前,应该先用CoUninitialize函数关闭COM。
    DirectDraw通常为用户提供一种引导使用鼠标的方法。对于使用页翻转的全屏独占模式的应用程序,唯一的选择是在一个精灵上手工实现鼠标的光标,依靠由DirectInput从设备中获取的数据或窗口的鼠标消息来移动精灵。任何不使用页翻转的应用程序也可以使用系统的鼠标光标支持。
    使用系统的鼠标光标时,在块写主表面的一部分时可能会出现图像赝象现象。在位块传输操作中,剪切板对象可以防止这些赝象的出现。
在应用中,先用IDirectDraw2::CreateClipper方法创建剪切板对象,再用 IDirectDrawClipper::SetHWnd方法将应用的句柄分配给剪切板。一旦剪切板附上了,任何随后的用IDirectDrawSurface3::Blt方法实现的位块传输的操作将不会出现赝象现象。
    你可以将一个剪切板对象块写到多个窗口。首先要创建一个只有一个主表面的DirectDraw对象,然后创建一个剪切板对象,再用 IDirectDrawSurface3::SetClipper方法将剪切板对象分配到主表面。要块写到窗口的客户区(client area),需要在块写到主表面之前用IDirectDrawClipper::SetHWnd方法将剪切板设到窗口的客户区。如果需要块写到另一个窗口的客户区域,就用目标窗口的句柄再调用
IDirectDrawClipper::SetHWnd方法一次。

0 0

相关博文

我的热门文章

img
取 消
img