c++ - 如何使用 DX11 截屏?
问题描述
我正在为 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 工作完美。
解决方案
使用DirectX Tool Kit中的ScreenGrab模块是您最好的选择。它可以编写WIC 支持的文件或各种格式,包括:DDS
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 的支持——有关详细信息,请参阅此博客文章。如果您无法升级,您可以使用稍旧的 2018 年 4 月版本,它支持 VS 2013。
D3DX9、D3DX10 和 D3DX11 通常与 DirectX SDK 一起根据MSDN被弃用。
推荐阅读
- node.js - 从 oracle db 获取数据并使用 app.get 在浏览器上显示
- http - 如何在静态站点上伪造 http 请求?
- simd - 在列主矩阵上使用 AVX512 _mm512_loadu_pd()?
- javascript - 加载音频有效,但现在无效
- c++ - 当我有两个指针在同一个内存时,为什么我必须调用两次“删除”?
- java - 在房间版本 1.1.1 中创建复合主键时无法使用 Kotlin 编译器构建 android studio 项目
- javascript - 在没有只读错误的情况下无法访问深层嵌套对象属性
- python - 如何在 python 中使用 requests.get 获取数据之前等待页面加载,而不使用 api
- java - Repaint() 方法不会一一调用paint() 和paintComponent() 方法,只有paintComponent() 方法有效
- unity3d - 你可以在 Unity 中导出切片精灵(PNG 图像)吗?