【问题标题】:DX9/10/11 Sceen Capture C#DX9/10/11 屏幕截图 C#
【发布时间】:2012-05-05 06:51:41
【问题描述】:

我正在阅读此文: http://www.ring3circus.com/gameprogramming/case-study-fraps/ 而且我开始意识到,考虑到它的年代久远,(作者甚至建议不要使用他的代码),这确实不适合我的需求(一,它是 C#,二,它用于 DX9)。我正在尝试获取 DirectX 游戏窗口的矩形捕获,并将其作为某种可以引用的流视频保存在内存中。如果不在前景中,甚至可见(隐藏在其他窗口后面),该窗口仍需要能够被捕获。我已经尝试过那个 C# 库(使用 EasyHook 和 SlimDX 制作的库),但我只设法让演示在 64 位下的 DirectX 11 游戏中成功运行一次(此后一直无法重现它)。即便如此,捕捉速度也慢得令人瞠目结舌。以及许多其他覆盖到 DirectX 的内容(我不需要)。我想模仿 fraps 在捕获方面的作用,但我只需要游戏的一个矩形区域,而不是整个区域,而且我不需要将其写入文件。我能否获得一个代码示例,说明我如何设法在 C# 中快速捕获游戏窗口的给定矩形,这适用于 DX9 到 DX11?

【问题讨论】:

  • 这是个好问题。似乎在网上找不到容易找到的答案 - 隐藏在许多 DX9 和其他不相关的解决方案之下。

标签: c# directx hook code-injection screen-capture


【解决方案1】:

这是我针对相同问题的 C++ 代码。

ID3D11Texture2D* pSurface;
HRESULT hr = m_swapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pSurface ) );
if( pSurface )
{
    const int width = static_cast<int>(m_window->Bounds.Width * m_dpi / 96.0f);
    const int height = static_cast<int>(m_window->Bounds.Height * m_dpi / 96.0f);
    unsigned int size = width * height;
    if( m_captureData )
    {
        freeFramebufferData( m_captureData );
    }
    m_captureData = new unsigned char[ width * height * 4 ];

    ID3D11Texture2D* pNewTexture = NULL;

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

    HRESULT hr = m_d3dDevice->CreateTexture2D( &description, NULL, &pNewTexture );
    if( pNewTexture )
    {
        m_d3dContext->CopyResource( pNewTexture, pSurface );
        D3D11_MAPPED_SUBRESOURCE resource;
        unsigned int subresource = D3D11CalcSubresource( 0, 0, 0 );
        HRESULT hr = m_d3dContext->Map( pNewTexture, subresource, D3D11_MAP_READ_WRITE, 0, &resource );
        //resource.pData; // TEXTURE DATA IS HERE

        const int pitch = width << 2;
        const unsigned char* source = static_cast< const unsigned char* >( resource.pData );
        unsigned char* dest = m_captureData;
        for( int i = 0; i < height; ++i )
        {
            memcpy( dest, source, width * 4 );
            source += pitch;
            dest += pitch;
        }

        m_captureSize = size;
        m_captureWidth = width;
        m_captureHeight = height;

        return;
    }

    freeFramebufferData( m_captureData );
}

您/可能/能够将其移植到 C#,或者至少将其包装在库中。我问了一个类似的问题,但后来找到了答案:DirectX 11 framebuffer capture (C++, no Win32 or D3DX)

【讨论】:

  • 请问您如何初始化交换链?您可以使用此代码为其他应用程序抓取屏幕吗?
  • 很好的起点,真的帮我找到了正确的方向。
猜你喜欢
  • 2021-03-20
  • 2011-03-28
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多