简体   繁体   中英

DirectX11 Update Dynamic Instance Buffer

I have a multitude of trees being rendered through the use of instancing within my terrain generation app. I compare an instance list with my cameras frustum, to test whether they are visible. If they are visible, they get pushed to an instance vector. Each frame, if there are trees visible, I update the tree instance buffer. This works absolutely fine and the trees were rendered each frame without any problems, however, I recreated the instance buffer each frame, rather than updated it.

I recently changed the update function, which I thought would instead update the 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);
}

The problem is, the trees arent rendered correctly, as there is a lot of flickering (which I couldn't really capture very well), which I can only describe as the trees teleporting everywhere:

在此输入图像描述

The buffer is properly set up with 'D3D11_USAGE_DYNAMIC' usage flag and 'D3D11_CPU_ACCESS_WRITE' access flag.

Is it immediately obvious what I'm doing wrong? For reference this is how the buffer was recreated previously :

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

As @galop1n pointed out, the issue was due to the fact that I wasn't creating the instance buffer with the maximum amount of instances that were possible.

To solve the issue, I simply created the buffer with this in mind.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM