Hello,
I am currently working on hardware instancing to put grass on a terrain based on this example (GitHub - Eastrall/MonoGame-HardwareInstancing).
But I can’t display the instances on the screen. I can display the GrassElement if I don’t use instancing (so this might not be the issue here)
I think the error might be in the GrassManager but it’s been two days and I can’t find anything to make it working.
I created a structure to pass a Vector4, I created the two buffers to store the geometry and the instances and I bind them to the Graphic Device.
Here is the code
Shader:
#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif
matrix WorldViewProjection;
struct InstancingVSInput
{
float4 Position : POSITION0;
float4 Color : COLOR0;
};
struct InstancingVSOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
};
InstancingVSOutput InstancingVS(in InstancingVSInput input, float4 instanceTransform : POSITION1)
{
InstancingVSOutput output = (InstancingVSOutput)0;
float4 pos = input.Position + instanceTransform;
pos = mul(pos, WorldViewProjection);
output.Position = pos;
output.Color = input.Color;
return output;
}
float4 InstancingPS(InstancingVSOutput input) : COLOR
{
return input.Color;
}
technique Instancing
{
pass P0
{
VertexShader = compile VS_SHADERMODEL InstancingVS();
PixelShader = compile PS_SHADERMODEL InstancingPS();
}
};
GrassManager
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
namespace _3dtest.Map
{
class GrassManager
{
private const int NBGRASS = 1;
GrassElement grassElement;
Effect effect;
VertexBuffer instancesBuffer;
IndexBuffer indexBuffer;
struct GrassInfo
{
public Vector4 World;
};
VertexBufferBinding[] bindings;
private VertexDeclaration instanceVertexDeclaration;
public void Initialize(GraphicsDevice graphicsDevice,int mapSize)
{
InitializeInstanceVertexBuffer();
grassElement = new GrassElement();
grassElement.Initialize(graphicsDevice);
indexBuffer = new IndexBuffer(graphicsDevice, typeof(short), grassElement.indices.Length, BufferUsage.WriteOnly);
indexBuffer.SetData(grassElement.indices);
//Creating instances
GrassInfo[] pos = new GrassInfo[NBGRASS];
pos[0].World = new Vector4(30,30,30,1);
instancesBuffer = new VertexBuffer(graphicsDevice, instanceVertexDeclaration, NBGRASS, BufferUsage.WriteOnly);
instancesBuffer.SetData(pos);
bindings = new VertexBufferBinding[2];
bindings[0] = new VertexBufferBinding(grassElement.vertexBuffer);
bindings[1] = new VertexBufferBinding(instancesBuffer, 0, 1);
}
private void InitializeInstanceVertexBuffer()
{
VertexElement[] _instanceStreamElements = new VertexElement[1];
// Position
_instanceStreamElements[0] = new VertexElement(0, VertexElementFormat.Vector4,
VertexElementUsage.Position, 1);
instanceVertexDeclaration = new VertexDeclaration(_instanceStreamElements);
}
public void LoadContent(ContentManager content)
{
effect = content.Load<Effect>("effects/instance_effect");
}
public void Draw(GraphicsDevice graphicsDevice,Matrix view,Matrix projection)
{
// Set the effect technique and parameters
effect.CurrentTechnique = effect.Techniques["Instancing"];
effect.Parameters["WorldViewProjection"].SetValue(view * projection);
graphicsDevice.Indices = indexBuffer;
effect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.SetVertexBuffers(bindings);
graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList ,0,0,NBGRASS,NBGRASS);
}
}
}
GrassElement:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace _3dtest.Map
{
class GrassElement
{
public readonly VertexPositionColor[] vertices = new VertexPositionColor[]
{
new VertexPositionColor(new Vector3(-10,0,0),Color.Green),
new VertexPositionColor(new Vector3(0,100,0),Color.Green),
new VertexPositionColor(new Vector3(10,0,0),Color.Green),
};
public VertexBuffer vertexBuffer;
public readonly short[] indices = new short[]
{
0,1,2
};
public void Initialize(GraphicsDevice graphicsDevice)
{
vertexBuffer = new VertexBuffer(graphicsDevice, typeof(
VertexPositionColor), vertices.Length, BufferUsage.
WriteOnly);
vertexBuffer.SetData<VertexPositionColor>(vertices);
}
}
}
Thank you for your help,