2010年9月27日月曜日

スクリーンショットを撮る方法まとめ



分散処理と垂直同期について。
連載2 画像転送システム その2
へーい(・・)ノ タクシー
#########################
【C++】 DirectX初心者質問スレ Part26 【C】
http://pc12.2ch.net/test/read.cgi/tech/1256403984/

514 :デフォルトの名無しさん [sage] :2009/12/01(火) 18:09:59
Direct3D9でフルスクリーンモードで描画している際、
自分自身のスクリーンのキャプチャを高速に行うにはどのように実装すればいいでしょうか?

sf = device->GetBackBuffer(0, 0);
HDC srcdc = sf.GetDC();
::BitBlt(dstdc, 0, 0, gameView.Width, gameView.Height, srcdc, 0, 0, SRCCOPY);
//後略

といった形でメインメモリに転送してるのですが、
BitBltの部分でFullHDの場合で0.3秒くらいかかってしまいます。

515 :514 [sage] :2009/12/01(火) 18:20:23
情報が抜けてました。
フルスクリーンモードの描画をキャプチャするのは、キャプチャ画像をファイルとして書き出すためではなく、
描画をGDIに切り替える際の描画キャッシュとして使いたいためです。
フルスクリーンで描画中に一時的に
device->SetDialogBoxMode(TRUE);
を実行してメニューを表示したりダイアログを表示したりしています。

516 :デフォルトの名無しさん [sage] :2009/12/01(火) 18:49:58
サーフェイスをロックしてそのメモリをコピーすればいいよ。
一番いいのはダイアログを使わない事だけど。

517 :デフォルトの名無しさん [sage] :2009/12/01(火) 22:03:18
サーフェスのLockはめちゃくちゃ遅いよ。
シングルコアだとそこまで遅くはないんだが、マルチコアだと致命的な遅さ。
GetDC等も内部的にLockするので駄目。

GetRenderTargetDataが速い。

518 :デフォルトの名無しさん [sage] :2009/12/01(火) 22:35:41
有料な同人ソフト以上のモノを作るなら、GDIでがんばるより
DXUTを使うかDXUTみたいなのを自作するほうが質も速度も断然いいのでは。

519 :デフォルトの名無しさん [sage] :2009/12/01(火) 22:41:15
>>516
ちょっと事情があって、Lock使うのは避けたい……。

>>517
なるほど。確かにビデオカード→システムメモリはボトルネックになりかねないし
画面の描画自体と競合もしてしまうので、
それを避けるためにGetRenderTargetData()でさっさとシステムメモリに転送かけたほうがよさそうです。
この線で試してみることにします。

520 :デフォルトの名無しさん [sage] :2009/12/01(火) 22:57:28
初歩的な質問ですみません
DrawPrimitiveとDrawSubsetを見かけるんですが、これってどんな違いが?

521 :デフォルトの名無しさん [sage] :2009/12/01(火) 22:58:41
>>520
DrawSubmitは内部でDrawPrimitiveIndexだっけ?を使用している

522 :デフォルトの名無しさん [sage] :2009/12/01(火) 23:14:35
>>517
描画前のバックバッファをシステムメモリのサーフェイスにコピーしてロックしたほうが速いだろ?
GetRenderTargetDataなんて鈍足の代表だろ。

523 :デフォルトの名無しさん [sage] :2009/12/01(火) 23:20:39
>>522
バックバッファをシステムメモリに転送するのがGetRenderTargetDataなんだが。
GetFrontBufferDataと間違えてない?

524 :デフォルトの名無しさん [sage] :2009/12/02(水) 00:43:04
GetRenderTargetDataってAA使うと使えなくね?

528 :デフォルトの名無しさん [sage] :2009/12/02(水) 11:28:36
>>517
FullHDでも0.1秒以内にメニューが表示できる状態になることを確認しました。
どうもありがとうございます。

しかし、表示方式を切り替えた瞬間にちらつくのは、なおらんのかなー。
デュアルディスプレイのもう一方のほうもちらついてるからなぁ。
#########################
【C++】 DirectX初心者質問スレ Part6 【C++】
http://pc8.2ch.net/test/read.cgi/tech/1127198808/


589 :デフォルトの名無しさん [] :2005/10/19(水) 23:17:28
スクリーンショットを取るコードを書いていますが、
D3DXSaveSurfaceToFile以外でスクリーンショットを簡単にとる方法ってないですかね。
取り込んだデータを別のウインドウに書き出したり手を加えたりすることも考えて、
メモリ上にデータを置けるといいのですが。
D3DXSaveSurfaceToFileInMemory以外だと助かります。

595 :デフォルトの名無しさん [sage] :2005/10/20(木) 09:06:18
555だけど、まさかあれが荒れる原因になるとは…すまんな

>>589
バックバッファ作成時にD3DPRESENTFLAG_LOCKABLE_BACKBUFFERを指定しておけば、
オフスクリーンメモリ参照し放題だよ。

パフォーマンスの低下が気になるなら、スクリーンショットを取るときだけ仕立て直すか
レンダリングターゲットを変えて強引にいじれるメモリ上へ持ってきてもいいかもね。

597 :デフォルトの名無しさん [] :2005/10/20(木) 15:34:10
>>589
そういう場合はIDirect3DDevice9::GetRenderTargetDataを使う。
#########################
Win32API質問箱 Build36
http://pc8.2ch.net/test/read.cgi/tech/1128951330/

251 :デフォルトの名無しさん [sage] :2005/10/20(木) 14:09:12
マウスカーソルの周辺部分を、拡大して表示するプログラムを作ってみたいと思うのですが、
どういう方法が一番高速なのでしょうか?

あと、マウスカーソル部分一点のRGB値を表示するようなプログラムだったら、
単純にGetPixel()でも問題ないのでしょうか?

252 :251 [sage] :2005/10/20(木) 14:12:39
方法とは、マウスカーソル周辺部分を取得する方法です。

253 :デフォルトの名無しさん [sage] :2005/10/20(木) 14:16:22
>一番高速

あえて回答もらうの否定してるんだろうか

254 :デフォルトの名無しさん [sage] :2005/10/20(木) 14:16:29
>>252
GetDC(NULL) した DC (←画面を参照できる) から、StretchBlt するとイイヨ。

255 :デフォルトの名無しさん [sage] :2005/10/20(木) 15:45:52
座標がわかるんだから、それを元にしてやればいいんじゃないのか。
そんなん高速だなんだってレベルなのか?

…釣りか。