Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ c++;Directx11捕获屏幕并保存到文件_C++_Save_Screenshot_Directx 11_Texture2d - Fatal编程技术网

C++ c++;Directx11捕获屏幕并保存到文件

C++ c++;Directx11捕获屏幕并保存到文件,c++,save,screenshot,directx-11,texture2d,C++,Save,Screenshot,Directx 11,Texture2d,我在将texture2d保存到文件时遇到问题,它总是给我黑色图像。 以下是代码: HRESULT hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &g_pSurface ) ); if( g_pSurface ) { ID3D11Texture2D* pNewTexture = NULL; D3D11_TEXTURE2D_DES

我在将texture2d保存到文件时遇到问题,它总是给我黑色图像。 以下是代码:

HRESULT hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &g_pSurface ) );
if( g_pSurface )
{
    ID3D11Texture2D* pNewTexture = NULL;

    D3D11_TEXTURE2D_DESC description;
    g_pSurface->GetDesc( &description );
    description.BindFlags = 0;
    description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
    description.Usage = D3D11_USAGE_STAGING;

    HRESULT hr = d3d11Device->CreateTexture2D( &description, NULL, &pNewTexture );
    if( pNewTexture )
    {
        d3d11DevCon->CopyResource( pNewTexture, g_pSurface );

        hr=D3DX11SaveTextureToFileA(d3d11DevCon, pNewTexture, D3DX11_IFF_BMP, "screen.bmp");
        return;
    }
}
HRESULT hr=SwapChain->GetBuffer(0,u-uuidof(ID3D11Texture2D),重新解释强制转换(&g_-pSurface));
if(g_pSurface)
{
ID3D11Texture2D*pNewTexture=NULL;
D3D11_纹理2D_描述;
g_pSurface->GetDesc(&description);
description.BindFlags=0;
description.CPUAccessFlags=D3D11_CPU_访问_读取| D3D11_CPU_访问_写入;
description.Usage=D3D11\u Usage\u STAGING;
HRESULT hr=d3d11设备->创建纹理2d(&description,NULL,&pNewTexture);
if(pNewTexture)
{
d3d11DevCon->CopyResource(pNewTexture,g_pSurface);
hr=D3DX11SaveTextureToFileA(d3d11DevCon,pNewTexture,D3DX11_IFF_BMP,“screen.BMP”);
返回;
}
}

我做错了什么?

在设置所有值之前,您的描述已声明,但未初始化为任何内容。它的
miscsflags
成员中可能有垃圾,这会破坏你的创作。尝试设置
description.miscsflags=0或先将整个描述归零。如果这还不行,下面是我当前的一个库中的一个精简代码示例:

试试这个:

HRESULT hr;

ID3D11Resource* pSurface = nullptr;
m_pRenderTargetView->GetResource(&pSurface);

if (pSurface)
{
    D3D11_TEXTURE2D_DESC desc;
    ZeroMemory(&desc, sizeof(desc));
    desc.ArraySize = 1;
    desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    desc.Width = clientWidth;
    desc.Height = clientHeight;
    desc.MipLevels = 1;
    desc.SampleDesc.Count = 1;
    desc.SampleDesc.Quality = 0;
    desc.BindFlags = 0;
    desc.CPUAccessFlags = 0;
    desc.Usage = D3D11_USAGE_DEFAULT;

    ID3D11Texture2D* pTexture = nullptr;
    hr = m_pDevice->CreateTexture2D(&desc, nullptr, &pTexture);
    if (pTexture)
    {
        m_pContext->CopyResource(pTexture, pSurface);
        hr = D3DX11SaveTextureToFileA(m_pContext, pTexture, D3DX11_IFF_PNG, "ss.png");
        pTexture->Release();
    }
    pSurface->Release();
}

首先,需要显式检查返回HRESULT的所有函数的返回代码

HRESULT hr = SwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ),
    reinterpret_cast< void** >( &g_pSurface ) );
if( SUCCEEDED(hr) )
{
...
    HRESULT hr = d3d11Device->CreateTexture2D( &description, NULL, &pNewTexture );
    if( SUCCEEDED(hr) )
事实上,您应该使用DirectX工具包,而不是传统的
D3DX11
库。所有版本的D3DX都不推荐使用,旧版DirectX SDK本身也不推荐使用(请参阅)。有许多容易获得的方法

除了MSAA问题外,您可能会遇到
D3DX11
选择WIC格式的问题。根据渲染目标格式和渲染,它可能会使用all 0 alpha通道写入图像,这可能会导致“空白”输出图像。DirectX工具包屏幕抓图模块使您能够显式指定输出格式,并默认尝试使用非alpha输出文件格式

不使用旧式
D3DX11
的另一个原因是:它从未针对DXGI 1.1格式进行过更新,因此它不支持写出BGRA格式资源,例如
DXGI\u格式B8G8R8A8\u UNORM
DXGI\u格式B8G8R8A8\u UNORM
,即使底层WIC容器文件格式支持它们。如果上面代码中的渲染目标是
DXGI_格式\u B8G8R8A8_UNORM
而不是
DXGI_格式\u r8g8a8_UNORM
,则
D3DX11
将失败,而屏幕抓取将正常工作

我有没有提到
D3DX11
太旧了,从2009年起就没有进行过任何修复

下面是屏幕抓图的一些用法示例:

ComPtr backBufferTex;
hr=swapChain->GetBuffer(0,u uuidof(ID3D11Texture2D),(LPVOID*)和backBufferTex);
如果(成功(hr))
{
//将渲染目标写出为PNG
hr=SaveWICTextureToFile(context.Get(),backBufferTex.Get(),GUID_ContainerFormatPng,L“SCREENSHOT.PNG”);
//将渲染目标写为JPG
hr=SaveWICTextureToFile(context.Get(),backuffertex.Get(),GUID_ContainerFormatJpeg,L“SCREENSHOT.JPG”);
//将渲染目标写出为BMP
hr=SaveWICTextureToFile(context.Get(),backBufferTex.Get(),GUID_ContainerFormatBmp,L“SCREENSHOT.BMP”);
//将渲染目标写出为BMP,并显式使用16位格式
hr=SaveWICTextureToFile(context.Get()、backBufferTex.Get()、GUID\u containerformattbmp、L“SCREENSHOT.BMP”、&GUID\u WICPixelFormat16bppBGR565);
//以TIF格式写出渲染目标
hr=SaveWICTextureToFile(context.Get(),backBufferTex.Get(),GUID_ContainerFormatTiff,L“SCREENSHOT.TIF”);
//将渲染目标写入具有显式WIC编解码器属性的TIF
hr=SaveWICTextureToFile(context.Get(),backuffertex.Get(),GUID_ContainerFormatTiff,L“SCREENSHOT.TIF”,nullptr,
[&](IPropertyBag2*道具)
{
PROPBAG2选项[2]={0,0};
选项[0]。pstrName=L“压缩质量”;
选项[1]。pstrName=L“TiffCompressionMethod”;
变量变量值[2];
变量值[0]。vt=vt_R4;
varValues[0]。fltVal=0.75f;
varValues[1].vt=vt_UI1;
varValues[1]。bVal=WICTiffCompressionNone;
(作废)道具->写入(2,选项,变量值);
});
//将渲染目标作为DDS写出
hr=saveddsturetofile(context.Get(),backBufferTex.Get(),L“SCREENSHOT.DDS”);
}
要写入MSAA缓冲区(交换链中的后缓冲区),需要使用“ResolveSubresource”而不是“CopyResource”

这是一个简单的代码段:

          D3D11_TEXTURE2D_DESC desc;
          HRESULT hr = S_OK;
          ID3D11Resource* pSurface = nullptr;

          // get pointer to back-texture from the swap chain referred from the pointer IDXGISwapChain* g_pswapChain
          hr=g_pswapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pSurface));
          if (FAILED(hr) || pSurface==nullptr)
          {
             // Throw Error  
      
          }
        
          D3D11_TEXTURE2D_DESC desc;
          ZeroMemory(&desc, sizeof(desc));
          desc.ArraySize = 1;
          desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
          desc.Width = 640; // i specified hard-coded the window size 640x480 in CreateWindowA
           desc.Height = 480;
           desc.MipLevels = 1;
           desc.SampleDesc.Count = 1;
           desc.SampleDesc.Quality = 0;
           desc.BindFlags = 0;
           desc.CPUAccessFlags = 0;  // data directly will be copied from GPU to a file
          desc.Usage = D3D11_USAGE_DEFAULT;

          ID3D11Texture2D* pTexture = nullptr;

          // g_pdevice is pointer to device ID3D11Device
          hr = g_pdevice->CreateTexture2D(&desc, nullptr, &pTexture);
          if (pTexture)
          {
                  // instead of CopyResource(pTexture, pSurface), g_pd3dContext pointer to context ID3D11DeviceContext
                  g_pd3dContext->ResolveSubresource(pTexture, 0, pSurface, 0, DXGI_FORMAT_R8G8B8A8_UNORM);

                  // save rendered image as bmp-file
                  hr = D3DX11SaveTextureToFileA(g_pd3dContext, pTexture, D3DX11_IFF_BMP, "test.bmp");
                  pTexture->Release();
              }
              pSurface->Release();
          
         
D3D11_TEXTURE2D_DESC DESC;
HRESULT hr=S_正常;
ID3D11Resource*pSurface=nullptr;
//从从指针IDXGISwapChain*g_pswapChain引用的交换链获取指向背面纹理的指针
hr=g_pswapChain->GetBuffer(0,_uuidof(ID3D11Texture2D),重新解释强制转换(&pSurface));
如果(失败(hr)| | pSurface==nullptr)
{
//抛出错误
}
D3D11_纹理2 d_描述;
零内存(&desc,sizeof(desc));
desc.ArraySize=1;
描述格式=DXGI_格式_R8G8B8A8_UNORM;
描述宽度=640;//我在CreateWindowA中指定了窗口大小640x480的硬编码
描述高度=480;
desc.MipLevels=1;
desc.SampleDesc.Count=1;
desc.SampleDesc.Quality=0;
desc.BindFlags=0;
desc.CPUAccessFlags=0;//数据将直接从GPU复制到f
ComPtr<ID3D11Texture2D> backBufferTex;
hr = swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&backBufferTex);
if ( SUCCEEDED(hr) )
{
    // Write out the render target as a PNG
    hr = SaveWICTextureToFile( context.Get(), backBufferTex.Get(), GUID_ContainerFormatPng, L"SCREENSHOT.PNG");

    // Write out the render target as JPG
    hr = SaveWICTextureToFile( context.Get(), backBufferTex.Get(), GUID_ContainerFormatJpeg, L"SCREENSHOT.JPG" );

    // Write out the render target as BMP
    hr = SaveWICTextureToFile( context.Get(), backBufferTex.Get(), GUID_ContainerFormatBmp, L"SCREENSHOT.BMP" );

    // Write out the render target as BMP and explicitly use a 16-bit format
    hr = SaveWICTextureToFile( context.Get(), backBufferTex.Get(), GUID_ContainerFormatBmp, L"SCREENSHOT.BMP", &GUID_WICPixelFormat16bppBGR565 );

    // Write out the render target as a TIF
    hr = SaveWICTextureToFile( context.Get(), backBufferTex.Get(), GUID_ContainerFormatTiff, L"SCREENSHOT.TIF" );

    // Write out the render target as a TIF with explicit WIC codec properties
    hr = SaveWICTextureToFile( context.Get(), backBufferTex.Get(), GUID_ContainerFormatTiff, L"SCREENSHOT.TIF", nullptr,
                                [&](IPropertyBag2* props)
                                {
                                    PROPBAG2 options[2] = { 0, 0 };
                                    options[0].pstrName = L"CompressionQuality";
                                    options[1].pstrName = L"TiffCompressionMethod";

                                    VARIANT varValues[2];
                                    varValues[0].vt = VT_R4;
                                    varValues[0].fltVal = 0.75f;

                                    varValues[1].vt = VT_UI1;
                                    varValues[1].bVal = WICTiffCompressionNone;

                                    (void)props->Write( 2, options, varValues ); 
                                });

    // Write out the render target as a DDS
    hr = SaveDDSTextureToFile( context.Get(), backBufferTex.Get(), L"SCREENSHOT.DDS" );
}
          D3D11_TEXTURE2D_DESC desc;
          HRESULT hr = S_OK;
          ID3D11Resource* pSurface = nullptr;

          // get pointer to back-texture from the swap chain referred from the pointer IDXGISwapChain* g_pswapChain
          hr=g_pswapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pSurface));
          if (FAILED(hr) || pSurface==nullptr)
          {
             // Throw Error  
      
          }
        
          D3D11_TEXTURE2D_DESC desc;
          ZeroMemory(&desc, sizeof(desc));
          desc.ArraySize = 1;
          desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
          desc.Width = 640; // i specified hard-coded the window size 640x480 in CreateWindowA
           desc.Height = 480;
           desc.MipLevels = 1;
           desc.SampleDesc.Count = 1;
           desc.SampleDesc.Quality = 0;
           desc.BindFlags = 0;
           desc.CPUAccessFlags = 0;  // data directly will be copied from GPU to a file
          desc.Usage = D3D11_USAGE_DEFAULT;

          ID3D11Texture2D* pTexture = nullptr;

          // g_pdevice is pointer to device ID3D11Device
          hr = g_pdevice->CreateTexture2D(&desc, nullptr, &pTexture);
          if (pTexture)
          {
                  // instead of CopyResource(pTexture, pSurface), g_pd3dContext pointer to context ID3D11DeviceContext
                  g_pd3dContext->ResolveSubresource(pTexture, 0, pSurface, 0, DXGI_FORMAT_R8G8B8A8_UNORM);

                  // save rendered image as bmp-file
                  hr = D3DX11SaveTextureToFileA(g_pd3dContext, pTexture, D3DX11_IFF_BMP, "test.bmp");
                  pTexture->Release();
              }
              pSurface->Release();