#type vertex
#version 440 core
layout (location = 0) in int Type;
layout (location = 1) in int ID;
layout (location = 2) in vec3 InitPosition;
layout (location = 3) in vec3 Randomness;
layout (location = 4) in vec4 InitColor; // It does not store the color but the XY coordiate of the FBO
layout (location = 5) in float Life;

uniform mat4 m4ViewModel; // view x Model matrix
uniform float fTime;
uniform float drawStartPosition; // where we need to start drawing particles
uniform float drawOffset;  // When we need to end drawing particles (fixed value)
uniform float fParticleSize;

out VS_OUT {
flat int 	Type;
flat int 	ID;
vec2		fboTexCoord;
vec4		Position;
float       Size;
} vs_out;

int randomInt(vec2 st) {
return int(fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453) * 10000.0);
}

void main(void) {
// LocalPosition stores where this particle is being drawn withing the offsset
float localPosition = 0;

if ((InitPosition.x > (drawStartPosition)) && (InitPosition.x < (drawStartPosition+drawOffset))) {
if (0 == mod(ID, randomInt(InitColor.xy))) // We draw one particle of each 16 
    vs_out.Type = Type;
else
    vs_out.Type = 0;
}
else {
vs_out.Type = 0; // This means that the particle will not be drawn (geometry shader will not emmit any primitieve)
}
vs_out.ID = ID;
//vs_out.Color = InitColor;
vs_out.Size = fParticleSize + fParticleSize*Randomness.z;

// A la piscion inicial le sumamos un poquito de randomness
vec3 newPosition = InitPosition + vec3(0.0*Randomness.x, 0.0*Randomness.y, 0); // Con el factor de random podemos ajustar la distorision de donde se pintan las partículas

vs_out.fboTexCoord = InitColor.xy;
vs_out.Position = m4ViewModel * vec4(newPosition, 1.0);
}

#type geometry
#version 440 core

layout(points) in;
layout(triangle_strip) out;
layout(max_vertices = 4) out;

uniform mat4 m4Projection;


// Info from the VS
in VS_OUT
{
flat int 	Type;
flat int	ID;
vec2		fboTexCoord;
vec4		Position;
float        Size;
} gs_in[];

// Info sent to FS
out GS_OUT
{
flat int	ID;
vec2		fboTexCoord;
vec2		TexCoord;
} gs_out;

#define PARTICLE_TYPE_EMITTER 1
#define PARTICLE_TYPE_SHELL 2

void main()
{
float fPartSize = gs_in[0].Size;
gs_out.ID = gs_in[0].ID;
gs_out.fboTexCoord = gs_in[0].fboTexCoord;

if (gs_in[0].Type == PARTICLE_TYPE_EMITTER) {

vec4 P = gs_in[0].Position;

// a: left-bottom 
vec2 va = P.xy + vec2(-0.5, -0.5) * fPartSize;
gl_Position = m4Projection * vec4(va, P.zw);
gs_out.TexCoord = vec2(0.0, 0.0);
EmitVertex();

// b: left-top
vec2 vb = P.xy + vec2(-0.5, 0.5) * fPartSize;
gl_Position = m4Projection * vec4(vb, P.zw);
gs_out.TexCoord = vec2(0.0, 1.0);
EmitVertex();

// d: right-bottom
vec2 vd = P.xy + vec2(0.5, -0.5) * fPartSize;
gl_Position = m4Projection * vec4(vd, P.zw);
gs_out.TexCoord = vec2(1.0, 0.0);
EmitVertex();

// c: right-top
vec2 vc = P.xy + vec2(0.5, 0.5) * fPartSize;
gl_Position = m4Projection * vec4(vc, P.zw);
gs_out.TexCoord = vec2(1.0, 1.0);
EmitVertex();

EndPrimitive();
}
}

#type fragment
#version 440 core
layout (location = 0) out vec4 FragColor;

uniform sampler2D partTexture;
uniform sampler2D screenTexture;

in GS_OUT
{
flat int	ID;
vec2		fboTexCoord;
vec2		TexCoord;
} fs_in;


void main(void)
{
vec4 fboColor = texture(screenTexture, fs_in.fboTexCoord);
//fboColor = vec4(1.0, 1.0, 1.0, 1.0);
FragColor = texture(partTexture, fs_in.TexCoord) * fboColor;
}
