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