Using vertex buffer instancing, how to dynamically change separate instance position?

2.1k views Asked by At

I need to draw million cubes. Cubes has the same vertex array, but may have different scale/position/rotation. Important: they may change their position dynamically, after vertex buffer creation. Some of them should be connected by the line. So I also need to draw lines.

Currently I deal with the instancing using constant buffer:

VertexShader.hlsl

struct VS_INPUT
{
float4 pos: POSITION;
float4 colour: COLOUR;
uint InstanceID: SV_InstanceID;
}
cbuffer ConstantBuffer : register(b0)
{
float4x4 view;
float4x4 proj;
float4x4 world[4000];
}

In D3D initialization I create one constant buffer resource, get the GPU address and copy there structure object:

struct ConstantBufferObject
{
XMFLOAT4X4 view;
XMFLOAT4X4 proj;
XMFLOAT4X4 world[4000];
}cbNPerObject;
...
memcpy(cbvGPUAddress[i],& cbNPerObject,sizeof(cbNPerObject));

Then I fill cbNPerObject.world the way I need and in the UpdatePipeline() make one call DrawIndexedInstanced() with number of cubes I added.

All works good, except one thing - constant buffer size restriction. float4x4 world[4000] can be maxim 4096 sized, but I need millions. Create chunks in form of constant buffers with 4096 size - seems not cool. So I decided to use another method of instancing - use vertex buffer.

I don’t understand how can I dynamically transform my instances when I use vertex buffer, because to change vertex buffer I have to change vertexBufferView which also seems incorrect. As far as I understand for instancing by this way I need to create instance buffer and store it together with vertex buffer or what, Im confused

1

There are 1 answers

6
cmaughan On

You need to use an instance buffer; effectively storing the positions in a new vertex buffer which you map into memory and modify before submitting. Inside the vertex shader you then have access to the instance position for the thing you are currently drawing.

There's a good explanation of it here: https://www.braynzarsoft.net/viewtutorial/q16390-33-instancing-with-indexed-primitives

This example is based on DX11, but the principle is the same.

Somebody converted the approach to DX12 here: https://gamedev.stackexchange.com/questions/163077/dx12-passing-an-instance-buffer