#version 430

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

in vec4 posG;
in vec2 uvG;
in vec2 uvOrig;
in float sharpnessG;
in vec4 posSS;
in float age;
in float ageSplit;

flat in int gl_PrimitiveID;


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

layout(binding=0, offset=0) uniform atomic_uint ac;

layout(binding=0, r32ui) uniform uimage2D headPointers;
layout(binding=1, r32ui) uniform uimage2D nextPointers;
layout(binding=2, rgba16f) uniform image2D pixelListColors;
layout(binding=3, rgba32f) uniform image2D pixelListDepthNorm;

uniform float g_time;
uniform float g_partSize = 0.15;

uniform float g_maxAge = 1.0;

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 g_partMapWX = 0.0;


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

uniform float g_partAlpha = 1.0;

uniform float g_vilkeFreq = 1.0;
uniform float g_vilkeAmp = 1.0;

uniform float g_fadeInSpeed = 10.0;
uniform float g_fadeOutSpeed = 10.0;

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

    vec4 result = texture2D(tex, myUv+vec2(0.0, 0.0));
    // vec4 nois = texture2D(texNoise, myUv+vec2(0.0, 0.0));
    // vec4 emitShape = texture2D(texEmitShape, uvOrig);

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

    vec2 uvNorm = uvm/sqrt(dist);

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

    sharpness = 1.0;
    float powe = 1.0;

   // circle = clamp(smoothstep(0.0, 1.0, pow(circle*sharpness, powe))/clamp(sharpness, 0.0, 100.0), 0.0, 1.0);
    circle = clamp(pow(circle*sharpness, powe), 0.0, 1.0);

    vec3 normal;

    normal.x = uvm.x;
    normal.y = uvm.y;
    normal.z = sqrt(1.0-dot(normal.xy, normal.xy));
    normal.z *= normal.z;
    normal = normalize(normal);
//    normal *= circle;

    float pa = g_partAlpha;
    pa *= clamp(age*g_fadeInSpeed*10.0, 0.0, 1.0);
    pa *= clamp((g_maxAge-age)*g_fadeOutSpeed*10.0, 0.0, 1.0);
    pa *= (0.5+0.5*g_vilkeAmp*sin(age*10.0*g_vilkeFreq));

    //circle = 1.0;
   // result.rgb = vec3(circle);

  //  result.a = clamp(result.r*0.50, 0.0, 1.0);
    // result.rgb *= 1.0;
    result.a *= pa*1.0;

   // result.a *= result.b;
    result.a = clamp(result.a-0.1, 0.0, 1.0)*1.0;

    result.rgb *= pa;
    frag = result;

    float depthi = (posG.z/posG.w);

    float ld = linearDepth(depthi);

    frag2.r = (depthi+result.a*5.0);
    frag2.gb = vec2(normal.xy);
    // frag2.g = ld;
    //frag2.b = 4.0+frag.a*3.0;
    frag2.a = pa;

  //  discard;

    if (result.a < 0.01) {
        discard;
    }

//    uint counter = atomicCounterIncrement(ac)+1;
//    uint cy = counter/(1280*4);
//    uint cx = counter-uint(cy*1280*4);
//    ivec2 listCoord = ivec2(cx,cy);
//    uint prevCounter = imageAtomicExchange(headPointers, ivec2(gl_FragCoord.xy), counter);
//    imageStore(nextPointers, listCoord, uvec4(prevCounter));
//    imageStore(pixelListColors, listCoord, frag);
//    imageStore(pixelListDepthNorm, listCoord, frag2);

//    discard;

//    uint counter = atomicCounterIncrement(ac);
//    frag.rgb = vec3(fract(float(counter)/(1280.0*720.0)));


//    if (result.a < 0.25) {
//        discard;
//    }

//    int primID = gl_PrimitiveID;

//    vec3 color;

//    if ((primID&3)==0) {
//        color.rgb = vec3(1.0);
//    } else if ((primID&3)==1) {
//        color.rgb = vec3(0.0, 0.0, 1.15);
//    } else if ((primID&3)==2) {
//        color.rgb = vec3(0.90, 0.0, 0.0);
//    } else {
//        color.rgb = vec3(0.2);
//    }

//    color.rgb = vec3(0.4+1.20*cos(age*0.75), 0.80*cos(age*0.72), 0.0+0.2*cos(age*0.52+sin(age*0.52)))+vec3(0.0);
    //frag2 = vec4(color*2.45*result.a*w, result.a*0.0);
}

