访问着色器中的索引缓冲区(Directx 11)

时间:2021-04-07 08:01:20

标签: c++ shader directx-11 hlsl

我有一个顶点和索引缓冲区,我正在将网格渲染为一个像素,我想知道网格的哪个三角形被渲染并访问其在 cpu 上的索引缓冲区中的索引以进行进一步处理(仅基于我的网格一个三角形可以渲染到那个像素)。

我首先使用 SV_PrimitiveId 实现它,我希望它会为索引缓冲区的前三个索引(第一个三角形)生成 0,并为后三个索引生成 1,依此类推。这样我就可以从 gpu 复制数据并读取该 id并找到三角形,但问题是 id 与我的索引缓冲区不对应(即。当我运行程序时,它给出了例如第三个三角形 id 7,其他时间为 10 等等)。

我想知道无论如何确定哪个三角形是像素着色器绘制的并在索引缓冲区中找到它的索引以在cpu上找到它?

1 个答案:

答案 0 :(得分:0)

这应该有效:

C++:

    ...
    Microsoft::WRL::ComPtr<ID3D11Texture2D>           pPrimitiveIDs;
    Microsoft::WRL::ComPtr<ID3D11RenderTargetView>    pPIDsRTV;
    Microsoft::WRL::ComPtr<ID3D11Texture2D>           pPIDsStaging;
    ...
    const int number_of_rtvs = 2;
    ID3D11RenderTargetView* rtvs[number_of_rtvs] =
    {
        pScreenRTV.Get(),
        pPIDsRTV.Get(),
    };
    pDeviceContext->OMSetRenderTargets(number_of_rtvs, rtvs, pDepthStencilView.Get());
    ...
    pDeviceContext->CopyResource(pPIDStaging.Get(), pPrimitiveIDs.Get());
    D3D11_MAPPED_SUBRESOURCE MappedResource;
    pDeviceContext->Map(pPIDStaging.Get(), 0, D3D11_MAP_READ, 0, &MappedResource);
    // here is the pid
    // in case of a 1x1 back buffer you would just read the first value
    UINT pid = *((UINT*)MappedResource.pData + MouseX + WindowWidth * MouseY);
    pDeviceContext->Unmap(pPIDStaging.Get(), 0);
    ...

像素着色器:

struct PSOutput
{
    float4 color : SV_Target0;
    uint pid : SV_Target1;
};

PSOutput main(..., uint pid : SV_PrimitiveId)
{
    ...
    PSOutput output =
    {
        color,
        pid,
    };
    return output;
}