1 hour ago, Hodgman said:You can have a single vertex shader that takes positions + colours as inputs, but create three different input layouts so that you can use that one shader with three different storage formats, e.g.
When it comes to your structs like Layout1Stream0 and my VertexTypeA I think we are talking about the same thing here. EG:
//The vertex types
class VertexTypeA
{
Vector3 pos; //Holds 3 floats: x, y, z
Color color; //Holds 4 floats: r, g, b, a
};
class VertexTypeB
{
Vector3 pos; //Holds 3 floats: x, y, z
};
class VertexTypeC
{
Color color; //Holds 4 floats: r, g, b, a
};
//======== Create and use the first input layout
D3D11_INPUT_ELEMENT_DESC layout1[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
d3dDevice->CreateInputLayout(layout1, 2, shaderCode->GetBufferPointer(), shaderCode->GetBufferSize(), &inputLayout1);
D3D11_BUFFER_DESC bufferDescription;
ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC));
bufferDescription.Usage = D3D11_USAGE_DYNAMIC;
bufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bufferDescription.ByteWidth = sizeof(VertexTypeA) * 3; //Enough for a triangle
graphicsDevice->device->CreateBuffer(&bufferDescription, NULL, &bufferVertexTypeA);
//Use the buffer/layout for input layout 1
UINT stride = sizeof(Vertex);
UINT offset = 0;
graphicsDevice->deviceContext->IASetVertexBuffers(0, 1, &bufferVertexTypeA, &stride, &offset);
//======== Create and use the second input layout
D3D11_INPUT_ELEMENT_DESC layout2[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
d3dDevice->CreateInputLayout(layout2, 2, shaderCode->GetBufferPointer(), shaderCode->GetBufferSize(), &inputLayout2);
//Position buffer
D3D11_BUFFER_DESC bufferDescription;
ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC));
bufferDescription.Usage = D3D11_USAGE_DYNAMIC;
bufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bufferDescription.ByteWidth = sizeof(VertexTypeB) * 3; //Enough for a triangle
graphicsDevice->device->CreateBuffer(&bufferDescription, NULL, &bufferVertexTypeB);
//Color buffer
D3D11_BUFFER_DESC bufferDescription;
ZeroMemory(&bufferDescription, sizeof(D3D11_BUFFER_DESC));
bufferDescription.Usage = D3D11_USAGE_DYNAMIC;
bufferDescription.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bufferDescription.ByteWidth = sizeof(VertexTypeC) * 3; //Enough for a triangle
graphicsDevice->device->CreateBuffer(&bufferDescription, NULL, &bufferVertexTypeC);
//Use the buffers/layout for input layout 2
UINT strides[2];
strides[0] = sizeof(VertexTypeB);
strides[1] = sizeof(VertexTypeC);
UINT offsets[2];
offsets[0] = 0;
offsets[1] = 0;
ID3D11Buffer* buffers[2];
buffers[0] = bufferVertexTypeB;
buffers[1] = bufferVertexTypeC;
deviceContext->IASetInputLayout(inputLayout2);
deviceContext->IASetVertexBuffers(0, 2, buffers, strides, offsets);
But yeah that makes sense that you could just have the one vertex shader to handle all of the different formats assuming they are more or less the same
I feel like it might be better to just create a new layout, but could you omit a property from use? Eg: you setup a layout to have 3 properties (Position, Color, Normal), but one of the things you want to draw only uses the properties Position and Normal where potentially everything else uses all 3 properties