// ## VERTEX SHADER ##
// Author: Jackson Luff
// Name: ParticleUpdate.vert
// Type: Vertex Shader
// Description:
// * This shader is utilized as the
// * standard update loop for the
// * particles. Only difference is
// * that this update loop is on
// * the GPU and not CPU.
#version 410
in layout(location=0) vec3 Position;
in layout(location=1) vec3 Velocity;
in layout(location=2) float Lifetime;
in layout(location=3) float Lifespan;
out vec3 vPosition;
out vec3 vVelocity;
out float vLifetime;
out float vLifespan;
uniform mat4 World;
uniform vec3 emitterPosition;
uniform float time;
uniform float deltaTime;
uniform float lifeMin;
uniform float lifeMax;
uniform float veloMax;
const float INVERSE_MAX_UINT = 1.0f / 4294967295.0f;
float rand(uint seed, float range)
{
uint i = (seed ^ 12345391u) * 2654435769u;
i ^= (i << 6u) ^ (i >> 26u);
i *= 2654435769u;
i += (i << 5u) ^ (i >> 12u);
return float(range * i) * INVERSE_MAX_UINT;
}
vec3 newVel = vec3(0);
void main()
{
//Get Previous Frame Velocity
newVel = Velocity;
uint seed = uint(time * 1000.0) + uint(gl_VertexID);
float dt = deltaTime;
// Warp velocity using trigonometry
float a = Lifetime, b = Lifespan, c = 0.5, d = 0.5;
newVel.x = (a-b)*sin(time) + b * sin(time * ((a/b)-1));
newVel.y = (a-b)*sin(time) / b * cos(time * ((a/b)-1));
newVel.z = (a-b)*cos(time) - b * cos(time * ((a/b)-1));
// Update base data with new information
vPosition = Position + (Velocity * dt);
vVelocity = newVel;
vLifetime = Lifetime + dt;
vLifespan = Lifespan;
// if life time is up, reset
if(vLifetime > vLifespan)
{
//Initialise velocity
vVelocity.x = rand(seed++, 2) / veloMax + sin(time);
vVelocity.y = rand(seed++, 2) / veloMax + cos(time);
vVelocity.z = rand(seed++, 2) / veloMax + tan(time);
vVelocity = normalize(vVelocity);
vPosition = emitterPosition + vec3(sin(time)*0.5, -sin(time)*0.5, cos(time)*0.5);
vLifetime = 0;
vLifespan = rand(seed++, lifeMax - lifeMin) + lifeMin;
}
}