Direct3D11 and SharpDX - How to pass a model instance's world matrix as an input to a vertex shader

Posted by Nathan Ridley on Game Development See other posts from Game Development or by Nathan Ridley
Published on 2013-11-01T12:00:47Z Indexed on 2013/11/01 16:23 UTC
Read the original article Hit count: 449

Filed under:
|

Using Direct3D11, I'm trying to pass a matrix into my vertex shader from the instance buffer that is associated with a given model's vertices and I can't seem to construct my InputLayout without throwing an exception.

The shader looks like this:

cbuffer ConstantBuffer : register(b0)
{
    matrix World;
    matrix View;
    matrix Projection;
}

struct VIn
{
    float4 position: POSITION;
    matrix instance: INSTANCE;
    float4 color: COLOR;
};

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(VIn input)
{
    VOut output;
    output.position = mul(input.position, input.instance);
    output.position = mul(output.position, View);
    output.position = mul(output.position, Projection);
    output.color = input.color;
    return output;
}

The input layout looks like this:

var elements = new[]
{
    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, InputClassification.PerVertexData, 0),
    new InputElement("INSTANCE", 0, Format.R32G32B32A32_Float, 0, 0, InputClassification.PerInstanceData, 1),
    new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 12, 0)
};
InputLayout = new InputLayout(device, signature, elements);

The buffer initialization looks like this:

public ModelDeviceData(Model model, Device device)
{
    Model = model;
    var vertices = Helpers.CreateBuffer(device, BindFlags.VertexBuffer, model.Vertices);
    var instances = Helpers.CreateBuffer(device, BindFlags.VertexBuffer, Model.Instances.Select(m => m.WorldMatrix).ToArray());
    VerticesBufferBinding = new VertexBufferBinding(vertices, Utilities.SizeOf<ColoredVertex>(), 0);
    InstancesBufferBinding = new VertexBufferBinding(instances, Utilities.SizeOf<Matrix>(), 0);
    IndicesBuffer = Helpers.CreateBuffer(device, BindFlags.IndexBuffer, model.Triangles);
}

The buffer creation helper method looks like this:

public static Buffer CreateBuffer<T>(Device device, BindFlags bindFlags, params T[] items)
    where T : struct
{
    var len = Utilities.SizeOf(items);
    var stream = new DataStream(len, true, true);
    foreach (var item in items)
        stream.Write(item);
    stream.Position = 0;
    var buffer = new Buffer(device, stream, len, ResourceUsage.Default,
        bindFlags, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
    return buffer;
}

The line that instantiates the InputLayout object throws this exception:

*HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.*

Note that the data for each model instance is simply an instance of SharpDX.Matrix.

EDIT

Based on Tordin's answer, it sems like I have to modify my code like so:

var elements = new[]
{
    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, InputClassification.PerVertexData, 0),
    new InputElement("INSTANCE0", 0, Format.R32G32B32A32_Float, 0, 0, InputClassification.PerInstanceData, 1),
    new InputElement("INSTANCE1", 1, Format.R32G32B32A32_Float, 0, 0, InputClassification.PerInstanceData, 1),
    new InputElement("INSTANCE2", 2, Format.R32G32B32A32_Float, 0, 0, InputClassification.PerInstanceData, 1),
    new InputElement("INSTANCE3", 3, Format.R32G32B32A32_Float, 0, 0, InputClassification.PerInstanceData, 1),
    new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 12, 0)
};

and in the shader:

struct VIn
{
    float4 position: POSITION;
    float4 instance0: INSTANCE0;
    float4 instance1: INSTANCE1;
    float4 instance2: INSTANCE2;
    float4 instance3: INSTANCE3;
    float4 color: COLOR;
};

VOut VShader(VIn input)
{
    VOut output;
    matrix world = { input.instance0, input.instance1, input.instance2, input.instance3 };
    output.position = mul(input.position, world);
    output.position = mul(output.position, View);
    output.position = mul(output.position, Projection);
    output.color = input.color;
    return output;
}

However I still get an exception.

© Game Development or respective owner

Related posts about shaders

Related posts about directx11