none
Direct3D10.1で画面キャプチャするには? RRS feed

  • 質問

  • Direct3D10.1でレンダリングした画像をキャプチャするにはどうすればいいでしょうか?

    できればCImageクラスで取り扱えるようにしたいです。

    ゲームプログラムで自分自身のプレイ画面を録画するようなことがしたいです。

    2014年5月2日 2:16

回答

  • 質問するときは最低限のマナーとして、もっと詳しい情報(特に開発環境、SDKなど)を毎回書きましょう。すでに別のスレッドで記載していたとしても、です。

    Direct3D 10以降を使っているのであれば、バックバッファのスワップチェーンからそのテクスチャリソースのインターフェイスID3D10Texture2Dを取り出す方法は分かりますよね?

    Direct3Dではレンダーターゲットになっているテクスチャ(D3D10_USAGE_DEFAULT)をMap/Unmapして直接CPUで内容を読み出すということはできないので、まずD3D10_USAGE_STAGINGとD3D10_CPU_ACCESS_READを指定してCPUがアクセスできるリードバック用テクスチャ(バックバッファと同サイズ・同フォーマット)を別途用意し、ID3D10Device::CopyResource()を使って(シーンレンダリング後の)バックバッファテクスチャからリードバック用テクスチャへ内容をコピーした後で、ID3D10Texture2D::Map()を使ってDIBデータを取り出します。バックバッファのフォーマットは通例DXGI_FORMAT_B8G8R8A8_UNORMを使っていると思いますが、これはGDIの32bit BGRA Windows Bitmapと内部的には同じフォーマットなので、後は例えばCImage::Create(), CImage::GetBits(), memcpy(), CImage::Save()を使うなりしてファイル保存すればよいかと。

    マルチサンプルアンチエイリアス(MSAA)を使う場合、バックバッファは非MSAAにして、まず別のMSAAレンダーターゲットテクスチャにシーンをレンダリングし、次にピクセルシェーダーを使ってバックバッファにダウンサンプル転送したのちにリードバック用テクスチャにコピーします。MSAA→非MSAAのダウンサンプルに関してはID3D10Device::ResolveSubresource()を使う方法もあります。

    CodePlexで公開されているDirectXTexライブラリには(Direct3D 11用ですが)スクリーンショット作成用コードScreenGrabが付属しているので、詳しくはそちらを参考にしてください。

    ちなみに旧DirectX SDK付属のD3DXライブラリにはD3DX10SaveTextureToFile()というヘルパー関数があり、テクスチャの内容をDDSフォーマットでファイル保存できますが、内部では上記で説明したStagingリソース経由のコピー処理を行なっているはずです。

    ところで下記スレッドにて質問されていた問題はその後解決しましたか? 問題点が明らかになったとき、自己レスなどの形で経緯・詳細を報告しておくと、同じ問題に突き当たっている他の誰かの役に立つことがあるかもしれません。

    Direct3D10.1の警告について

    • 編集済み sygh 2014年5月9日 16:09
    • 回答としてマーク たけし 2014年5月11日 15:32
    2014年5月9日 12:10