2010年07月28日

C#からDirect3Dを使う第3の方法

C#からDirect3Dを使う手段として、以前はManaged DirectXがありましたが2007年頃からDirectX SDKから削除されてしまいました。

Managed DirectXが消された代わりに、現在はXNA FrameworkというPCとXbox360両方で動くゲームが作れるフレームワークを使うことでDirect3Dを使った描画を行うことができます。しかし、XNA Frameworkはゲーム製作のために高度に抽象化されたライブラリなのでDirect3Dとは全くの別モノになっています。

もう1つ、C#でDirect3Dを使う手段がMicrosoftから提供されています。それが今回紹介する「Windows® API Code Pack for Microsoft® .NET Framework」です。

API Code Packは、Windows Vistaや7の機能でC++からは利用できるがマネージコードからは利用できないAPIを、C#等のマネージコードから利用できるようにするライブラリです。その中にDirect3Dも含まれています。

例としてDirect3D10は次のようになっています。

API Code Pack

C++用のインターフェースから、ID3D10の接頭語を抜いた名前でクラスが定義されています(一部のクラスはD3Dの接頭語付き)。引数や戻り値が変わっているものもありますが、ほとんどが元のインターフェースと同じように定義されています。XNAのような抽象化されたものではなく、もっとDirect3Dをダイレクトに使いたいというDirect3D大好きっ子でも安心です。

ちなみに、API Code Packはソースコードでの提供となっているので、利用するには自分でビルドする必要があります。ライブラリ部分はC++/CLIで書かれているので、ビルドするにはVisualC++が必要になります。たぶんライブラリのビルドはExpress Editionでも出来ると思いますが、サンプルプログラムはC++とC#の混合プロジェクトなので、Express Editionではビルドできないと思います。

D3DXに相当するコードも用意されていますが、D3DXの全てを網羅しているわけではないようです。さっと見た感じでは、実行時にシェーダをコンパイルする機能は無さそうです。

また、みんなが大好きなDirect3D9もありません。対応しているのはDirect3D10.0、10.1、11.0、DXGI1.0、1.1となっています。Direct2DやDirectWriteにも対応しています。

ぶっちゃけ誰にでも作れそうなラッパーライブラリですが、Microsoftが公開したことで標準と呼べる物ができたのは大きいですね。

ところで、サンプルプログラムは無操作でもアニメーションし続けているにも関わらず、コールバックタイマーのような物が見当たらないので、どうやって画面を更新し続けているのか調べてみたら、次のようになっていました。

IntPtr DirectHost::WndProc( IntPtr hwnd,  int message,  IntPtr wParam,  IntPtr lParam, bool% handled)
{
    switch (message)
    {
    case WM_PAINT:
    case WM_DISPLAYCHANGE:
        {
            if (Render != nullptr)
                Render();            
        }
        handled = true;
        return IntPtr::Zero;

    case WM_DESTROY:
        {
            Render = nullptr;
            break;
        }
    }

    handled = false;
    return IntPtr::Zero;
}

通常、WM_PAINTのハンドラではBeginPaint/EndPaintやValidateRect等を呼んで、無効領域のクリアをしないといけません。しかし、このサンプルではWM_PAINTで何もしていないので、無効領域がクリアされず永遠にWM_PAINTが発生し続けます。

普通はWindowsプログラマがやってはいけないことのタブーを、このサンプルプログラムでは画面更新のトリガーに使っています。私の感覚では、気持ち悪いですね。

VistaからGDIのティアリングを抑える設計になったので、この方法で上手い具合にWM_PAINTが発生するんですかね?DWMを切った状態でどうなるのか、ちょっと心配です。



2010年07月28日 【プログラミング】 | コメント(0) |

この記事へのトラックバック
この記事へのコメント

コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。