首页 > 解决方案 > 在 DirectX 11 中高效捕获帧

问题描述

我试图捕捉我正在玩的游戏的每一帧。市面上有很多优秀的屏幕捕捉软件,其中一个内置于 Windows 10 中。

但是,出于不同的原因,我需要一种自定义方法。我目前正在使用 DirectX Tool KitsSaveWICTextureToFile()方法来保存 Present() 生成的每一帧。

https://github.com/microsoft/DirectXTK

对于捕获的每一帧,我想用它的适用编号标记文件名的末尾。ScreenShot_0通过ScreenShot_n.

该方法SaveWICTextureToFile()为您保存屏幕截图,如下所示:

DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, L"C:/Users/User Name/Desktop/Images/ScreenShot.JPG");

这不允许您按顺序捕获帧。它只是为每一帧重写同一个文件。不过表演非常流畅。在游戏过程中没有任何滞后。

为了尝试为每一帧编写一个文件,我执行了以下操作:

#include <sstream>
int Frame_Number;

//For each Call to Present() do the following:

//Get Device
ID3D11Device* device;
HRESULT gd = pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&device);
assert(gd == S_OK);

//Get context
ID3D11DeviceContext* context;
device->GetImmediateContext(&context);

//get back buffer
ID3D11Texture2D* backbufferTex;
HRESULT gb = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2d), (LPVOID*)&backbufferTex);
assert(gb == S_OK);

//Set-up Directory
std::wstringstream Image_Directory;
Image_Directory << L"C:/Users/User Name/Desktop/Images/ScreenShot_" << Frame_Number << L".JPG";

//Capture Frame
REFGUID GUID_ContainerFormatJpeg{ 0x19e4a5aa, 0x5662, 0x4fc5, 0xa0, 0xc0, 0x17, 0x58, 0x2, 0x8e, 0x10, 0x57 };
HRESULT hr = DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, Image_Directory.str().c_str());
assert(hr == S_OK);
Frame_Number = Frame_Number + 1;

这行得通,但是性能不稳定。与以前的方法相比,我不再获得流畅的游戏玩法。有人可以推荐一种更有效的方法吗?

标签: c++directx-11

解决方案


如果这是在调试版本中完成的,我怀疑 stringstream 的逻辑会导致问题,我建议使用字符数组和 swprintf。如果您跟踪目录的结束位置,那么只需要写出文件名部分就更好了(您可以更进一步,只需要格式化数字和扩展名)。


推荐阅读