Why do DirectX fullscreen applications give black screenshots?

前端 未结 2 1142
臣服心动
臣服心动 2021-01-21 22:23

You may know that trying to capture DirectX fullscreen applications the GDI way (using BitBlt()) gives a black screenshot.

My question is r

2条回答
  •  庸人自扰
    2021-01-21 22:48

    I believe it is actually due to double buffering. I'm not 100% sure but that was actually the case when I tested screenshots in OpenGL. I would notice that the DC on my window was not the same. It was using two different DC's for this one game.. For other games I wasn't sure what it was doing. The DC was the same but swapbuffers was called so many times that I don't think GDI was even fast enough to screenshot it.. Sometimes I would get half a screenshot and half black..

    However, when I hooked into the client, I was able to just ask for the pixels like normal. No GDI or anything. I think there is a reason why we don't use GDI when drawing in games that use DirectX or OpenGL..

    You can always look at ways to capture the screen here:http://www.codeproject.com/Articles/5051/Various-methods-for-capturing-the-screen

    Anyway, I use the following for grabbing data from DirectX:

    HRESULT DXI_Capture(IDirect3DDevice9* Device, const char* FilePath)
    {
        IDirect3DSurface9* RenderTarget = nullptr;
        HRESULT result = Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &RenderTarget);
        result = D3DXSaveSurfaceToFile(FilePath, D3DXIFF_PNG, RenderTarget, nullptr, nullptr);
        SafeRelease(RenderTarget);
        return result;
    }
    

    Then in my hooked Endscene I call it like so:

    HRESULT Direct3DDevice9Proxy::EndScene()
    {
        DXI_Capture(ptr_Direct3DDevice9, "C:/Ssers/School/Desktop/Screenshot.png");
    
        return ptr_Direct3DDevice9->EndScene();
    }
    

    You can either use microsoft detours for hooking EndScene of some external application or you can use a wrapper .dll.

提交回复
热议问题