【问题标题】:DX11 Losing Instance Buffer DataDX11 丢失实例缓冲区数据
【发布时间】:2015-11-23 04:51:30
【问题描述】:

我有一个函数,它基本上将不同的实例缓冲区创建到一个数组中,供我在DrawIndexedInstanced 调用中使用。

但是当我将顶点缓冲区和实例缓冲区传递给我的着色器时,当着色器开始使用它时,我的实例数据完全丢失了,因此我的所有对象都没有被重新定位,因此都在同一个地方渲染。

我已经看了好几个小时了,实际上找不到任何有用的东西。

创建顶点着色器输入布局:

D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
{
    //Vertex Buffer
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },

    //Instance buffer
    { "INSTANCEPOS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
    { "INSTANCEROT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 12, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
    { "INSTANCESCA", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 24, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
    { "INSTANCETEX", 0, DXGI_FORMAT_R32_FLOAT, 1, 36, D3D11_INPUT_PER_INSTANCE_DATA, 1 }
};

创建实例缓冲区(每帧调用多次,以创建所有必要的缓冲区):

void GameManager::CreateInstanceBuffer(ID3D11Buffer** buffer, Mesh* mesh, std::vector<Instance> instances)
{

    D3D11_BUFFER_DESC instBuffDesc;
    ZeroMemory(&instBuffDesc, sizeof(instBuffDesc));

    instBuffDesc.Usage = D3D11_USAGE_DEFAULT;
    instBuffDesc.ByteWidth = sizeof(Instance) * instances.size();
    instBuffDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    instBuffDesc.CPUAccessFlags = 0;
    instBuffDesc.MiscFlags = 0;
    instBuffDesc.StructureByteStride = 0;

    int i = sizeof(Instance);

    D3D11_SUBRESOURCE_DATA instData;
    ZeroMemory(&instData, sizeof(instData));

    instData.pSysMem = &instances;
    instData.SysMemPitch = 0;
    instData.SysMemSlicePitch = 0;

    CheckFailWithError(dxManager.GetDevice()->CreateBuffer(&instBuffDesc, &instData, buffer),
        "An error occurred whilst building an instance buffer",
        "[GameManager]");


    meshBuffers.push_back(mesh->GetBuffer(VERTEX_BUFFER));
}

绘制命令:

dxManager.GetContext()->DrawIndexedInstanced(instanceIndexCounts[buffer], instanceCounts[buffer], 0, 0, 0);

着色器:

cbuffer cbChangesEveryFrame : register(b0)
{
    matrix worldMatrix;
};
cbuffer cbNeverChanges : register(b1)
{
    matrix viewMatrix;
};
cbuffer cbChangeOnResize : register(b2)
{
    matrix projMatrix;
};

struct VS_Input
{
    float4 pos : POSITION;
    float2 tex0 : TEXCOORD0;

    float4 instancePos : INSTANCEPOS;
    float4 instanceRot : INSTANCEROT;
    float4 instanceSca : INSTANCESCA;
    float instanceTex : INSTANCETEX;
};

PS_Input VS_Main(VS_Input vertex)
{
    PS_Input vsOut = (PS_Input)0;
    vsOut.pos = mul(vertex.pos + vertex.instancePos, worldMatrix);
    vsOut.pos = mul(vsOut.pos, viewMatrix);
    vsOut.pos = mul(vsOut.pos, projMatrix);
    vsOut.tex0 = vertex.tex0;
    return vsOut;
}

我使用了 Visual Studio 中内置的图形调试器。最初,它似乎将顶点着色器中的变量从后向前分配,但从 AlignedByteOffset 中删除 APPEND_ALIGNED_ELEMENT 已解决此问题,但每个实例的数据似乎已损坏并且没有被接收。

如果您还有其他需要,请告诉我,我会根据需要更新帖子。

【问题讨论】:

    标签: c++ directx-11 hlsl


    【解决方案1】:

    问题在于您的subresource 数据。

    instData.pSysMem = &instances;
    

    您没有指定从哪个偏移量读取内存。尝试使用

    instData.pSysMem = &instances[0];
    

    instData.pSysMem = &instances.at(0);
    

    这阐明了从哪里开始读取内存,并有望解决您的问题。

    【讨论】:

    • 3 个字符... 你是说我花了 2 个醒着的夜晚来寻找这个问题,以及它的 3 个字符?!非常感谢!它工作得很好,而且有点道理。
    • 指针...一定要爱上它们! 指向向量的指针与指向该向量中数据的指针不同。这就像指向一个装有某物的袋子与直接指向某物一样。它们是两种截然不同的东西。
    • 与其说是指针,不如说是void *。因为任何指针都可以隐式转换为指向void 的指针,所以类型系统无法帮助您解决这里的错误。正是出于这个原因,我通常在 void 指针周围放置一个最小的类型安全 C++ 包装器。
    猜你喜欢
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    相关资源
    最近更新 更多