I created a simple Model framework in C++ 11 so that the same model can be rendered in different parts of a scene.
What I am trying to figure out is how to reference VertexBuffer data already "set" in the GPU for reuse as I draw different instances(100x) of different geometries, (i.e., square, triangle, etc).
I apologize that I had not understood the complexity of this particular question and have not been very good at making my question clear. As I am researching, I am clarifying the detail of the question.
Given: 1. Model Vertex Data is Stored in a Vertex Buffer, (that I refer to as the static/default Vertex Buffer). 2. Instance Position, (Vertex) data is stored in an instance buffer. 3. Constant Data, (World, View(to be changed), Projection) is stored in the Constant Buffer.
How Do I: 1. Update the entire Instance Buffer without having to re-bind the Static Buffer, and/or 2. Update only one instance in the Instance Buffer without having to re-bind the entire Instance Buffer
In the following code: I am defining both the Instance and Static Vertex Buffers' Element Description at the same time... Want to break this up, so that I can call VertexBuffer's initialization methods once, and then Instance Buffer's stuff over and over again:
void ModelRenderer::InitializeInputElementDescription()
{
// InputElementDescription = new D3D11_INPUT_ELEMENT_DESC[2]();
InputElementDescription[0] = D3D11_INPUT_ELEMENT_DESC();
InputElementDescription[0].SemanticName = "POSITION";
InputElementDescription[0].SemanticIndex = 0;
InputElementDescription[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
InputElementDescription[0].InputSlot = 0;
InputElementDescription[0].AlignedByteOffset = 0;
InputElementDescription[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
InputElementDescription[0].InstanceDataStepRate = 0;
InputElementDescription[1] = D3D11_INPUT_ELEMENT_DESC();
InputElementDescription[1].SemanticName = "TEXCOORD";
InputElementDescription[1].SemanticIndex = 0;
InputElementDescription[1].Format = DXGI_FORMAT_R32G32B32_FLOAT;
InputElementDescription[1].InputSlot = 1;
InputElementDescription[1].AlignedByteOffset = 0;
InputElementDescription[1].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
InputElementDescription[1].InstanceDataStepRate = 1;
}
Shader File: My Semantic isn't being recognized somehow here, but I can manually set a shape's position.
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
float3 position : POSITION;
float3 instance_position : TEXCOORD;
// float3 color : COLOR0;
};
struct VertexShaderOutput
{
float4 pos : SV_POSITION;
// float3 color : COLOR0;
};
VertexShaderOutput main(VertexShaderInput input)
{
VertexShaderOutput output;
// Move the Instance someplace into the world.
float3 translatedPosition = input.position + input.instance_position;
float4 pos = float4(translatedPosition, 1.0f);
// Transform the vertex position into projected space.
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
// Pass through the color without modification.
// output.color = input.color;
return output;
}
Initializing InstanceBuffer: Something like this would be called every frame, or so. But right now, I am sending this info along with the static vertex buffer info:
/**************************************/ void ModelRenderer::InitializeInstanceBuffer() { HRESULT result;
instances = new Position[2]();
instances[0].X = 0.0f;
instances[0].Y = 0.0f;
instances[0].Z = 0.0f;
instances[1].X = 0.5f;
instances[1].Y = 0.5f;
instances[1].Z = 0.5f;
// Set up the description of the instance buffer.
instanceBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
instanceBufferDesc.ByteWidth = sizeof(Position) * 2;
instanceBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
instanceBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
instanceBufferDesc.MiscFlags = 0;
instanceBufferDesc.StructureByteStride = 0;
instanceSubResourceData.SysMemPitch = 0;
instanceSubResourceData.SysMemSlicePitch = 0;
instanceSubResourceData.pSysMem = instances;
result = DeviceManager::Device->CreateBuffer(&instanceBufferDesc, &instanceSubResourceData, &instanceBuffer);
delete [] instances;
}
Here, I am setting my VertexBuffer and InstanceBuffer into the InputAssembly (IA), both at the same time. I would only want to do this once on initialization, and then call a similar method that doesn't reference the initial static vertex buffer data again:
/******************************************************************/
void ModelRenderer::Stage()
{
DeviceManager::DeviceContext->OMSetRenderTargets(
1,
DeviceManager::RenderTargetView.GetAddressOf(),
DeviceManager::DepthStencilView.Get()
);
DeviceManager::DeviceContext->UpdateSubresource(
ConstantBuffer.Get(),
0,
NULL,
&ConstantBufferData,
0,
0
);
DeviceManager::DeviceContext->UpdateSubresource(
instanceBuffer,
0,
NULL,
&instanceSubResourceData,
0,
0
);
unsigned int offsets[2] = {0,0};
unsigned int strides[2];
ID3D11Buffer* bufferPointers[2];
strides[0] = sizeof(NS::Vertex);
strides[1] = sizeof(Position);
bufferPointers[0] = ModelRenderer::VertexBuffer.Get();
bufferPointers[1] = ModelRenderer::instanceBuffer;
DeviceManager::DeviceContext->IASetInputLayout(ModelRenderer::InputLayout.Get());
DeviceManager::DeviceContext->IASetVertexBuffers(
0,
2,
bufferPointers,
strides,
offsets
);
DeviceManager::DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
DeviceManager::DeviceContext->VSSetConstantBuffers(
0,
1,
ModelRenderer::ConstantBuffer.GetAddressOf()
);
}
Thanks for the help!