//Go through list of trees and creates vertex buffer, this of course happens only on inicialization of scene
//Vertex declaration has byteStride 64, 4x Vector4 (world matrix), world matrix is transposed (column major) to save few instructions when building matrix on GPU
private void GenerateWorldMatrixBuffer(List<InstanciedModelInfo> modelList, ref VertexBuffer vertexBuffer)
{
Matrix[] worldMatrixArray = new Matrix[modelList.Count];
for(int i = 0; i < modelList.Count; i++)
{
worldMatrixArray[i] = modelList[i].WorldMatrix;
}
vertexBuffer = new VertexBuffer(RENDERING_MANAGER.device, VegetationVertex.VertexDeclaration, worldMatrixArray.Length, BufferUsage.WriteOnly);
vertexBuffer.SetData(worldMatrixArray);
}
//During scene inicializtion
//Generate World Matrix vertex buffer for all trees
GenerateWorldMatrixBuffer(tree01ModelsInfo, ref tree01WorldBuffer);
//Build bindings
tree01Bindings = new VertexBufferBinding[2];
//Whole model is in meshPart[0]
tree01Bindings[0] = new VertexBufferBinding(MODEL_MANAGER.tree01.Meshes[0].MeshParts[0].VertexBuffer);
//Vertex buffer of world matrices, frequency 1
tree01Bindings[1] = new VertexBufferBinding(tree01WorldBuffer, 0, 1);
Draw cycle
DrawInstanciedModels(tree01Bindings, tree01.model.Meshes[0].MeshParts[0], tree01ModelsInfo.Count, tree01.effect);
private void DrawInstanciedModels(VertexBufferBinding[] bindings, ModelMeshPart mesh, int count, ModelShader effect)
{
effect.Apply();
//set bindings
RENDERING_MANAGER.device.SetVertexBuffers(bindings);
//get indices
RENDERING_MANAGER.device.Indices = mesh.IndexBuffer;
//Draw
RENDERING_MANAGER.device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, mesh.IndexBuffer.IndexCount / 3, count);
}
Vertex Shader
struct VertexShaderInput
{
float4 Position : SV_Position;
float4 Normal : NORMAL0;
float3 Tangent : TANGENT0;
float3 Binormal : BINORMAL0;
float2 TexCoord : TEXCOORD0;
float4 Color : COLOR0;
};
struct VertexShaderInstanceInput
{
float4 row1 : TEXCOORD1;
float4 row2 : TEXCOORD2;
float4 row3 : TEXCOORD3;
float4 row4 : TEXCOORD4;
};
VertexShaderOutput DebugVertexInstancied(VertexShaderInput input, VertexShaderInstanceInput input2)
{
VertexShaderOutput output;
//actually columns
float4x4 WorldInstance = CreateMatrixFromCols(input2.row1, input2.row2, input2.row3, input2.row4);
float objectID = dot(float3(WorldInstance._41, WorldInstance._42, WorldInstance._43), 1);
float4 worldPosition = mul(input.Position, WorldInstance);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.WorldPos = worldPosition;
output.TexCoord = input.TexCoord;
output.Normal = normalize(mul(float4(input.Normal.xyz,0), WorldInstance));
output.Tangent = mul(input.Tangent, (float3x3)WorldInstance);
output.Tangent = normalize(output.Tangent);
output.Binormal = mul(input.Binormal, (float3x3)WorldInstance);
output.Binormal = normalize(output.Binormal);
output.Color = input.Color;
return output;
}
Thanks again and if this doesn’t help or is too inconvenient I will do my best to get project in way you can run it (but lot of things are in prototype state so I think this actually might be more readable from outside view.