如何绝对保证Direct3D9 hook overlay rendering on top

How to absolutely ensure Direct3D9 hook overlay rendering on top

我正在尝试挂钩 IDirect3DDevice9::Present::EndScene 并在 D3D9 应用程序的所有其他内容之上呈现我自己的叠加层(目前,它只是一个简单的矩形),但是我的叠加层似乎随机出现和消失。我目前使用的绘图代码是:

typedef struct CUSTOMVERTEX {
    float x, y, z, rwh;
    DWORD color;
};

#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

void draw() {
    // the positions are just for testing purposes, so they don't really make sense
    CUSTOMVERTEX vertices[] = {
        { 0, 0, 0, 1.0f, D3DCOLOR_XRGB(255, 255, 255) },
        { 0, cursor_pos.y+500, 0, 1.0f, D3DCOLOR_XRGB(127, 255, 255) },
        { cursor_pos.x, cursor_pos.y, 0, 1.0f, D3DCOLOR_XRGB(255,255, 255) },
        { cursor_pos.x, 600, 0, 1.0f, D3DCOLOR_XRGB(127, 0, 0) }
    };

    if (vBuffer == 0) return;

    VOID* pVoid; 

    vBuffer->Lock(0, 0, &pVoid, 0); 
    memcpy(pVoid, vertices, sizeof(vertices));    
    vBuffer->Unlock(); 

    d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

    D3DMATRIX orthographicMatrix;
    D3DMATRIX identityMatrix;

    // MAKE_D3DMATRIX should be equivalent to D3DXMATRIX constructor
    D3DMATRIX viewMatrix = MAKE_D3DMATRIX( 
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, 0,
        ((float)-(get_window_width()/2)), ((float)-(get_window_height()/ 2)), 0, 1
    );
    // MAKE_ORTHO_LH is equivalent to D3DMatrixOrthoLH
    MAKE_ORTHO_LH(&orthographicMatrix, (FLOAT)get_window_width(), (FLOAT)get_window_height(), -1.0, 1.0); 

    // and this to D3DMatrixIdentity
    MAKE_IDENTITY(&identityMatrix); // and this to D3DMatrixIdentity

    d3dDevice->SetTransform(D3DTS_PROJECTION, &orthographicMatrix);
    d3dDevice->SetTransform(D3DTS_WORLD, &identityMatrix);
    d3dDevice->SetTransform(D3DTS_VIEW, &viewMatrix);

    d3dDevice->SetRenderState(D3DRS_ZENABLE, false);
    d3dDevice->SetFVF(CUSTOMFVF);
    d3dDevice->SetStreamSource(0, vBuffer, 0, sizeof(CUSTOMVERTEX));
    d3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
    d3dDevice->SetRenderState(D3DRS_ZENABLE, true);
}

我似乎无法弄清楚为什么这会导致叠加层在看似随机的时间点突然出现和消失。我错过了什么?

我找到了一个万无一失的方法来将我的东西直接渲染到后台缓冲区(在 CPU 上):

IDirect3DSwapChain9 *sc;
if (FAILED(d3dDevice->GetSwapChain(0, &sc))) {
    PRINT("GetSwapChain failed\n");
    return;
}

IDirect3DSurface9 *s;
if (FAILED(sc->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &s))) {
    PRINT("GetBackBuffer failed\n");
    return;
}

D3DLOCKED_RECT r;
if (FAILED(s->LockRect(&r, NULL, D3DLOCK_DONOTWAIT))) {
    PRINT("LockRect failed\n");
    return;
}

// here, find out pixel format and manipulate 
// pixel buffer through r->pBits, using r->Pitch accordingly

s->UnlockRect();

s->Release();
sc->Release();

很可能会导致性能下降,但在我的应用程序中这并没有真正产生影响。更好的方法是利用 GPU 的 hwacceled 渲染功能,但我目前缺乏这样做的 D3D 知识。