読者です 読者をやめる 読者になる 読者になる

IDirectDrawSurface7::Blt

DirectX編・・・。

DirectX (ダイレクトエックス) ダウンロード/総合情報 - Microsoft

DirectXは、Microsoftが開発したマルチメディアAPI・・・。
ゲーム開発における、グラフィック、サウンド、入出力の実装などに役立っている・・・。

最新はDirectX12だが、ここではとってもレガシーなDirectX7から扱っていく・・・少しだけ・・・。

DirectX7にはDirectDrawというとってもレガシーな2D処理API群があったので、それを使って画像を表示してみる・・・。

ここでの実行環境はWIndows7なので、このOSでの最終バージョンは、

Download DirectX Software Development Kit from Official Microsoft Download Center

DXSDK_Jun10.exeである・・・。

しかし、このバージョンはDirectDraw非対応になってしまったので、DirectDrawが使えるのは、

Download DirectX Software Development Kit from Official Microsoft Download Center

DXSDK_Feb10.exeなので、こっちをダウンロードしてインストール・・・。

また、インストール中にエラーが出ることがある・・・。

DirectX SDKインストール時に”S1023エラー”が出る時の対処法

こんなのが出たので、再配布パッケージを削除してから再インストールするなど・・・。

インストールしたら、

f:id:BG1:20160810141313p:plain

[ツール]-[オプション]から、

f:id:BG1:20160810141405p:plain

インクルードパスが通ってるか確認・・・。

f:id:BG1:20160810141445p:plain

ライブラリパスも・・・。
上に追加されてるとおもうので下に寄せとく・・・。
(他のライブラリとのビルド順調整のつもり・・・。)

Win32の空のプロジェクトを作成したら、

f:id:BG1:20160810141654p:plain

ddraw.libとdxguid.libをリンク・・・。

f:id:BG1:20160810141903p:plain

test.bmpを置く・・・。

でIDirectDrawSurface7.cppを追加して、コードを書いてく・・・。

ddraw.hをインクルード・・・。

DirectXはCOMベースのライブラリなので、ポインタを指定するとReleaseメソッドが呼ばれてポインタをNULLにするようなマクロSAFE_RELEASEを用意しておくのが慣習・・・。

たくさん、変数やらオブジェクトやらあるが、都度説明・・・。

まずは、

高速描画を実現するため、PeekMessageによるメインループ構造にする・・・。
メッセージが来ていない時に、DirectXによる描画処理を行う・・・。
(ゲーム開発ではよく使われている慣習・・・。)
まずはiPhaseが0の時(一回しか実行されない)は、DirectXによる描画の準備を行う・・・。

DirectDrawCreateExでDirectDrawオブジェクトを生成する・・・。
戻り値はHRESULT型なので、FAILEDマクロで判定して、失敗ならbreakして終了処理に向かう・・・。

lpDDの型はLPDIRECTDRAW7となっているが、DirectDrawCreateでLPDIRECTDRAWなポインタを指定するなどしても作成はできる・・・。
ただし、LPDIRECTDRAW7とは違うものなので、より新しいの"7"の付いてるほうにしたほうがいいだろう・・・。

lpDD->SetCooperativeLevelで協調レベル設定・・・。
協調レベルについては、
協調レベル
こういうものらしい・・・。まあ、今回は普通のウィンドウアプリなのでDDSCL_NORMALを指定・・・。

クリッパーは表示できる範囲を指定するもので、オブジェクトポインタがlpClipに入ったら、lpClip->SetHWndでウィンドウハンドルを指定する・・・。

続いて、ウィンドウに表示される画面、プライマリーサーフェイスを作る・・・。
まず、プライマリサーフェイスディスクリプタで設定する・・・。

DDSCAPS_PRIMARYSURFACEでプライマリーサーフェイスであることを指定・・・。

DDSURFACEDESC2を使っているが、DDSURFACEDESCと間違えないように・・・。

でddsdを使って、lpDD->CreateSurfaceでプライマリーサーフェイスlpDDSPrimaryを作る・・・。

lpDDSPrimary->SetClipperでlpClipを指定・・・。

さて、続いて、表示する画像test.bmpを貼り付けたサーフェイスを作成する・・・。

まず、test.bmpをロードする・・・。

メモリデバイスコンテキストhMemDCを作成・・・。

SelectObjectでhMemDCとhBitmapを紐づけ・・・。

画像の幅と高さを知りたいので、GetObjectでBITMAPオブジェクトbitmap取得・・・。

サーフェイスディスクリプタを設定・・・。
システムメモリでオフスクリーン(表示されない)なサーフェイスで、ビットマップの幅と高さに合わせたものとして作成・・・。

lpDD->CreateSurfaceでサーフェイス作成・・・。

lpDDSBitmap->GetDCで、このサーフェイスのデバイスコンテキストを取得・・・。

BitBltでメモリデバイスコンテキストから、ビットマップサーフェイスのデバイスコンテキストにビット転送・・・。
これでビットマップサーフェイスに画像が映る・・・。

lpDDSBitmap->ReleaseDCでビットマップサーフェイスのデバイスコンテキストを解放・・・。
hDDSBitmapDCはもうNULLにしちゃう・・・。
(これをやっても、プライマリーサーフェイスに描画した時、画像は消えていない・・・。)

iPhaseを1にする・・・。
これでここはもう通らない・・・。

次にここに来る・・・。
ここでサーフェイスを描画する・・・。

GetWindowRectでウィンドウ矩形を取得し、ウィンドウタイトルとか境界線とかの分を調整したら、lpDDSPrimary->BltでlpDDSPrimaryの上にlpDDSBitmapを描画する・・・。

IDirectDrawSurface7::Blt method (Windows)

でこれを繰り返してる・・・。

ウィンドウの閉じるボタンなどで、メインループを抜けたら、

作成した順とは逆にSAFE_RELEASEなどで削除・解放をしていく・・・。

これで実行すると、

f:id:BG1:20160810152735p:plain

test.bmpが表示される・・・。

Sample/dx/IDirectDrawSurface7/Blt/src/IDirectDrawSurface7 at master · bg1bgst333/Sample · GitHub