如何使用DX11截取屏幕截图?

时间:2018-06-14 05:28:14

标签: c++ directx directx-11

我正在为DX11游戏编写插件,我需要截取屏幕截图并将其保存到文件中。我找到了一些使用函数D3DX11SaveTextureToFile的代码片段,但我无法让它工作。这是我到目前为止所做的:(为简单起见,错误检查和不相关的代码被删除)

void screenshot(IDXGISwapChain *pSwapChain)
{
    ID3D11Device *pDevice;
    pSwapChain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast<void **>(&pDevice));

    ID3D11DeviceContext *pContext;
    pDevice->GetImmediateContext(&pContext);

    ID3D11Texture2D *pBackBuffer;
    pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&pBackBuffer));

    D3D11_TEXTURE2D_DESC txtDesc;
    pBackBuffer->GetDesc(&txtDesc);
    txtDesc.Usage = D3D11_USAGE_STAGING;
    txtDesc.BindFlags = 0;
    txtDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    // txtDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM

    ID3D11Texture2D *pBackBufferStaging;
    pDevice->CreateTexture2D(&txtDesc, nullptr, &pBackBufferStaging);
    pContext->CopyResource(pBackBufferStaging, pBackBuffer);

    HRESULT hr = D3DX11SaveTextureToFileA(pContext, pBackBufferStaging, D3DX11_IFF_PNG, "E:\\screenshot.png");
    // hr == E_FAIL

    pBackBufferStaging->Release();
    pBackBuffer->Release();
}

我遇到了E_FAIL错误,经过一些研究后,D3DX11SaveTextureToFile似乎不支持我假设的游戏使用的纹理格式DXGI_FORMAT_B8G8R8A8_UNORM。如果我手动将格式设置为类似DXGI_FORMAT_R8G8B8A8_UNORM的函数,则函数将成功,但我将获得黑色图像。我认为CopyResource要求源和目标具有相同的格式。

我知道有DirectXTK库,但我坚持使用VS2013,如果我正确读取它的自述文件,DirectXTK似乎不支持它。

修改
DirectXTK / DirectXTex完美运行。

1 个答案:

答案 0 :(得分:1)

使用 DirectX工具包中的ScreenGrab模块是您最好的选择。它可以写出DDS文件或WIC支持的各种格式,包括JPG

using namespace DirectX;
using namespace Microsoft::WRL;

ComPtr<ID3D11Texture2D> backBuffer;
HRESULT hr = swapChain->GetBuffer( 0,
    __uuidof( ID3D11Texture2D ),
   reinterpret_cast<LPVOID*>( backBuffer.GetAddressOf() ) );
if ( SUCCEEDED(hr) )
{
    hr = SaveWICTextureToFile( immContext.Get(), backBuffer.Get(),
                GUID_ContainerFormatJpeg, L"SCREENSHOT.JPG" );
}
DX::ThrowIfFailed(hr);

我最近从我的GitHub项目中删除了对Visual Studio 2013的支持 - 有关详细信息,请参阅this blog post。如果您无法升级,则可以使用稍早于2018年4月release的版本,该版本支持VS 2013.

  

D3DX9,D3DX10和D3DX11通常每{... 3}}都与DirectX SDK一起弃用。