简体   繁体   中英

DirectX 11: how to define input layout when using more than one vertex buffer?

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.

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 },
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM