DirectDraw

  这部分介绍了 DirectX API 的DirectDraw部分, 共分以下几部分:


关于 DirectDraw

  DirectDraw是 DirectX API 的一部分能让你直接操作显存, 硬件显存块移动(Blitter), 支持硬件屏遮(OverLay), 翻转平面(Flipping Surface). DirectDraw在提供这些特性同时保持与Microsoft Windows的应用程序及设备驱动程序的兼容.

  DirectDraw 是一个与Windows 图形系统接口(GDI) 相兼容的直接操作显示设备的软件接口. 这并不是一个高级的图形API. DirectDraw为游戏及Windows提供一个与系统无关的软件子系统, 例如: 3-D图形及数字图象编译码器, 更好的访问特殊显示设备.

  DirectDraw 可以在许多各种不同的显示硬件上工作, 从简单SVGA监视器到硬件支持剪切、伸拉,及非RGB色彩格式. 这个接口可使你的程序使用各种硬件特性及DirectX模拟的硬件尚不支持的特性.

  DirectDraw 提供与硬件无关性的同时允许直接操作显存. 程序只要使用一些基本的标准硬件约定如: RGB及YUV色彩格式及解析度. 你无须调用特殊的过程来使用显存块移动(Blitter)及调色板. 使用DirectDraw, 你可简单操作显存, 完全使用各种硬件特性而不必理会各种不同硬件之间的差异。

  DirectDraw 提供一个世界范围的运行在Windows95 及Windows NT Version4.0 及以上的游戏图形系统.


为什么使用DirectDraw?

DirectDraw 组件为你,Windows图形程序程序员,提供了许多有力的特性功能:

这些特性使你能完全能表现标准的基于GDI的Windows程序甚至MS-DOS应用程序.


准备开始: 基本图形概念

  这部分简介了DirectDraw下的图形程序. 所有的介绍都是非技术性的深入浅出的, 以DirectDraw如何支持的部分特性为向导.

  如果你是一个图形操作高手便可跳过这部分内容直接学习DirectDraw的精髓部分. 如果你熟悉Windows下C及C++编程, 那你就不难消化这部分内容. 当你阅读完这部分内容,你就有了一个坚实的DirectDraw基本图形概念. 共分以下几部分:


  1. 设备无关位图

      Windows及DirectX都使用与设备无关位图(DIB)作为其原始图形格式. 本质上, 一个DIB文件就是包含描述图象的尺寸, 使用多少色彩, 描述这些色彩的参数, 每一像素的描述数据. 另外, 一个DIB还包含一些基本参数如: 压缩信息, 有效色(如果没有使用), 及物理尺寸(如打印输出到尾部). DIB通常以BMP为扩展名, 有时也使用DIB为扩展名.

      因为DIB在Windows程序中应用广泛, 操作系统SDK已经包含许多函数操作DIB你可与DirectX一起使用. 例如: 以下例程Ddutil.cpp定义一个功能, 用Win32及DirectX的函数读取一个DIB到一个DirectX平面:

    extern "C" IDirectDrawSurface * DDLoadBitmap(IDirectDraw *pdd, 
        LPCSTR szBitmap, int dx, int dy) 
    { 
        HBITMAP             hbm; 
        BITMAP              bm; 
        DDSURFACEDESC       ddsd; 
        IDirectDrawSurface *pdds; 
     
        // 
        //  这是Win32部分
        //  试图读取一个Bitmap(位图)
        //  如果失败,用文件代替
       // 
        hbm = (HBITMAP)LoadImage(
                GetModuleHandle(NULL), szBitmap, 
                IMAGE_BITMAP, dx, dy, LR_CREATEDIBSECTION); 
     
        if (hbm == NULL) 
            hbm = (HBITMAP)LoadImage(
                    NULL, szBitmap, IMAGE_BITMAP, dx, dy,
                    LR_LOADFROMFILE|LR_CREATEDIBSECTION); 
     
        if (hbm == NULL) 
            return NULL; 
     
        // 
        // 获取位图的尺寸 
        // 
        GetObject(hbm, sizeof(bm), &bm); 
     
        // 
        // 现在回到DirectX函数调用 
        // 为该位图创建一个DirectDrawSurface(平面) 
        // 
        ZeroMemory(&ddsd, sizeof(ddsd)); 
        ddsd.dwSize = sizeof(ddsd); 
        ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; 
        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 
        ddsd.dwWidth = bm.bmWidth; 
        ddsd.dwHeight = bm.bmHeight; 
     
        if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK) 
            return NULL; 
     
        DDCopyBitmap(pdds, hbm, 0, 0, 0, 0); 
     
        DeleteObject(hbm); 
     
        return pdds; 
    }
    
    要获得DIB的详细内容参见WIN32SDK.

  2. 绘制平面

      绘制平面接收数据将图象显示到屏幕(位图). 在大多数Windows程序中都要通过Win32函数来创建绘制平面例如GetDC, 用来获取设备句柄(DC).当你获得设备句柄后, 你就可向屏幕输出. 不管怎样, Win32的图形函数是系统另一部分提供的, 图形设备接口(GDI). GDI是为Windows应用程序提供一个图形输出的抽象层.

      对GDI来说最不利的就是对于多媒体来说它不是高度优化的. 它是用来制作商用程序如WORD或电子表格. GDI能操作系统内存, 而不是显存, 也无法发挥硬件所提供的特性. 简言之, GDI对大多数商业软件已足够, 但性能太差无法满足多媒体及游戏软件。

      另一方面, DirectDraw能让你绘制平面来显示显存中的内容. 这意味着当你使用DirectDraw, 你能直接操作显示卡的显存, 使图形操作非常快. 这些平面能反映对应的显存块, 使寻址更容易.

      详见平面.

  3. 块图形移动

      Blit术语是块移动(Bit Block Transfer), 就是将一内存块从原地整块移动到其他地方. 图形程序用Blit将图形从一内存块移动到其他地方. Blit通常用于小物体精灵 (Sprite)的移动, 将在以后讨论. 详见DirectDraw的Blit和平面(Surface)的Blit.

  4. 交换页和屏后缓冲

      页交换是多媒体, 动画, 及游戏的关键. 软件上的页交换就象画卡通的一叠纸. 艺术家只要在每张纸上稍加修改, 当你快速翻动时, 它就动起来了.

      软件页交换过程与此很象, 当你设置许多DirectDraw平面, 就象艺术家的纸一张一张的层叠, 第一个平面称为主平面, 而后面的平面称为屏后缓冲. 你的程序事先修改屏后缓冲的图象, 然后翻开主平面, 屏后缓冲便显示出来了. 当系统显示图象, 你的程序继续写屏后缓冲. 就这样不停继续, 使你能高速高效显示动画. DirectDraw能使你简单实现使用页交换, 如简单双缓冲(一个主平面一个屏后缓冲)或更多更复杂的多屏后缓冲. 详见DirectDraw教程及平面交换.

  5. 矩形

      通过DirectDraw及Windows程序, 屏幕上的对象都归于一个叫绑定矩形 (Bounding Rectangles)的术语. 在绑定矩形通常与屏幕平行, 因此绑定矩形由两点决定, 左上角及右下角. 多数程序在Blit时使用RECT结构来设置绑定矩形的信息. RECT结构如下:

    typedef struct tagRECT { 
        LONG    left;    // 这是左上角的X坐标。
        LONG    top;     // 这是左上角的Y坐标。
        LONG    right;   // 这是右下角的X坐标。
        LONG    bottom;  // 这是右下角的Y坐标。
    } RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;  
    
    在上面的结构中, 左面及上面的X,Y坐标是绑定矩形的左上角. 同样, 右面及下面的数是绑定矩形的右下角. 下面的图片直观显示了该结构:

    显示屏幕(3378字节)

    出于效率, 兼容, 易用性, 所有的DirectDraw的Blit函数都以绑定矩形来工作. 不管怎样, 你可使用自由Blit自行定义Blit, 详见自由Blit.


上篇|返回|下篇

Lucker 1998.12.27
E-Mail: fred_cai@kali.com.cn


云风工作室 制作