#version 430

layout(binding=0) uniform sampler2D tex;
layout(binding=1) uniform sampler2D texNoise;
layout(binding=2) uniform sampler2D texAgeSwipe;
layout(binding=3) uniform sampler2D texEnv;

layout(binding=5) uniform sampler2D texPrevBlurFrame;

in vec4 posG;
in vec2 uvG;
in vec2 uvOrig;
in vec3 colG;
in float sharpnessG;
// in vec4 posSS;
in float age;
in vec3 ageColG;
in float brightG;
in float aspectG;

in vec3 posW;

// flat in int gl_PrimitiveID;
uniform float g_windowWidth = 1280.0;
uniform float g_windowHeight = 720.0;


layout(location = 0) out vec4 frag;
layout(location = 1) out vec4 frag2;
layout(location = 2) out vec4 frag3;


uniform float g_time;
uniform float g_partSize = 0.15;

uniform float zNear = 0.1;
uniform float zFar = 1000.0;
// convert from 0.0 to 1.0 depth sample ds to linear depth
float linearDepth(float ds) {
    ds = 2.0*ds-1.0;
    float zLinear = 2.0*zNear*zFar/(zFar+zNear-ds*(zFar-zNear));
    return zLinear;
}
// result suitable for assigning to gl_FragDepth
float depthSample(float linearDepth) {
    float nonLinearDepth = (zFar+zNear-2.0*zNear*zFar/linearDepth)/(zFar-zNear);
    nonLinearDepth = (nonLinearDepth+1.0)/2.0;
    return nonLinearDepth;
}


#define PI 3.1415926

vec2 latlong(vec3 v) {
  v = normalize(v);
  float theta = acos(v.z); // +z is up
  float phi = atan(v.y, v.x) + PI;
  return vec2(phi, theta)*vec2(.1591549, .6366198);
}


vec3 rotateXY(vec3 p, float a) {
  vec3 r = p;
  r.x = cos(a)*p.x - sin(a)*p.y;
  r.y = sin(a)*p.x + cos(a)*p.y;
  return r;
}


uniform float g_partMapX = 0;
uniform float g_partMapY = 0;


uniform float near = 0.1;
uniform float far = 1000.0;

uniform float g_maxAge;

uniform float g_partBright = 1.0;
uniform float g_partAlpha = 1.0;

uniform float g_useTexture = 0.0;

uniform float g_palaEmit = 0.0;

uniform float g_palaEmitThr = 0.0;

// starting from fadeZ position gain with given value until palaEmit is reached
// use g_palaEmitFadeZ -9999 to disable
uniform float g_palaEmitFadeZ = -30.0;
uniform float g_palaEmitGainZ = -10.0;


uniform float g_prevBlurAmount = 0.0;

uniform float g_ageAlphaFade = 0.0;

void main() {
    vec2 myUv = uvG;
    myUv.y *= -1.0;
    float sharpness = sharpnessG;
    myUv *= 1.0/8.0;
    myUv.x += g_partMapX*1.0/8.0;
    myUv.y += g_partMapY*1.0/8.0;

    vec4 result;

    vec2 uvm = (uvG-vec2(0.5,0.5))*2.0;
    float dist = (dot(uvm,uvm));

    float circle = clamp(1.0-dist*1.0, 0.0, 1.0);

    float powe = 1.0/sharpness;

    circle = clamp(pow(circle, powe), 0.0, 1.0);
    result.rgb = vec3(circle);

    if (g_useTexture > 0.5) {
        result.rgb = texture2D(tex, myUv+vec2(0.0, 0.0)).rgb;
    }

    vec3 myNormal = vec3(uvm.x, uvm.y, 0.0);


    result.rgb = pow(result.rgb, vec3(0.5));

    result.rgb *= g_partBright*brightG;
    result.a = clamp(result.r*1.0, 0.0, 1.0);
    result.a = pow(result.a, 1.0);


    result.rgb *= ageColG;



    if (g_prevBlurAmount > 0.001) {
        vec2 norkor = vec2(gl_FragCoord.x/g_windowWidth, gl_FragCoord.y/g_windowHeight);
        myNormal.x /= g_windowWidth/g_windowHeight;
        vec2 paske = (norkor.xy)-0.1*myNormal.xy;
        paske = clamp(paske, 0.0, 1.0);
        vec3 prevb = texture2D(texPrevBlurFrame, paske).rgb;
        result.rgb += g_prevBlurAmount*pow(clamp(prevb-vec3(0.001), 0.0, 1.0),vec3(1.0));
     }

    result.a *= g_partAlpha;

    result.a *= clamp(1.0/(age*g_ageAlphaFade+0.01), 0.0, 1.0);


    result.a = clamp(result.a, 0.0, 100.0);

    frag = result;

    if (frag.r < 0.001) {
        discard;
    }
    if (result.a < 0.002) {
        discard;
    }

    frag.rgb *= (colG*1.0+0.0);
    frag2 = vec4(myNormal.xy, -1.0, 1.0); // result.a);

    float pe = g_palaEmit;
    if (g_palaEmitFadeZ > -9990.0) {
        pe = min(pe, abs((posW.z-g_palaEmitFadeZ)*g_palaEmitGainZ));

        float per = min(1.0, abs((posW.z-g_palaEmitFadeZ)*g_palaEmitGainZ));
        frag.rgb *= per;

       // frag.rgb = vec3(posW.z)*100.0;
       // frag.rgb = posW.xyz;
    }

    frag3.rgba = clamp(frag.rgba-vec4(g_palaEmitThr), 0.0, 100.0)*pe;

    // frag3.r = 1.0;
}

