在不破坏现有内容的情况下绘制 Present() 钩子

Draw in Present() hook without destroying existing content

我正在为 DX11 全屏应用程序编写通用覆盖应用程序(不是作弊)。
我是 DX11 的新手,由于项目的时间压力,我试图快速赶上进度。希望得到您的帮助。

我正在注入一个 dll 并挂接 DX11 Present(),它似乎工作得很好。
使用 Present() 中的交换链,我可以获得 Window 处理程序、设备和上下文。

我缺乏很多理解,试图通过现有的代码、教程和文档来爬行。 我目前的做法是演示"overlay",我想画一个三角形并将其覆盖在现有场景上。
现在我似乎擦除所有现有的东西而不是覆盖。

我的第一个目标是覆盖一个简单的矩形框并在其上添加现有图像作为纹理。非常感谢有关该目标的任何帮助。

这是我在 Present() 挂钩中调用的当前演示覆盖函数。 DX11 对象是一个包含我从 Present() 交换链(游戏交换链)收集的东西的结构。

void draw_simple_test()
{
    ID3D11InputLayout*          g_pInputLayout = NULL;
    ID3D11Buffer*               g_pVertexBuffer = NULL;
    ID3D11RenderTargetView*     g_pRenderTargetView = NULL;
    ID3D11VertexShader*         g_pVertexShader = NULL;
    ID3D11PixelShader*          g_pPixelShader = NULL;
    HRESULT hr = S_OK;
    CHAR* g_strVS =
        "void VS( in float4 posIn : POSITION,\n"
        "         out float4 posOut : SV_Position )\n"
        "{\n"
        "    // Output the vertex position, unchanged\n"
        "    posOut = posIn;\n"
        "}\n";

    CHAR* g_strPS =
        "void PS( out float4 colorOut : SV_Target )\n"
        "{\n"
        "    // Make each pixel yellow, with alpha = 1\n"
        "    colorOut = float4( 1.0f, 1.0f, 1.0f, 1.0f );\n"
        "}\n";


    // Create the render target view
    ID3D11Texture2D* pRenderTargetTexture;
    hr = DX11.SwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pRenderTargetTexture);
    if (FAILED(hr))
        return; //hr

    hr = DX11.Device->CreateRenderTargetView(pRenderTargetTexture, NULL, &g_pRenderTargetView);
    pRenderTargetTexture->Release();


    float ClearColor[4] = { 1.0f, 0.125f, 0.3f, 1.0f }; // red, green, blue, alpha
    //DX11.BackBufferRT
    //DX11.Context->ClearRenderTargetView(g_pRenderTargetView, ClearColor); // clear whole view to color

    DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
    ID3D10Blob* pBlobVS = NULL;
    ID3D10Blob* pBlobError = NULL;
    hr = D3DCompile(g_strVS, lstrlenA(g_strVS) + 1, "VS", NULL, NULL, "VS",
        "vs_4_0", dwShaderFlags, 0, &pBlobVS, &pBlobError);
    if (FAILED(hr))
    {
        if (pBlobError != NULL)
        {
            OutputDebugStringA((CHAR*)pBlobError->GetBufferPointer());
            pBlobError->Release();
        }
        return ;//hr
    }
    hr = DX11.Device->CreateVertexShader(pBlobVS->GetBufferPointer(), pBlobVS->GetBufferSize(),
        NULL, &g_pVertexShader);
    if (FAILED(hr))
        return ; //hr

    // Compile and create the pixel shader
    ID3D10Blob* pBlobPS = NULL;
    hr = D3DCompile(g_strPS, lstrlenA(g_strPS) + 1, "PS", NULL, NULL, "PS",
        "ps_4_0", dwShaderFlags, 0, &pBlobPS, &pBlobError);
    if (FAILED(hr))
    {
        if (pBlobError != NULL)
        {
            OutputDebugStringA((CHAR*)pBlobError->GetBufferPointer());
            pBlobError->Release();
        }
        return; //hr
    }
    hr = DX11.Device->CreatePixelShader(pBlobPS->GetBufferPointer(), pBlobPS->GetBufferSize(),
        NULL, &g_pPixelShader);
    if (FAILED(hr))
        return ;//hr
    pBlobPS->Release();


    // Create the input layout
    D3D11_INPUT_ELEMENT_DESC elements[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = _countof(elements);

    hr = DX11.Device->CreateInputLayout(elements, numElements, pBlobVS->GetBufferPointer(),
        pBlobVS->GetBufferSize(), &g_pInputLayout);
    if (FAILED(hr))
        return ;

    pBlobVS->Release();


    SimpleVertex vertices[] =
    {
        0.0f, 0.2f, 0.2f, // top
        0.5f, -0.5f, 0.5f, // left
        -0.5f, -0.5f, 0.5f, // right
    };
    D3D11_BUFFER_DESC bd;
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof(vertices);
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;
    bd.StructureByteStride = 0;
    D3D11_SUBRESOURCE_DATA initData;
    initData.pSysMem = vertices;
    hr = DX11.Device->CreateBuffer(&bd, &initData, &g_pVertexBuffer);
    if (FAILED(hr))
        return ;//hr



    // ---
    // zuweisen
    DX11.Context->IASetInputLayout(g_pInputLayout);

    UINT stride = sizeof(SimpleVertex);
    UINT offset = 0;
    DX11.Context->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);

    DX11.Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    DX11.Context->VSSetShader(g_pVertexShader, NULL, 0);

    DX11.Context->PSSetShader(g_pPixelShader, NULL, 0);

    RECT rc;
    GetClientRect(DX11.Window, &rc);
    D3D11_VIEWPORT vp;
    vp.Width = (FLOAT)(rc.right - rc.left);
    vp.Height = (FLOAT)(rc.bottom - rc.top);
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    DX11.Context->RSSetViewports(1, &vp);

    DX11.Context->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);


    DX11.Context->Draw(3, 0); //3 vertices start at 0
    //cleanup
    }

我做错了什么? 考虑到我在游戏已经准备好一切后注入此功能,我想我犯了不止一个错误。
我应该使用游戏中的交换链吗?创建自己的第二个?
我有点(很多)迷路了。

解决了,花了我不少时间,但问题确实是缓冲区损坏了。 很明显,我想我之前看不到,因为所有新的 DX 东西都让我不知所措。

这是为我做的(应该会持续一段时间): 为了尽量减少影响,您只能采用您在自己的绘图代码中实际使用的那些功能。

m_pContext->AddRef();
m_pContext->IAGetPrimitiveTopology(&m_primitiveTopology);
m_pContext->IAGetInputLayout(&m_pInputLayout);
m_pContext->OMGetBlendState(&m_pBlendState, m_blendFactor, &m_sampleMask);
m_pContext->OMGetDepthStencilState(&m_pDepthStencilState, &m_stencilRef);

m_pContext->RSGetState(&m_pRasterizerState);

m_pContext->VSGetShader(&m_pVS, 256, &m_numVSClassInstances);
m_pContext->VSGetConstantBuffers(0, 4, m_pVSConstantBuffer);

m_pContext->PSGetShader(&m_pPS, 256, &m_numPSClassInstances);
m_pContext->PSGetShaderResources(0, 9, m_pPSSRV);
pContext->PSGetSamplers(0, 10, m_pSamplerState);
m_pContext->PSGetConstantBuffers(0, 3, m_ppConstantBuffers);
m_pContext->OMGetRenderTargetsAndUnorderedAccessViews(2, m_RTView, &m_DepthView, 0, 0, NULL);
m_pContext->RSGetViewports(&m_numViewports, m_RSViewports);
m_pContext->GSGetShader(&m_pGS, 256, &m_numGSClassInstances);
m_pContext->GSGetConstantBuffers(0, 2, m_pGSConstantBuffer);

m_pContext->GSGetShaderResources(0, 1, &m_pGSSRV);

m_pContext->HSGetShader(&m_pHS, 256, &m_numHSClassInstances);

m_pContext->DSGetShader(&m_pDS, 256, &m_numDSClassInstances);
m_pContext->DSGetSamplers(0, 3, m_dSSamplers);

m_pContext->IAGetVertexBuffers(0, 3, m_pVB, m_vertexStride, m_vertexOffset);
m_pContext->IAGetIndexBuffer(&m_pIndexBuffer, &m_indexFormat, &m_indexOffset);

需要在 "release" 上调用 'set' 函数来恢复缓冲区。 选择你实际使用的函数,简单的例子5-6行代码。