DirectXで遊ぼう 上のページ

IDirectDrawSurface その2(通常サーフェイス生成)
  1. 概要

    もうひとつのサーフェイスの生成方法を説明します。

    以下の内容について解説します。

  2. サンプルプログラム

    IDirectDrawオブジェクトからサーフェイスを生成する方法です。
    IDirectDrawの説明で使用した、ddrawから呼び出す事を前提としています。
    LPDIRECTDRAWSURFACE dds_image;  // IDirectDrawSurfaceのポインタ
    DDSURFACEDESC dds;              // CreateSurfaceに渡す構造体
    HRESULT r;                      // 関数の返値
    
    #define SIZE_WIDTH      100     // サーフェイスのサイズ
    #define SIZE_HEIGHT     100     //
    
    ZeroMemory(&dds,sizeof(DDSURFACEDESC));
    dds.dwSize = sizeof(DDSURFACEDESC);
    dds.dwHeight = SIZE_HEIGHT;
    dds.dwWidth = SIZE_WIDTH;
    dds.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_DDSCAPS;
    dds.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
    r = ddraw->CreateSurface(&dds,&dds_image,NULL);
    if(r != DD_OK){
        //
        // CreateSurface失敗(r:エラーコード)
        //
    }
    
  3. 生成に用いる構造体

    DDSURFACEDESC構造体に、サーフェイスを生成するための情報を設定する必要があります。
    しかし、プライマリサーフェイスを生成するには以下の情報だけで十分です。

    • dwSize
      DDSURFACEDESC構造体の大きさを格納します。

    • dwFlags
      DDSURFACEDESC構造体中にあるデータ中において、有効にするデータをフラグで設定します。
      プライマリサーフェイスと異なりサーフェイスのサイズ等の設定も必要になるので、 DDSD_HEIGHT|DDSD_WIDTH|DDSD_DDSCAPSという風に論理和でフラグを与えています。

    • dwHeight,dwWidth
      生成するサーフェイスのサイズを与えています。

    • ddsCaps
      サーフェイスの属性を設定します。
      ここではオフスクリーンに展開するという事を宣言(DDSCAPS_OFFSCREENPLAIN)しています。

  4. 生成する場所を指定するには?

    ddsCapsに与えるフラグによって、生成する場所を変更する事ができます。
    サンプルプログラムではデフォルトの動作を行うようになっており、VRAMを優先し、次にシステムメモリを選択するようになっています。
    通常VRAMに展開するとDirectDrawの動作は高速になりますが、任意にシステムメモリに展開したいケースもあると思います。 またVRAMのみに展開したいという事もあるでしょう。 そのときは、以下のフラグを与えます。

    DDSCAPS_SYSTEMMEMORYシステムメモリに生成する
    DDSCAPS_VIDEOMEMORYVRAMに生成する

    しかしDDSCAPS_VIDEOMEMORYを指定した場合、VRAMの少ないマシンではこれが失敗する事があります。
    対応する環境を増やしたい場合には、ムリにVRAMにするよりかはデフォルトの設定で確保した方が良いと思います。 この場合、GetCapsでシステムメモリとVRAMのどちらで確保できたかをチェックし、システムメモリで確保した場合にはユーザーにパフォーマンスが低下する事を教えるという手もあります。

  5. サーフェイス展開

    サーフェイスに画像を展開するには、生成したオブジェクトからLockメンバ関数を呼び出します。
    DDSURFACEDESC dds;
    HRESULT r;
    
    ZeroMemory(&dds,sizeof(DDSURFACEDESC));
    dds.dwSize = sizeof(DDSURFACEDESC);
    r = dds_image->Lock(NULL,&dds,DDLOCK_WAIT,NULL);
    if(r != DD_OK){
        //
        // Lock失敗(r:エラーコード)
        //
    }else{
        //
        // ここに、サーフェイス展開を行うコードを記述します
        //
        dds_image->UnLock(NULL);
    }
    
    Lockから取得される構造体DDSURFACEDESCにある、以下の情報を使用します。

    • lPitch
      1ラインを定義するのに必要な画像データサイズです。
      この値はビデオカードによって異なるので、展開時には必ず参照する必要があります。

    • lpSurface
      サーフェイスの先頭ポインタです。
      ここに記述されているアドレス以降から展開していく必要があります。

    例えば256色の場合1ピクセルに必要なデータ容量は1バイトですので、以下のように参照する事によって展開を行うことができます。

    *((LPBYTE)dds->lpSurface + y * dds->lPitch + x) = p;
    // x,y:展開場所
    // p:カラーコード



上のページ