// ★事前準備。
// デフォルトレンダリングターゲットのSurfaceを取得
Surface s = device.GetRenderTarget(0);
SurfaceDescription sd = s.Description;
// 保存用のSurfaceと、コピー領域指定用用のRectangleを生成。
Surface saveSurface = Surface.CreateOffscreenPlain(device, sd.Width, sd.Height, sd.Format, Pool.SystemMemory);
Rectangle rect = Rectangle(0, 0, sd.Width, sd.Height);
// ★保存処理実施
device.GetRenderTargetData(s, saveSurface);
DataRectangle dr = _SaveView.LockRectangle(LockFlags.ReadOnly);
byte[] buf = new byte[dr.Pitch * Height];
// DirectXのバックバッファから一時バッファへコピー(1)
Marshal.Copy(dr.DataPointer, buf, 0, buf.Length);
_SaveView.UnlockRectangle();
try {
using(Bitmap bmp = new Bitmap(Width, Height, PixelFormat.Format32bppArgb)){
// 一時バッファからBitmapのデータ領域へコピー(2)
BitmapData bd = _SaveBmp.LockBits(_SaveRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(buf, 0, bd.Scan0, buf.Length);
bmp.UnlockBits(bd);
// BitmapをJPEGで保存
bmp.Save(path, ImageFormat.Jpeg);
}
}
catch(Exception ex) {
// エラーログ出すとか
}
(1)と(2)の処理を一度でできるといいけど、
Marshal.Copyでsrc、dstともIntPtrで指定できるやつを見つけられていない・・・
なにかしら他の方法で一発で行けるかな・・・?
なににせよ、とりあえずスクリーンショットはとれるようになったし、毎フレーム実施するわけでもないので、若干重くなってもいいや、という感じでとりあえずはこれでOKとしておく・・・。
タグ:DirectX