高级DirectDraw(一)

使用高彩模式
上一章中说了可以用16位的色彩深度,但是16位的色彩深度的数据表示模式可以有两种:Alpha.5.5.5(or X.5.5.5) 和 5.6.5(这是16位色彩最常用的)。对于使用哪种16位的色彩模式这个是由硬件决定的,我们不能决定。但是我们可以查询,然后按照硬件支持的模式来填写。
我们可以调用方法IDIRECTDRAWSURFACE7::GetPixelFormat(),同时这个函数需要一个LPDDPIXELFORMAT的结构,其中的dwFlags 和 dwRGBBitCount成员记录着像素格式(8位索引或者RGB模式)
示例代码如下:
DDPIXELFORMAT ddpixel;   
memset(&ddpixel, 0, sizeof(ddpixel) );  
ddpixel.dwSize = sizeof(ddpixel);  
lpddsprimary->GetPixelFormat(&ddpixel); 
                                    
if (ddpixel.dwFlags & DDPF_RGB)  // RGB Mode  
{    
        switch(ddpixel.dwRGBBitCount)    
        {    
                case 15:  // 5.5.5 
                break;   
                case 16:  // 5.6.5     
                break;                                   
                case 24:                                          
                break;                     
                case 32:            
                break;            
                default:      
                break;         
        }        
}         
else  // ddpixel.dwFlags & DDPF_PALETTEINDEXED8 == TRUE
{            
              
}      
对于32位的模式也可以用以上判断代码,并且将填写颜色的代码写在case 32:里面。
32位色彩的两种模式为:Alpha.8.8.8 和 X.8.8.8。对于后面的一种,建议将X的8位置为0。
双缓冲
现在我们已经可以对表面进行修改了。这样也就是通过视频控制器直接将每一帧都光栅化。这对于静态图像来说已经很好了。但是如果是动画呢?可能就不是非常平滑。我们就需要使用双缓冲技术。即先申请一个和主表面同样大小的数组(或者数据块),将色彩数据填写进这个数组中,最后再复制进加锁的表面中。在复制的时候我们需要注意表面是否线形的问题。如果是线性的,那么我们可以把整个数据块一并复制;如果不是,那么我们只能一行行来复制。(其中这种技术我们并不会真正的用到,除非数据块很小。因为DirectDraw提供给我们更好的动态表面)
表面动态
离屏表面一——后备缓冲。创建后备缓冲的目的是用DirectDraw的方式来实现对双缓冲功能的仿真。如果创建了DirectDraw后备缓冲(通常在VRAM中),读写会非常快。你可以将它和主表面进行页面切换,这比双缓冲方案下所需做的内存复制要快得多。
创建一个关联有后备缓冲的主表面步骤:
  1. 首先,你要将DDSD_BACKBUFFERCOUNT加到dwFlags标志字段,向DirectDraw表明DDSURFACEDESC2结构的dwBackBufferCount字段有效,其中含有后备缓冲的数目。
  2. 其次,将控制标志DDSCAPS_COMPLEX 和 DDSCAPS_FLIP加到DDSURFACEDESC2结构的特性描述字段ddsCaps.dwCaps上。
  3. 最后,像通常一样创建主表面。从它调用IDIRECTDRAWSURFACE7::GetAttachedSurface() 以得到后备缓冲。

示例代码:

LPDIRECTDRAWSURFACE7 lpddsback;

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;                                       
ddsd.dwBackBufferCount = 1;                                                                                         
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;                                                                                                                    
lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL);                                                
ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;                                                       
lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback);                    

注意其中红色属性。

这样一来,以后只要每次都在后备缓冲绘图,然后调用Flip方法进行表面切换,就可以实现快速的翻页。

示例代码:

lpddsprimary->Flip(NULL, DDFLIP_WAIT);

需要注意两点,1.翻页总是由主表面执行的。2.翻页前主表面或者后备缓冲表面都必须解锁

By Lu Jun

80后男,就职于软件行业。习于F*** GFW。人生48%时间陪同电子设备和互联网,美剧迷,高清视频狂热者,游戏菜鸟,长期谷粉,临时果粉,略知摄影。

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.