2014年02月25日

複数のウィンドウに対する描画2

以前複数ウィンドウに対する描画について書きましたが、実際に試した結果いくつか間違っていた点がありました。
というわけで、ひとつのデバイスで複数のウィンドウに描画する手順の修正版を以下に示します。

■ 準備する

 HWND hWnd1 = ウィンドウ1
 HWND hWnd2 = ウィンドウ2
 
 // プレゼントパラメータの作成
 D3DPRESENT_PARAMETERS pp1, pp2;
 pp1.hDeviceWindow = hWnd1;
 pp2.hDeviceWindow = hWnd2;
 ... 設定つづく ...

 // 普通にデバイスを作成
 D3D9->CreateDevice(..., &pp1, &Device);

 // ウィンドウ1に描画するために、最初のスワップチェーンを取得
 Device->GetSwapChain(0, &SwapChain1)

 // ウィンドウ2に描画するために、追加のスワップチェーンを作成して取得
 Device->CreateAdditionalSwapChain(&pp2, &SwapChain2);


■ hWnd1 に対して描画するとき

 // スワップチェーン1のバックバッファを描画先にする
 IDirect3DSurface9 *back;
 SwapChain1->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back);
 Device->SetRenderTarget(0, back);
 back->Release();

 Device->BeginScene();
 // いろいろ描画
 Device->EndScene();

 // hWnd1 に転送
 SwapChain1->Present(NULL, NULL, hWnd1, NULL, 0);


■ hWnd2 に対して描画するとき

 // スワップチェーン2のバックバッファを描画先にする
 IDirect3DSurface9 *back;
 SwapChain2->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &back);
 Device->SetRenderTarget(0, back);
 back->Release();

 Device->BeginScene();
 // いろいろ描画
 Device->EndScene();

 // hWnd2 に転送
 SwapChain2->Present(NULL, NULL, hWnd2, NULL, 0);


これでOKです。
・CreateAdditionalSwapChain で作成したスワップチェーンは、Direct3DDevice9::Reset のリセット前に破棄し、リセット後に再生成する必要があります。
・エラー処理を省略しているので、実際に使う場合は適当にエラーチェックしてください

posted by JUNOSOFT at 17:27| Comment(0) | プログラミング

2014年02月18日

複数のウィンドウに対する描画

これまでキャラクターエディタやマップエディタなど、いろいろなツールを作ってきましたが、
たとえ複数のウィンドウがあった方が便利だな、と思った場合でも、無理矢理1ウィンドウにまとめていました。
なぜなら、複数のウィンドウに対して Direct3D で描画するのが非常に面倒に思えたからです。

複数のウィンドウがあるということは描画先のウィンドウハンドルが複数存在するということで、Direct3Dデバイスの作成時にウィンドウハンドルを渡している以上、ウィンドウハンドル1つにつき Direct3D デバイスが1つ必要なわけです。
デバイスを複数つくるだけならまだしも、テクスチャはデバイスごとに管理されているため、全く同じ画像を表示したい場合でも、デバイスごとに別々のテクスチャを作成しなければなりません。同じ絵を表示するウィンドウが2つあるなら、作成・管理するテクスチャの数も2倍になるということです。

これが非常臭そうに思えたので、Direct3D による描画が必要なツールを作る場合、ウィンドウが1つで済むよう、どうにかやりくりしていました。

.... とか思ってたら、なんか SwapChain つかえばできるよ的な話が聞こえてきました。
調べてみた所、まさに欲しかった機能です。
というわけで、いま描画先として二つのウィンドウハンドル hWnd1, hWnd2 がある場合、それぞれに描画する手順(DirectX9の場合)は:

- hWnd1 を指定した D3DPRESENT_PARAMETERS を用意し、普通に IDirect3D9::CreateDevice して IDirect3DDevice9 *dev を作成
- dev->GetSwapChain で hWnd1 に対応するスワップチェーン IDirect3DSwapChain9 *sc1 を取得
- hWnd2 を指定した D3DPRESENT_PARAMETERS を用意し、dev->CreateAdditionalSwapChain で hWnd2 に対応したスワップチェーン sc2 を作成
- hWnd1 に描画する時は、sc1->GetBackBuffer → dev->SetRenderTarget で描画先をセットして描画し、dev->Present で転送(BeginScene, EndScene忘れずに)
- hWnd2 に描画する時は、sc2->GetBackBuffer → dev->SetRenderTarget で描画先をセットして描画し、dev->Present で転送(BeginScene, EndScene忘れずに)

でいけるみたいですよ?(実は未確認)
posted by JUNOSOFT at 18:32| Comment(0) | プログラミング

2014年02月07日

ラスタライゼーションルール

ラインの端1ピクセルがが描画されないのって、もしかしてコレのせいなんですかね…?

http://msdn.microsoft.com/en-us/library/windows/desktop/bb147314#Point_and_Line_Rules
posted by JUNOSOFT at 21:10| Comment(0) | プログラミング