##start
##vertex

#version 150
#extension GL_ARB_explicit_attrib_location : enable


layout(location=0) in vec3 in_Position;
layout(location=1) in vec3 in_Direction;
layout(location=2) in vec4 in_Data;
layout(location=3) in vec2 in_Lifetime;
layout(location=4) in vec3 in_Color;


uniform mat4 projMatrix;
uniform mat4 viewMatrix;
uniform mat4 viewProjMatrix;
uniform mat4 depthBiasMV;

uniform vec2 screenRes;

uniform float time;

uniform float flashLightIntensity;

out vec4 color;
out float visibility;

#define PARTICLE_RAIN 0.0
#define PARTICLE_OTHER 1.0
#define PARTICLE_RAIN_FLYING 2.0


float compute_pointsize(float light_radius, vec4 position)
{
        float d = position.z;

        mat4 m = projMatrix;
        vec4 v = vec4(light_radius, light_radius, d, 1.0);

        vec4 tmp = vec4(v.x*m[0].x, v.y*m[1].y, v.z*m[2].z+m[3].z, -v.z);
        vec3 tmp2 = tmp.xyz / tmp.w;

//10.15*


        float size = tmp2.x *screenRes.x /  200.f;
        return size;
}



void main()
{
	float in_Gravity = in_Data.x;
	float in_Size = in_Data.y;
        float in_Type = in_Data.z;
        float in_bottom = in_Data.w;

	float x = time - in_Lifetime.x;
	float factor = x/(in_Lifetime.y-in_Lifetime.x);

	vec4 pos = vec4(in_Position,1) +  vec4(0,-1,0,0)*x*x*in_Gravity + vec4(in_Direction,0)*x;

        //vec4 pos = vec4(in_Position,1);
        gl_Position = viewProjMatrix *  pos;
        float pointSizeScale = 1.0;
        if (in_Type == PARTICLE_RAIN_FLYING){
            pointSizeScale = 2.0;
        }
        gl_PointSize = /*max(minPointsize, */pointSizeScale*compute_pointsize(in_Size,viewMatrix*pos)/*)*/;
        //gl_PointSize = 1000.0f;
        //color = vec4(x/(in_Lifetime.y-in_Lifetime.x),pos.y/100,pos.x*100,1-factor);
        color = vec4(in_Color,1-factor);
        if(factor>1 || factor<0){
            gl_PointSize = 0.0f;
            visibility = 0.f;
            return;
        }



        vec4 shadowCoord = depthBiasMV * pos;
        shadowCoord /= shadowCoord.w;


        const float ambient = 0.0;

        //check if fragment is outside of lights view
        if ((in_Type == PARTICLE_RAIN || in_Type == PARTICLE_RAIN_FLYING) && (shadowCoord.s < 0 || shadowCoord.s > 1 || shadowCoord.t < 0 || shadowCoord.t > 1)){
            visibility = ambient; //ambient
        } else if (in_Type == PARTICLE_RAIN || in_Type == PARTICLE_RAIN_FLYING){

//            //TODO: check for night
            visibility = 1.0;

            float borderfactor = 1.0f;

            const float minRange =0.45f;
            const float maxRange = 0.5f;
            float dist = distance(vec2(0.5,0.5),shadowCoord.st);

            borderfactor = dist-minRange;
            borderfactor = 1-(borderfactor/(maxRange-minRange));
            borderfactor= clamp(borderfactor,ambient,1.0) *clamp(flashLightIntensity*2.0, 0.7, 1.0);
            visibility *= borderfactor;

//            if (flashLightIntensity == 1.75){
//                visibility = 0.0;
//            }
            //            visibility = 1.0;


            //limit flashlight range
            const float minRange2 = 10.0f;
            float maxRange2 = 70.0f*flashLightIntensity*2;
            //linear fall off between min and max range
            float dist2 = length(viewMatrix*pos);
            float falloff = dist2-minRange2;
            falloff = 1-(falloff/(maxRange2-minRange2));
            visibility*=  clamp(falloff,0.0,1.0);
//            visibility =1.0;


        } else {
            visibility =1.0;

        }



        if(pos.y<in_bottom){
            gl_PointSize = 0.0f;
            visibility = 0.0f;

        }
}



##end


##start
##fragment

#version 150 core
#extension GL_EXT_texture_array : enable

in vec4 color;
in float visibility;

out vec4 out_color;



void main(void)
{


        out_color = visibility*color;


}


##end
