DirectX11更新动态实例缓冲区

时间:2016-06-10 13:00:10

标签: c++ directx directx-11 direct3d11

我通过在我的地形生成应用程序中使用实例化来渲染大量树。我将实例列表与我的相机视锥体进行比较,以测试它们是否可见。如果它们可见,则会将它们推送到实例向量。每个帧,如果有树可见,我更新树实例缓冲区。这非常正常,并且每个帧都呈现树而没有任何问题,但是,我每帧重新创建实例缓冲区,而不是更新它。

我最近更改了更新功能,我认为它会更新缓冲区:

void CModel::UpdateInstances(const std::vector<SInstance>& instances, ID3D11DeviceContext* context)
{
    D3D11_MAPPED_SUBRESOURCE resource;
    ZeroMemory(&resource, sizeof(resource));

    mInstanceCount = instances.size();
    size_t copySize = sizeof(SInstance) * mInstanceCount;

    context->Map(mIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);     
    memcpy(resource.pData, &instances[0], copySize);
    context->Unmap(mIB, 0);
}

问题是,树木没有正确渲染,因为有很多闪烁(我无法捕捉得非常好),我只能将其描述为传送到各处的树木:

enter image description here

使用&#39; D3D11_USAGE_DYNAMIC&#39;正确设置缓冲区。使用标志和&#39; D3D11_CPU_ACCESS_WRITE&#39;访问标志。

我做错了吗?作为参考,这是如何重新创建缓冲区之前

void CModel::UpdateInstances(const std::vector<SInstance>& instances, ID3D11Device* device)
{
    mInstanceCount = instances.size();

    if (mIB)
        SafeRelease(mIB);

    D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_DYNAMIC;
    ibd.ByteWidth = sizeof(SInstance) * mInstanceCount;
    ibd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    ibd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    ibd.MiscFlags = 0;
    ibd.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA isr;
    isr.pSysMem = &instances[0];
    isr.SysMemPitch = 0;
    isr.SysMemSlicePitch = 0;

    DXHRes(device->CreateBuffer(&ibd, &isr, &mIB));
}

1 个答案:

答案 0 :(得分:0)

正如@ galop1n指出的那样,问题是由于我没有使用可能的最大实例数创建实例缓冲区。

为了解决这个问题,我只是简单地创建了缓冲区。

D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_DYNAMIC;
ibd.ByteWidth = sizeof(SInstance) * maxInstances;
ibd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
ibd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;

D3D11_SUBRESOURCE_DATA isr;
isr.pSysMem = &instances[0];
isr.SysMemPitch = 0;
isr.SysMemSlicePitch = 0;

DXHRes(device->CreateBuffer(&ibd, &isr, &mIB));