#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=6) uniform sampler2D texB;



in vec4 posG;
in vec3 normalG;
in vec3 normalWSG;
in vec2 uvG;
in vec3 tangentG;
//in vec3 colorG;
in vec4 posW;
in vec3 origCenterG;
in vec4 genInfoG;
in vec4 emitInfoG;
in vec4 branchInfoG;
in float alphaG;

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 float g_uvScale = 1.0;

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

uniform float g_texFade0 = 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;

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);
}

// branch trans
uniform float g_palSwipeTimeOfs = 0.0;

uniform float g_palSwipeFreq = 1.0;
uniform float g_palSwipeOfs = 0.0;
uniform float g_palSwipeZero = 0.1;
uniform float g_palSwipeIntensity = 1.5;
uniform float g_palSwipeColorPow = 1.0;

uniform float g_palSwipeFadeFreq = 1.0;
uniform float g_palSwipeFadeOfs = 0.0;
uniform float g_palSwipeFadePerc = 0.0;

uniform float g_swipeRadAmp = 1.0;

uniform float g_agePalFreq = 1.0;
uniform float g_agePalOfs = 0.0;
uniform float g_agePalIntensity = 1.0;


void main() {    

  vec3 normal = normalG;
  vec2 uv = uvG;
  vec3 tangent = tangentG;
//  vec3 color = colorG;

  float branchTime = emitInfoG.x*0.001;

  float age = genInfoG.y*0.001; // age in seconds

  uv.x += branchTime*1.0;

  vec4 diffuse = texture2D(tex, uv*g_uvScale*1.0);
  diffuse.rgb *= diffuse.rgb;

  vec4 diffuseB = texture2D(texB, uv*g_uvScale*1.0);
  diffuseB.rgb *= diffuseB.rgb;

  if (g_texFade0 > 0.0) {
      diffuse = (1.0-g_texFade0)*diffuse+g_texFade0*diffuseB;
  }

  float daa = diffuse.a;

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

 float twopi = 2.0*3.141592;



// diffuse.rgb = vec3(1.0);
 float swipePos = -branchTime*g_palSwipeFreq+g_palSwipeOfs;
 float radWorld = emitInfoG.x*0.1;//sqrt(dot(posW.xz, posW.xz));
 vec4 swipe = texture2D(tex2, vec2(swipePos, radWorld*g_swipeRadAmp));


 vec4 ageSwipe = texture2D(tex3, vec2(clamp(age*g_agePalFreq+g_agePalOfs+0.002, 0.0, 1.0), radWorld*g_swipeRadAmp));

 swipe.rgb = pow(swipe.rgb, vec3(g_palSwipeColorPow));
 float fp = clamp((branchTime*g_palSwipeFadeFreq+g_palSwipeFadeOfs)/twopi, 0.0, 1.0)*twopi;
 float swipeFade = clamp(sin(fp)-g_palSwipeFadePerc, 0.0, 1.0)/(1.0-g_palSwipeFadePerc);
 diffuse.rgb += (vec3(g_palSwipeZero)+g_palSwipeIntensity*swipe.rgb*swipeFade);
 diffuse.rgb += ageSwipe.rgb*ageSwipe.rgb*g_agePalIntensity;


 vec2 b = g_bump*getBump(uv.xy*g_uvScale);
 vec3 normalW = normalize(normalWSG);
 tangent = normalize(tangent);
 vec3 bt = cross(normalW,tangent);
 vec3 normResult = normalW+tangent*b.x+bt*b.y;
 normResult = normalize(normResult);

 normal = normResult;

 vec4 normalBW = (projectionMatrix*viewMatrix*vec4(normal, 0.0));
 vec3 normalB = normalBW.xyz;
 normalB /= -normalBW.w;
 vec2 norkor = vec2(gl_FragCoord.x/g_windowWidth, gl_FragCoord.y/g_windowHeight);
 vec2 paske = (norkor.xy)+0.0025*(normalB.xy);
 paske = clamp(paske, 0.0, 1.0);
 float kk = 0.5;

 if (paske.x < 0.01 || paske.y < 0.01 || paske.x > 0.99 || paske.y > 0.99) kk = 0.0;

 vec2 pasked = (norkor.xy)+0.0001*(normalB.xy);
 pasked = clamp(pasked, 0.0, 1.0);
// if (paske.x < 0.01 || paske.y < 0.01 || paske.x > 0.99 || paske.y > 0.99) kk = 0.0;
 vec3 jorge = texture2D(texPrevNorm, pasked).rgb*1.0;
 vec4 efe = CalcEyeFromWindow(vec3(paske.x*g_windowWidth, paske.y*g_windowHeight, jorge.r));
 vec3 seze = (viewInvMatrix*vec4(efe.xyz, 1.0)).xyz*1.0;

 vec3 jorgeC = texture2D(texPrevNorm, norkor).rgb*1.0;
 vec4 efeC = CalcEyeFromWindow(vec3(norkor.x*g_windowWidth, norkor.y*g_windowHeight, jorgeC.r));
 vec3 sezeC = (viewInvMatrix*vec4(efeC.xyz, 1.0)).xyz*1.0;

 vec3 sp = posW.xyz;
 sp = seze-sezeC;
 float kx = sqrt(dot(sp, sp))*100.0;
 float dok = 0.1/(clamp(kx*kx, 0.0, 10000.0)*0.25+1.0);
 dok = clamp(dok, 0.0, 100.0);

 float kx0 = dot(sp, sp);
 sp/=sqrt(kx0);
 float dok2 = dot(sp, normal)+0.0;
 dok2 = clamp(dok2*1.0, 0.0, 1.0);

 float dok2a = 0.5;
 dok = (dok2*dok2a+(1.0-dok2a)*dok);

 vec3 prevb = texture2D(texPrevBlurFrame, paske).rgb*clamp(dok*kk, 0.0, 1.0);

 diffuse.rgb *= (0.10+1.0*g_prevBlurAmount*(pow(clamp(prevb-vec3(0.001), 0.0, 8.0),vec3(1.0))-vec3(0.0)));

 diffuse.rgb *= genInfoG.x;
 frag.rgb = diffuse.rgb;
 frag.a = daa*alphaG*ageSwipe.a;

 if ((frag.a+0.001*rand(gl_FragCoord.xy+vec2(0.69*g_time, 0.9*g_time)))<0.01) {
     discard;
 }


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

}

