Hi,
i try to optimize my particle system. Just for fun. I use a single vertex buffer and index buffer for all emitters and try to optimize it with instancing.
I have one vertex buffer for my quad (texture cordinates only) and the index buffer of course.
I also have a vertex buffer for my instances with position, rotation, color and size.
But it just does not render anything. My custom shader works, I tested it with the old rendering, but I am doing something wrong
public sealed class ParticleProcessor : BaseDrawingProcessor<ParticleComponent>
{
private const int NumParticlesPerRenderingCall = 4000;
private IndexBuffer indexBuffer;
private VertexBuffer vertexBuffer;
private VertexBuffer instanceBuffer;
private VertexBufferBinding vertexBufferBinding;
private VertexBufferBinding instanceBufferBinding;
private VertexBufferBinding[] bindings;
private VertexPositionColorRotationSize[] instanceVertices;
private ParticleEffect particleEffect;
public override void LoadContent(Scene scene)
{
indexBuffer = new IndexBuffer(scene.GraphicsDevice, IndexElementSize.SixteenBits, 6, BufferUsage.None);
indexBuffer.SetData(new long[] { 0, 1, 2, 0, 2, 3 });
vertexBuffer = new VertexBuffer(scene.GraphicsDevice, typeof(VertexTexture), 4, BufferUsage.None);
vertexBufferBinding = new VertexBufferBinding(vertexBuffer);
vertexBuffer.SetData(new VertexTexture[]
{
new VertexTexture(new Vector2(0, 0)),
new VertexTexture(new Vector2(1, 0)),
new VertexTexture(new Vector2(1, 1)),
new VertexTexture(new Vector2(0, 1)),
});
instanceVertices = new VertexPositionColorRotationSize[NumParticlesPerRenderingCall];
instanceBuffer = new VertexBuffer(scene.GraphicsDevice, typeof(VertexPositionColorRotationSize), NumParticlesPerRenderingCall, BufferUsage.WriteOnly);
instanceBufferBinding = new VertexBufferBinding(instanceBuffer, 0, 1);
bindings = new VertexBufferBinding[] { vertexBufferBinding, instanceBufferBinding };
particleEffect = new ParticleEffect(scene.Content.Load<Effect>("Effects/Particles"));
}
private void RenderJob(GraphicsDevice graphicsDevice, ParticleRenderingJob job, Matrix viewProjection)
{
graphicsDevice.Indices = indexBuffer;
particleEffect.CurrentTechnique.Passes[0].Apply();
var particleIndex = 0;
unsafe
{
for (var i = 0; i < job.Particles.Length; i++)
{
var particle = job.Particles[i];
if (particle->Lifetime > 0)
{
instanceVertices[particleIndex].Position = particle->Position;
instanceVertices[particleIndex].Rotation = particle->Rotation;
instanceVertices[particleIndex].Size.X = particle->Size;
instanceVertices[particleIndex].Size.Y = particle->Size;
instanceVertices[particleIndex].Color = particle->Color;
particleIndex++;
if (particleIndex == NumParticlesPerRenderingCall)
{
RenderMesh(graphicsDevice, particleIndex);
particleIndex = 0;
}
}
}
}
RenderMesh(graphicsDevice, particleIndex);
}
private void RenderMesh(GraphicsDevice graphicsDevice, int numParticles)
{
if (numParticles > 0)
{
instanceBuffer.SetData(instanceVertices, 0, numParticles);
graphicsDevice.SetVertexBuffers(bindings);
graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 2, numParticles);
}
}
}
What is confusing for me, is that the ordering of the vertex bindings matters. When I change the order I get the following execption: : 'An error occurred while preparing to draw. This is probably because the current vertex declaration does not include all the elements required by the current vertex shader. The current vertex declaration includes these elements: SV_Position0, COLOR0, COLOR1, TEXCOORD1, TEXCOORD0.'
Which is strange because it matchs to my shader:
struct VSInput
{
float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
float2 Size : TEXCOORD1;
float4 Color : COLOR0;
float Rotation : COLOR1;
};