#version 430

layout(binding=0) uniform sampler2D tex;
//layout(binding=1) uniform sampler2D tex2;
//layout(binding=2) uniform sampler2D tex3;
//layout(binding=3) uniform sampler2D tex4;
//layout(binding=4) uniform sampler2D texPrevBlurFrame;
//layout(binding=5) uniform sampler2D texPrevNorm;

layout(binding=0, offset=0) uniform atomic_uint ac;
layout(binding=0, rgba16f) uniform image2D emittedPartPos;
layout(binding=1, rgba16f) uniform image2D emittedPartVel;
layout(binding=2, rgba16f) uniform image2D emittedPartCol;


in vec4 posG;
in vec3 normalG;
in vec3 normalWSG;
in vec2 uvG;
in vec3 tangentG;
in vec4 posW;
in float brightG;

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


#define PI 3.1415926

uniform float g_time;

uniform float g_uvOfsX = 0.0;
uniform vec4 g_uvScale = vec4(1.0);

uniform float g_texBrightness = 1.0;
uniform float g_texAmbient = 0.0;
uniform float g_prevAmount = 0.0;
uniform float g_prevBlurAmount = 0.0;
uniform float g_bump = 0.0;

uniform float g_zoomTime = 0.0;

uniform vec4 g_color = vec4(1.0);


uniform mat4 modelViewMatrix;
uniform mat4 modelViewInvMatrix;
uniform mat4 viewInvMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 projectionInvMatrix;

uniform float g_windowWidth = 1280.0;
uniform float g_windowHeight = 720.0;

uniform float g_vortexRot;
uniform float g_vortexRotOfs;
uniform float g_vortexScale;

uniform float g_emitPercent;

uniform float g_vortexAngSpeed = 1.0;

uniform float g_timeStep;

uniform float g_alpha = 1.0;

uniform mat4 modelMatrix;


uniform float g_emitVelX = 0.0f;
uniform float g_emitVelY = 0.0f;
uniform float g_emitVelZ = 0.0f;
uniform float g_emitVelAmp = 1.0;
uniform float g_emitColorThr = 0.01;




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

vec3 rotateXY3(vec3 p, float a) {
  return rotateXY(vec4(p, 0.0), a).xyz;
}

// google glsl rand gave this, thanks and credit flies to
// http://stackoverflow.com/questions/4200224/random-noise-functions-for-glsl
float rand(vec2 co){
  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}

const float zFar = 1.0;
const float zNear = 0.0;

float getPointDist(float z) {
    float clipA = zFar / (zFar - zNear);
    float clipB = zFar*zNear / (zNear - zFar);
    return clipB/(z-clipA);
}
float getPointZ(float d) {
    float clipA = zFar / (zFar - zNear);
    float clipB = zFar*zNear / (zNear - zFar);
    return (clipB + d*clipA)/d;
}

vec4 CalcEyeFromWindow(in vec3 windowSpace) {
    vec3 ndcPos;
    vec4 viewport = vec4(0.0, 0.0, g_windowWidth, g_windowHeight);
    ndcPos.xy = ((2.0 * windowSpace.xy) - (2.0 * viewport.xy)) / (viewport.zw) - 1;
//    ndcPos.z = (2.0 * windowSpace.z - zNear - zFar) / (zFar - zNear);
    ndcPos.z = (2.0 * windowSpace.z - zNear - zFar) / (zFar - zNear);
    vec4 clipPos;
    clipPos.w = projectionMatrix[3][2]/(ndcPos.z-(projectionMatrix[2][2]/projectionMatrix[2][3]));
    clipPos.xyz = ndcPos * clipPos.w;
    return projectionInvMatrix * clipPos;
}

vec2 getBump(vec2 uv) {
    vec2 d = vec2(0.01, 0.0);
    return vec2(texture2D(tex, uv+d.xy).g-texture2D(tex, uv-d.xy).g,
                texture2D(tex, uv+d.yx).g-texture2D(tex, uv-d.yx).g);
}

float aTanSafe(float y, float x) {
    float ret;
    if (x!=0.0) {
        if (x>0.0) {
            ret=atan(y/x);
        } else	{
            ret=atan(y/x)+3.141592;
        }
    } else	{
        if (y>=0.0) {
            ret=0.5*3.141592;
        } else {
            ret=-0.5*3.141592;
        }
    }
    return ret;
}

float angTot = 0.0;



vec4 getRadTex(vec2 uv, vec2 uvd, float timeOfs) {
    uv.x *= -1.0;
    float rada = sqrt(dot(uv, uv));
    float ang = aTanSafe(uv.y, uv.x)*1.0;
    float rad = sqrt(dot(uv, uv))*0.1;
    float timePos = 64.0*fract(g_zoomTime+timeOfs);

    float radABase = log(rad)-timePos;
    float radA = fract(radABase);
    float radAC = radABase-radA;
    float radAP = (radA+50.0)/60.0;
    float angA = ang+radAC;
    vec2 uvrA = vec2(cos(ang), sin(ang))*(radA);
    float rotta = pow((1.0-rad*g_vortexScale), 3.5);
    uvrA = rotateXY(vec4(uvrA, 0.0, 0.0), (g_vortexRot+g_vortexRotOfs)*rotta).xy;

    float radBBase = log(rad)-timePos+0.375;
    float radB = fract(radBBase);
    float radBC = radB-radBBase;
    float angB = ang+radBC;
    vec2 uvrB = vec2(cos(ang), sin(ang))*(radB);
    rotta = pow((1.0-rad*g_vortexScale), 3.5);
    uvrB = rotateXY(vec4(uvrB, 0.0, 0.0), (g_vortexRot+g_vortexRotOfs)*rotta).xy;

    float fader = clamp((sin(radAP*150.0*2.0*3.141592+1.0*3.141592)+1.0)*0.5, 0.0, 1.0);
    vec4 diffuseA = texture2D(tex, (uvrA+uvd)*g_uvScale.xy)*fader;
    vec4 diffuseB = texture2D(tex, (uvrB+uvd)*g_uvScale.xy)*(1.0-fader);

    angTot = angA*fader+angB*(1.0-fader);

    vec4 diffuse = diffuseA+diffuseB;

    return diffuse;
}

vec2 getRadBump(vec2 uv) {
    vec2 d = vec2(0.01, 0.0);
    return vec2(getRadTex(uv, d.xy, 0.0).g-getRadTex(uv, -d.xy, 0.0).g,
                getRadTex(uv, d.yx, 0.0).g-getRadTex(uv, -d.yx, 0.0).g);
}


void main() {
  vec3 normal = normalG;
  vec2 uv = uvG;
  vec3 tangent = tangentG;
  float sk = 0.2;

  uv -= vec2(0.5);

  float angSpeed = 0.0;

  vec4 diffuse = getRadTex(uv, vec2(0.0), 0.0);
  angSpeed = angTot;
  vec4 diffuse2 = getRadTex(uv, vec2(0.0), 0.05);
  angSpeed -= angTot;

  vec4 d1 = diffuse;

 diffuse.rgb *=g_texBrightness;
 diffuse.rgb += vec3(g_texAmbient);
 diffuse.rgb *= g_color.rgb;

 vec2 norkor = vec2(gl_FragCoord.x/g_windowWidth, gl_FragCoord.y/g_windowHeight);

 diffuse.rgb *= brightG;

 frag.rgb = diffuse.rgb;

  float de = 100.0*rand(norkor.xy*1.0+vec2(sin(g_time*6.69), cos(g_time*1.320)));
  float ep = g_emitPercent*d1.r*g_timeStep/(0.07);

  float br = dot(vec3(1.0), frag.rgb);

  if (de > 100.0-ep && br*100.0>g_emitColorThr) {
      uint counter = atomicCounterIncrement(ac);
      uint cy = counter/(1280);
      uint cx = counter-uint(cy*1280);
      ivec2 listCoord = ivec2(cx,cy);
      vec3 rado = normalize(vec3(posW.xyz));
      vec3 uppo = vec3(0.0, 1.0, 0.0);
      vec3 radde = cross(rado,uppo);
      vec4 emitVel = vec4(g_emitVelX, g_emitVelY, g_emitVelZ, 0.0)+vec4(radde, 0.0)*g_vortexAngSpeed*angSpeed;
	  
      imageStore(emittedPartPos, listCoord, modelMatrix*vec4(posW.xyz, posW.w));
      imageStore(emittedPartVel, listCoord, emitVel);
      imageStore(emittedPartCol, listCoord, vec4(frag.rgb*50.0, 0.0));
     // frag.rgb = vec3(1.0);
  } else {
   // frag.rgb = vec3(0.0);
  }

  frag.rgb *= 0.001;
  frag.a = g_alpha;

  frag2.rgb = normalize(normalWSG).xyz;
  frag2 = clamp(frag2, -1.0, 1.0);
  frag2.a = 1.0;  

}
