Reputation: 11
Using Direct3D 11, I would like to be able to use separate vertex buffers for positions and color. I want do do that when positions rarely change at runtime, whereas colors may change quite often. The subject is not new but I could not find a comprehensive answer to correctlty handle many vertex buffers/shaders. If I'm quite confident on how to create and set the vertex buffers, I'm not sure how to define the layout. To experiment, I started from a MSDN tutorial that just draw a single triangle with just one vertex shader. I splitted the shader into 2 parts, position and color.
Hereafter are the main lines of my HLSL and C++ code.
// ****** Shaders file *****
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};
// Position shader
VS_OUTPUT VPS( float4 Pos : POSITION )
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Pos = Pos;
return output;
}
// Color shader
VS_OUTPUT VCS( float4 Color : COLOR )
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Color = Color;
return output;
}
// Pixel shader
float4 PS( VS_OUTPUT input ) : SV_Target
{
return input.Color;
}
// ********** C++ file abstract **********
// Position shader
ID3DBlob* pVPSBlob
ID3D11VertexShader* g_pVertexShader
// Color shader
ID3DBlob* pVCSBlob
ID3D11VertexShader* g_pVertexColorShader
// Pixel shader
ID3DBlob* pPSBlob
ID3D11InputLayout* g_pVertexLayout
// Vertex buffers
ID3D11Buffer* g_pVertexBuffer = nullptr;
ID3D11Buffer* g_pVertexColorBuffer = nullptr;
// I compile and create the shaders with:
D3DCompileFromFile(), CreateVertexShader()
// I define the input vertex position layout in slot 0
D3D11_INPUT_ELEMENT_DESC positionLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE( positionLayout );
// Create the input vertex layout
hr = g_pd3dDevice->CreateInputLayout( positionLayout, numElements, pVPSBlob->GetBufferPointer(),
pVPSBlob->GetBufferSize(), &g_pVertexLayout );
// Set the input vertex layout
g_pImmediateContext->IASetInputLayout( g_pVertexLayout );
// I define the input color layout in slot 1
D3D11_INPUT_ELEMENT_DESC colorsLayout[] =
{
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
numElements = ARRAYSIZE( colorsLayout );
// Create the input colors layout
hr = g_pd3dDevice->CreateInputLayout( colorsLayout, numElements, pVCSBlob->GetBufferPointer(),
pVCSBlob->GetBufferSize(), &g_pVertexColorLayout );
// Set the input color layout
g_pImmediateContext->IASetInputLayout( g_pVertexColorLayout );
// I set the 3 shaders:
g_pImmediateContext->VSSetShader( g_pVertexShader, nullptr, 0 );
g_pImmediateContext->VSSetShader( g_pVertexColorShader, nullptr, 0 );
g_pImmediateContext->PSSetShader( g_pPixelShader, nullptr, 0 );
// I create 2 vertex buffers for positions and colors and set them
// Set the positions & colors vertex buffers
ID3D11Buffer *vertexBuffers[] = { g_pVertexBuffer, g_pVertexColorBuffer };
UINT strides[] = { sizeof( SimpleVertex ), sizeof( ColorVertex ) };
UINT offsets[] = { 0, 0};
g_pImmediateContext->IASetVertexBuffers( 0, 2, vertexBuffers, strides, offsets );
I also tried to define the layout element into a single array, in two different slots, but it didn't work either. In that case, what shader should I use?
All I could get was an empty screen, and I'm getting stuck... Thanks in advance if someone could help.
Upvotes: 1
Views: 7453
Reputation: 39551
You can only have one input layout and one vertex shader set on the device context at one time. Each time you call IASetInputLayout
and VSSetShader
the previous layout/shader is replaced with the new one. Merge your two input layout structures into one structure, and your HLSL vertex shaders into one shader. The InputSlot
field member of D3D11_INPUT_ELEMENT_DESC
will determine which vertex buffer is used for that element.
Something like:
VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR) { VS_OUTPUT output = (VS_OUTPUT)0; output.Pos = Pos; output.Color = Color; return output; }
D3D11_INPUT_ELEMENT_DESC positionLayout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
Upvotes: 7