Ty PumpkinPudding.
Figures it would be a typo to look past over and over.
VertexElementUsage.Position, 1),
Most ridiculous thing of all is that the 1 was in the shader the entire time. So i must of accounted for it at some point. Sorry man i feel stupid.
Edit:
I altered the code a bit and pumped out 2 million particles no problem, nice.
The altered working gl code is below it’s a little bit simpler then the previous example.

The 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
#define PS_SHADERMODEL ps_4_0
#endif
//_________________________________________________________________
//__________________________ the gl shader_________________________
//_________________________________________________________________
static const float PI = 3.14159;
static const float PI2 = 6.28318;
static const float EIGHT_PI = 25.13274;
//float Life;
float TotalTime;
matrix WorldViewProjection;
Texture2D ParticleTexture;
sampler2D TexSampler = sampler_state
{
Texture = <ParticleTexture>;
//AddressU = Wrap;//AddressV = Wrap;//MinFilter = Anisotropic;//MagFilter = Anisotropic;//MipFilter = Point;
};
//__________________________________________________________
struct VSInstanceInputSimple
{
float3 InstancePosition : POSITION1; // ahh wait waat .... like i must have accounted for this at some point and didn't change the cs file as well ... omg there is a lesson here.
float InstanceTimeOrId : BLENDWEIGHT0;
};
struct VSVertexInputSimple
{
float4 Position : POSITION0;//SV_POSITION;
float2 TexCoord : TEXCOORD0;
//uint InstanceId : SV_InstanceId;
};
struct VSOutputSimple
{
float4 Position : SV_POSITION;
float2 TexCoord : TEXCOORD0;
float4 Color : COLOR0;
};
VSOutputSimple MainVSSimple(in VSVertexInputSimple vertexInput, VSInstanceInputSimple instanceInput)
{
VSOutputSimple output;
output.TexCoord = vertexInput.TexCoord;
float3 InstancePosition = instanceInput.InstancePosition;
float InstanceTimeOrId = instanceInput.InstanceTimeOrId;
float movingTime = InstanceTimeOrId * TotalTime + TotalTime;
float4 posVert = mul(vertexInput.Position, WorldViewProjection);
float4 posInst = mul(InstancePosition.xyz, WorldViewProjection);
float4 pos = posVert + posInst;
output.Position = pos;
// uncomment the below line for super trippy mode lol
output.Position = pos * sin(movingTime * PI2);
output.Position.x = pos.x * cos(movingTime * PI2) - pos.y * sin(movingTime * PI2);
output.Position.y = pos.x * sin(movingTime * PI2) + pos.y * cos(movingTime * PI2);
// change color
float4 startColor = lerp(float4(1.0, 0.0, 0.0, 1.0), float4(0.0, 0.0, 1.0, 1.0), InstancePosition.x);
float4 endColor = lerp(float4(0.5, 0.5, 0.0, 1.0), float4(0.0, 1.0, 1.0, 1.0), InstancePosition.y);
output.Color = lerp(startColor, endColor, (InstancePosition.z + InstanceTimeOrId));
return output;
}
float4 MainPSSimple(VSOutputSimple input) : COLOR0
{
float4 col = input.Color * tex2D(TexSampler, input.TexCoord);
// straight clip alpha draws
clip(col.a - .05f);
return col;
}
technique ParticleDrawingSimple
{
pass
{
VertexShader = compile VS_SHADERMODEL MainVSSimple();
PixelShader = compile PS_SHADERMODEL MainPSSimple();
}
};
The game1 file
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Runtime.InteropServices;
namespace GLParticleTestTrimed
{
// the instanceDataType
[StructLayout(LayoutKind.Sequential)]
public struct InstanceData : IVertexType
{
public Vector3 instancePosition;
public float instanceTimeOrId;
public static readonly VertexDeclaration VertexDeclaration;
static InstanceData()
{
var elements = new VertexElement[]
{
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 1), // oh 0 so bad bad.
new VertexElement(12, VertexElementFormat.Single, VertexElementUsage.BlendWeight, 0)
//new VertexElement( offset in bytes, VertexElementFormat.Single, VertexElementUsage. option, shader element usage id number )
};
VertexDeclaration = new VertexDeclaration(elements);
}
VertexDeclaration IVertexType.VertexDeclaration
{
get { return VertexDeclaration; }
}
}
// the vertexDataType
[StructLayout(LayoutKind.Sequential)]
public struct VertexPositionTexture : IVertexType
{
public Vector3 position;
public Vector2 texCoordinate;
public static readonly VertexDeclaration VertexDeclaration;
static VertexPositionTexture()
{
var elements = new VertexElement[]
{
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
};
VertexDeclaration = new VertexDeclaration(elements);
}
VertexDeclaration IVertexType.VertexDeclaration
{
get { return VertexDeclaration; }
}
}
public class Game1 : Game
{
GraphicsDeviceManager graphics;
ParticleSystem02 particleSystem;
Matrix viewProjection;
Texture2D particleTexture;
Effect particlesEffect;
// basically a elaborate timing device.
float cyclePercentage = 0f;
public double fullCycleTimeInSeconds = 9d; // you can speed it up or slow it down with this.
double cycleTime = 0d;
double elapsedUpdateTime = 0;
double last = 0d;
double now = 0d;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.GraphicsProfile = GraphicsProfile.HiDef;
graphics.PreferMultiSampling = false;
Window.AllowUserResizing = true;
graphics.PreferredBackBufferWidth = 1024;
graphics.PreferredBackBufferHeight = 768;
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
SetUpViewProjection();
particlesEffect = Content.Load<Effect>("ParticleEffect03GL");
particleTexture = Content.Load<Texture2D>("particle");
particleSystem = new ParticleSystem02(particlesEffect)
{
ParticleSize = new Vector2(2.0f, 2.0f),
ParticleTexture = particleTexture,
InitialInstanceCount = 2000500, // Lets push it up to a Million
//VisiblityDuration = 5.0f,
};
particleSystem.IntializeParticleSystemBuffers(GraphicsDevice);
}
public void SetUpViewProjection()
{
// Setup the worldViewProj matrix
float width = GraphicsDevice.PresentationParameters.BackBufferWidth;
float height = GraphicsDevice.PresentationParameters.BackBufferHeight;
float aspect = width / height;
Matrix viewMatrix = Matrix.CreateLookAt(new Vector3(0.01f, 0.01f, 5.0f), Vector3.Forward, Vector3.Up);
Matrix projMatrix = Matrix.CreateOrthographic(aspect * width, height, 0.1f, 1000);
viewProjection = viewMatrix * projMatrix;
}
protected override void UnloadContent()
{
Content.Unload();
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
last = now;
now = gameTime.ElapsedGameTime.TotalSeconds;
elapsedUpdateTime = now - last;
cycleTime += elapsedUpdateTime;
cyclePercentage = (float)(cycleTime / fullCycleTimeInSeconds);
if (cycleTime > fullCycleTimeInSeconds)
{
cycleTime -= fullCycleTimeInSeconds;
}
particleSystem.UpdateParticleTime((float)(cyclePercentage));
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
//GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.Black, 1.0f, 0);
GraphicsDevice.BlendState = BlendState.Additive;
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
particleSystem.DrawParticles(viewProjection, GraphicsDevice);
base.Draw(gameTime);
}
}
public class ParticleSystem02
{
// Vertex data
VertexBuffer vertexBuffer;
IndexBuffer indexBuffer;
VertexBufferBinding vertexBufferBinding;
// Instance data
InstanceData[] instanceData;
VertexBuffer instanceBuffer;
VertexBufferBinding instanceBufferBinding;
int numInstancesToDraw;
float totalTime = 0;
Effect particlesEffect;
public Vector2 ParticleSize { get; set; }
public Texture2D ParticleTexture { get; set; }
public uint InitialInstanceCount { get; set; }
public int MaxVisibleParticles
{
get; private set;
}
//public float VisiblityDuration { get; set; }
#region Initilisation
public ParticleSystem02(Effect effect)
{
particlesEffect = effect;
}
public void IntializeParticleSystemBuffers(GraphicsDevice graphicsDevice)
{
// set up the indice stuff
int[] indices = new int[6];
// indices to triangle vertices
indices[0] = 1; indices[1] = 0; indices[2] = 2;
indices[3] = 3; indices[4] = 1; indices[5] = 2;
//
indexBuffer = new IndexBuffer(graphicsDevice, typeof(int), 6, BufferUsage.WriteOnly);
indexBuffer.SetData(indices);
// set up the vertex stuff
// Create a single quad centered at the origin
float halfWidth = ParticleSize.X / 2;
float halfHeight = ParticleSize.Y / 2;
float z = .2f;
VertexPositionTexture[] vertices = new VertexPositionTexture[4];
// x,y world positions
vertices[0].position = new Vector3(-halfWidth, -halfHeight, z);
vertices[1].position = new Vector3(halfWidth, -halfHeight, z);
vertices[2].position = new Vector3(-halfWidth, halfHeight, z);
vertices[3].position = new Vector3(halfWidth, halfHeight, z);
// u,v texture coords
vertices[0].texCoordinate = new Vector2(0.0f, 0.0f);
vertices[1].texCoordinate = new Vector2(1.0f, 0.0f);
vertices[2].texCoordinate = new Vector2(0.0f, 1.0f);
vertices[3].texCoordinate = new Vector2(1.0f, 1.0f);
//
vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionTexture.VertexDeclaration, 4, BufferUsage.WriteOnly);
vertexBuffer.SetData(vertices);
vertexBufferBinding = new VertexBufferBinding(vertexBuffer);
// set up the instance stuff
MaxVisibleParticles = (int)(InitialInstanceCount);
instanceData = new InstanceData[MaxVisibleParticles];
// set particles randomly
Random rnd = new Random();
for (int i = 0; i < MaxVisibleParticles; ++i)
{
// instance data float time
instanceData[i].instanceTimeOrId = -(i + 1) / (float)InitialInstanceCount;
// instance data float position
instanceData[i].instancePosition = new Vector3
(
(rnd.Next(0, 800) - 400),
(rnd.Next(0, 600) - 300),
rnd.Next(1, MaxVisibleParticles + 1) / (float)(MaxVisibleParticles + 1)
);
}
//
instanceBuffer = new VertexBuffer(graphicsDevice, InstanceData.VertexDeclaration, MaxVisibleParticles, BufferUsage.WriteOnly);
instanceBufferBinding = new VertexBufferBinding(instanceBuffer, 0, 1);
instanceBuffer.SetData(instanceData);
}
#endregion Initilisation
// We could draw less instances here.
public void UpdateParticleTime(float seconds)
{
// i could use my dynamic dead alive buffer here to keep the sorting smooth.
numInstancesToDraw = MaxVisibleParticles;
totalTime += seconds;
}
public void DrawParticles(Matrix worldViewProj, GraphicsDevice graphicsDevice)
{
// Select the technique.
particlesEffect.CurrentTechnique = particlesEffect.Techniques["ParticleDrawingSimple"];
// Initialise our shader constants
particlesEffect.Parameters["WorldViewProjection"].SetValue(worldViewProj);
particlesEffect.Parameters["ParticleTexture"].SetValue(ParticleTexture);
particlesEffect.Parameters["TotalTime"].SetValue((float)totalTime);
// Set buffers to device
graphicsDevice.SetVertexBuffers(vertexBufferBinding, instanceBufferBinding);
graphicsDevice.Indices = indexBuffer;
// Draw
particlesEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 2, numInstancesToDraw);
}
}
}
The texture i used
![]()