DirectX11 更新动态实例缓冲区

DirectX11 Update Dynamic Instance Buffer

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

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

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);
}

问题是,树没有正确渲染,因为有很多闪烁(我不能很好地捕捉到),我只能描述为到处传送的树:

缓冲区已正确设置 'D3D11_USAGE_DYNAMIC' 使用标志和 'D3D11_CPU_ACCESS_WRITE' 访问标志。

我做错了什么很明显吗?作为参考,这是重新创建缓冲区的方式 之前:

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));
}

正如@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));