#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;
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;
	vec4		Color;
	vec4		Position;
    float       Size;
} vs_out;

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)))
        vs_out.Type = Type;
    else
        vs_out.Type = 0; // This means that the particle will not be drawn (geometry shader will not emmit any primitieve)

    //Descartamos las particulas que tienen un color cero (o casi cero)
    float colorFilter = dot(InitColor.rgb, vec3(1, 1, 1));
    if(colorFilter < 1) // Si ajustamos este valor, podemos pintar partículas incluso donde la imagen es cero
        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*Randomness.y, 0); // Con el factor de random podemos ajustar la distorision de donde se pintan las partículas

    // Calculate LocalPosition value, based on the new Position of the particle, describing a sinusoidal curve
    // LocalPosition = 0 when the particle is at drawStartPosition
    // LocalPosition = 1 when the particle is at drawStartPosition+(offset/2)
    // LocalPosition = 0 when the particle is at drawStartPosition+offset
    localPosition = sin(2*3.1415*(newPosition.x/drawOffset) - (drawStartPosition)/drawOffset);

    //vs_out.Color = InitColor * localPosition; // Podemos usar el color original de la imagen
    vs_out.Color = vec4(0.7,0.8,0.3,1) * localPosition; // O podemos forzar nosotros un color... incluso podemos sacarlo como un parámetro del sscript
    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;
	vec4		Color;
	vec4		Position;
    float        Size;
} gs_in[];

// Info sent to FS
out GS_OUT
{
	flat int	ID;
	vec4		Color;
	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.Color = gs_in[0].Color;

	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;

in GS_OUT
{
	flat int	ID;
	vec4		Color;
	vec2		TexCoord;
} fs_in;


void main(void)
{
FragColor = texture(partTexture, fs_in.TexCoord) * fs_in.Color;
}
