5

DirectXでスクリーンショットを撮る方法を聞いたところ、「GetFrontBufferData()を使う」との回答でした。ただし、「この関数は設計上非常に低速であり、パフォーマンスが重要なパスでは使用しないでください」とMSDNで説明されていました。

他の方に対策を聞いたところ「バックバッファのデータをシステムメモリに転送する」との回答でした。しかし、具体的な方法を見つけることができませんでした。

これは失敗例です。正しいコードを教えてください。

#include <stdio.h>
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9tex.h>

void main()
{
    CoInitialize(NULL);

    HWND hwnd = GetDesktopWindow();

    LPDIRECT3D9 d3d9;
    D3DDISPLAYMODE ddm;

    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    d3d9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm);

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.BackBufferCount = 1;
    d3dpp.BackBufferWidth = ddm.Width;
    d3dpp.BackBufferHeight = ddm.Height;
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality = 0;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.hDeviceWindow = hwnd;
    d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;

    LPDIRECT3DDEVICE9 dev;
    d3d9->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp, &dev);

    /* Deprecation
    IDirect3DSurface9* surface = NULL;
    dev->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
    dev->GetFrontBufferData(0, surface);
    D3DXSaveSurfaceToFile(L"D:\\test.bmp", D3DXIFF_BMP, surface, NULL, NULL);
    */

    // Transfer the data of a back buffer to the system memory
    IDirect3DSurface9* surface = NULL;
    dev->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
    LPDIRECT3DSURFACE9 back = NULL;
    dev->SetRenderTarget(0, surface);
    dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back);
    dev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,127), 1.0, 0 );
    dev->BeginScene();
    dev->StretchRect(surface, NULL, back, NULL, D3DTEXF_NONE);
    dev->EndScene();
    dev->Present(0,0,0,0);
    D3DXSaveSurfaceToFile(L"D:\\test.bmp", D3DXIFF_BMP, back, NULL, NULL);


    if(back) back->Release();

    dev->Release();
    d3d9->Release();

    CoUninitialize();
}
4

1 に答える 1

3

バック バッファからデータを取得することはできません。関数 GetBackBuffer は、バック バッファ内のデータではなく、バック バッファのポインタのみを取得します。

  • フロントバッファ。グラフィックス アダプタによって変換され、モニタに表示されるメモリの四角形。Direct3D では、アプリケーションがフロント バッファーに直接書き込むことはありません。
  • バックバッファ。アプリケーションが直接書き込むことができるメモリの四角形。バック バッファーがモニターに直接表示されることはありません。

これは、デスクトップに表示されたものがフロント バッファーに存在することを意味します。

于 2012-10-14T07:53:17.220 に答える