#version 430 core

layout(std430, binding = 0) buffer SSBO
{
    vec3 values[100];
};



#pragma optionNV unroll all
#define MAX_LIGHTS 14
#define TMAX_LIGHTS 20
#define MAX_BONES 78

#define NUMLIGHTS 4

uniform float iTime;
uniform float testvalue;

uniform sampler2D normalMap;

uniform mat4 ModelViewProjectionMatrix;
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;

uniform float lightsPosx[MAX_LIGHTS];
uniform float lightsPosy[MAX_LIGHTS];
uniform float lightsPosz[MAX_LIGHTS];

out vec4 vpos; 

    out vec3 v;
    out vec3 N;
    out vec3 T;
    out vec3 B;
    out vec3 originalV;

in vec3 vertexPosition;
in vec3 vertexNormal;
in vec2 textureCoord;
in vec3 vertexTangent;
in float vertexTangentHandedness;
in vec3 vertexOriginalPosition;
in vec4 vertexBones;
in vec4 vertexWeights;

uniform mat4 depthBiasMVP[NUMLIGHTS];
out vec4 ShadowCoord[NUMLIGHTS];

uniform vec4 Lights[NUMLIGHTS];
uniform vec4 LightsPos[NUMLIGHTS];

out float ShadowAngle[NUMLIGHTS];
out vec4 vN_;
out vec4 vP_;



uniform int hasAnim[1];
uniform mat4 bonePos[MAX_BONES];
uniform mat4 boneRPos[MAX_BONES];
uniform mat4 boneRot[MAX_BONES];
uniform mat4 boneScl[MAX_BONES];

out vec3 alightVec[TMAX_LIGHTS];
out vec3 aeyeVec[TMAX_LIGHTS];
out vec2 texCoord;
uniform float lightsEnabled[MAX_LIGHTS];





vec3 tmpVec;















//
// Description : Array and textureless GLSL 2D/3D/4D simplex 
//               noise functions.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : stegu
//     Lastmod : 20110822 (ijm)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//               https://github.com/ashima/webgl-noise
//               https://github.com/stegu/webgl-noise
// 

vec4 mod289(vec4 x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0; }

float mod289x(float x) {
  return x - floor(x * (1.0 / 289.0)) * 289.0; }

vec4 permutex(vec4 x) {
     return mod289(((x*34.0)+10.0)*x);
}

float permutex(float x) {
     return mod289x(((x*34.0)+10.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

float taylorInvSqrtx(float r)
{
  return 1.79284291400159 - 0.85373472095314 * r;
}

vec4 grad4(float j, vec4 ip)
  {
  const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
  vec4 p,s;

  p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
  p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
  s = vec4(lessThan(p, vec4(0.0)));
  p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; 

  return p;
  }
						
// (sqrt(5) - 1)/4 = F4, used once below
#define F4 0.309016994374947451

float snoise(vec4 v)
  {
  const vec4  C = vec4( 0.138196601125011,  // (5 - sqrt(5))/20  G4
                        0.276393202250021,  // 2 * G4
                        0.414589803375032,  // 3 * G4
                       -0.447213595499958); // -1 + 4 * G4

// First corner
  vec4 i  = floor(v + dot(v, vec4(F4)) );
  vec4 x0 = v -   i + dot(i, C.xxxx);

// Other corners

// Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI)
  vec4 i0;
  vec3 isX = step( x0.yzw, x0.xxx );
  vec3 isYZ = step( x0.zww, x0.yyz );
//  i0.x = dot( isX, vec3( 1.0 ) );
  i0.x = isX.x + isX.y + isX.z;
  i0.yzw = 1.0 - isX;
//  i0.y += dot( isYZ.xy, vec2( 1.0 ) );
  i0.y += isYZ.x + isYZ.y;
  i0.zw += 1.0 - isYZ.xy;
  i0.z += isYZ.z;
  i0.w += 1.0 - isYZ.z;

  // i0 now contains the unique values 0,1,2,3 in each channel
  vec4 i3 = clamp( i0, 0.0, 1.0 );
  vec4 i2 = clamp( i0-1.0, 0.0, 1.0 );
  vec4 i1 = clamp( i0-2.0, 0.0, 1.0 );

  //  x0 = x0 - 0.0 + 0.0 * C.xxxx
  //  x1 = x0 - i1  + 1.0 * C.xxxx
  //  x2 = x0 - i2  + 2.0 * C.xxxx
  //  x3 = x0 - i3  + 3.0 * C.xxxx
  //  x4 = x0 - 1.0 + 4.0 * C.xxxx
  vec4 x1 = x0 - i1 + C.xxxx;
  vec4 x2 = x0 - i2 + C.yyyy;
  vec4 x3 = x0 - i3 + C.zzzz;
  vec4 x4 = x0 + C.wwww;

// Permutations
  i = mod289(i); 
  float j0 = permutex( permutex( permutex( permutex(i.w) + i.z) + i.y) + i.x);
  vec4 j1 = permutex( permutex( permutex( permutex (
             i.w + vec4(i1.w, i2.w, i3.w, 1.0 ))
           + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ))
           + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ))
           + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ));

// Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope
// 7*7*6 = 294, which is close to the ring size 17*17 = 289.
  vec4 ip = vec4(1.0/294.0, 1.0/49.0, 1.0/7.0, 0.0) ;

  vec4 p0 = grad4(j0,   ip);
  vec4 p1 = grad4(j1.x, ip);
  vec4 p2 = grad4(j1.y, ip);
  vec4 p3 = grad4(j1.z, ip);
  vec4 p4 = grad4(j1.w, ip);

// Normalise gradients
  vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
  p0 *= norm.x;
  p1 *= norm.y;
  p2 *= norm.z;
  p3 *= norm.w;
  p4 *= taylorInvSqrtx(dot(p4,p4));

// Mix contributions from the five corners
  vec3 m0 = max(0.57 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0);
  vec2 m1 = max(0.57 - vec2(dot(x3,x3), dot(x4,x4)            ), 0.0);
  m0 = m0 * m0;
  m1 = m1 * m1;
  return 60.1 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))
               + dot(m1*m1, vec2( dot( p3, x3 ), dot( p4, x4 ) ) ) ) ;

  }








vec4 noised(vec4 pos_){
   vec4 displace1;
   vec4 displace2;
   vec4 displace3;
   vec4 displace;
   vec4 pos = pos_;
   float sc;
   pos.w=iTime;
   sc=1.0;
   displace1.x=snoise(pos*sc);
   displace1.y=snoise(pos*sc+vec4(1234));
   displace1.z=snoise(pos*sc+vec4(6345));

   pos.w=iTime/2.0;
   sc=4.0;
   displace2.x=snoise(pos*sc);
   displace2.y=snoise(pos*sc+vec4(11234));
   displace2.z=snoise(pos*sc+vec4(26345));
   pos.w=iTime/4.0;
   //sc=0.7; displace2*=snoise(pos*sc+vec4(2002))*10.0/1.3;

   sc=6.0;
   displace3.x=snoise(pos*sc);
   displace3.y=snoise(pos*sc+vec4(31234));
   displace3.z=snoise(pos*sc+vec4(46345));

   displace=displace1/2.0+displace2/2.0+displace3/4.0/1.5;
   displace/=20.0/0.6/1.1/1.21;
   sc=0.7;
   //displace*=snoise(pos*sc+vec4(2002))*10.0/testvalue;
   return pos+displace/5.4/2.3/1.5;
}











void main(void)
{
vec4 vP;
vec4 vN;
vec4 vT;
vec4 vPa[4];
vec4 vNa[4];
vec4 vTa[4];
	
	
	
	vP=vec4(vertexPosition.xyz, 1.0);
	vN=vec4(vertexNormal.xyz, 1.0);
	vT=vec4(vertexTangent.xyz, 1.0);

    vP=noised(vP);

    ///originalV=vertexPosition.xyz;
    originalV=vertexOriginalPosition;

vN_=vN;
vP_=vP;


	if (hasAnim[0]>0){
        if (vertexBones.x>=0){

            vPa[0]=vP;
            vPa[0].x-=bonePos[int(vertexBones.x)][0][3];
            vPa[0].y-=bonePos[int(vertexBones.x)][1][3];
            vPa[0].z-=bonePos[int(vertexBones.x)][2][3];
            vPa[0]=boneRot[int(vertexBones.x)]*vPa[0];
            vPa[0].x+=bonePos[int(vertexBones.x)][0][3];
            vPa[0].y+=bonePos[int(vertexBones.x)][1][3];
            vPa[0].z+=bonePos[int(vertexBones.x)][2][3];
            vPa[0].x+=boneRPos[int(vertexBones.x)][0][3];vPa[0].y+=boneRPos[int(vertexBones.x)][1][3];vPa[0].z+=boneRPos[int(vertexBones.x)][2][3];

            vNa[0]=vN;
            vNa[0]=boneRot[int(vertexBones.x)]*vNa[0];
            
            

            vTa[0]=vT;
            vTa[0]=boneRot[int(vertexBones.x)]*vTa[0];
            
            


            
            
            
        }
        if (vertexBones.y>=0){
            
            
            vPa[1]=vP;
            vPa[1].x-=bonePos[int(vertexBones.y)][0][3];
            vPa[1].y-=bonePos[int(vertexBones.y)][1][3];
            vPa[1].z-=bonePos[int(vertexBones.y)][2][3];
            vPa[1]=boneRot[int(vertexBones.y)]*vPa[1];
            vPa[1].x+=bonePos[int(vertexBones.y)][0][3];
            vPa[1].y+=bonePos[int(vertexBones.y)][1][3];
            vPa[1].z+=bonePos[int(vertexBones.y)][2][3];
            vPa[1].x+=boneRPos[int(vertexBones.y)][0][3]; vPa[1].y+=boneRPos[int(vertexBones.y)][1][3]; vPa[1].z+=boneRPos[int(vertexBones.y)][2][3];

            vNa[1]=vN;
            vNa[1]=boneRot[int(vertexBones.y)]*vNa[1];
            
            

            vTa[1]=vT;
            vTa[1]=boneRot[int(vertexBones.y)]*vTa[1];
            
            

        }
        if (vertexBones.z>=0){
            
            
            vPa[2]=vP;
            vPa[2].x-=bonePos[int(vertexBones.z)][0][3];
            vPa[2].y-=bonePos[int(vertexBones.z)][1][3];
            vPa[2].z-=bonePos[int(vertexBones.z)][2][3];
            vPa[2]=boneRot[int(vertexBones.z)]*vPa[2];
            vPa[2].x+=bonePos[int(vertexBones.z)][0][3];
            vPa[2].y+=bonePos[int(vertexBones.z)][1][3];
            vPa[2].z+=bonePos[int(vertexBones.z)][2][3];
            vPa[2].x+=boneRPos[int(vertexBones.z)][0][3];vPa[2].y+=boneRPos[int(vertexBones.z)][1][3];vPa[2].z+=boneRPos[int(vertexBones.z)][2][3];

            vNa[2]=vN;
            vNa[2]=boneRot[int(vertexBones.z)]*vNa[2];
            
            

            vTa[2]=vT;
            vTa[2]=boneRot[int(vertexBones.z)]*vTa[2];
            
            
        }
        if (vertexBones.w>=0){
            
            
            vPa[3]=vP;
            vPa[3].x-=bonePos[int(vertexBones.w)][0][3];
            vPa[3].y-=bonePos[int(vertexBones.w)][1][3];
            vPa[3].z-=bonePos[int(vertexBones.w)][2][3];
            vPa[3]=boneRot[int(vertexBones.w)]*vPa[3];
            vPa[3].x+=bonePos[int(vertexBones.w)][0][3];
            vPa[3].y+=bonePos[int(vertexBones.w)][1][3];
            vPa[3].z+=bonePos[int(vertexBones.w)][2][3];
            vPa[3].x+=boneRPos[int(vertexBones.w)][0][3];vPa[3].y+=boneRPos[int(vertexBones.w)][1][3]; vPa[3].z+=boneRPos[int(vertexBones.w)][2][3];

            vNa[3]=vN;
            vNa[3]=boneRot[int(vertexBones.w)]*vNa[3];
            
            

            vTa[3]=vT;
            vTa[3]=boneRot[int(vertexBones.w)]*vTa[3];
            
            
        }

        vP=vPa[0]*vertexWeights.x+vPa[1]*vertexWeights.y+vPa[2]*vertexWeights.z+vPa[3]*vertexWeights.w;
        vN=vNa[0]*vertexWeights.x+vNa[1]*vertexWeights.y+vNa[2]*vertexWeights.z+vNa[3]*vertexWeights.w;
        vN=vec4(vN.xyz, 1.0);
        vT=vTa[0]*vertexWeights.x+vTa[1]*vertexWeights.y+vTa[2]*vertexWeights.z+vTa[3]*vertexWeights.w;
        vT=vec4(vT.xyz, 1.0);
	}

    
    gl_Position = ModelViewProjectionMatrix * vec4(vP.xyz, 1.0f); 

    


 




vpos=ModelViewMatrix * vec4(vP.xyz, 1.0f);


for (int i=0;i<NUMLIGHTS;i++){
    ShadowCoord[i] = depthBiasMVP[i] * vec4(vP.xyz, 1.0f);
}

    texCoord = textureCoord;

	
	vec3 n = normalize(NormalMatrix * vec3(vN.x,vN.y,vN.z));
	vec3 t = normalize(NormalMatrix * vec3(vT.x,vT.y,vT.z));
	
	
	
	


	vec3 b = cross(n, t) * vertexTangentHandedness;
    
	
	

	
	vec3 vVertex = vec3(ModelViewMatrix * vec4(vP.xyz, 1.0));

    
    
    

    
for (int i=0;i<NUMLIGHTS;i++){
    ShadowAngle[i] = dot(normalize(vec3(Lights[i].xyz)),n);
}

for (int i=0; i<2; i++)
   {
	//if (lightsEnabled[i]>0.0)
	{
    //float x=0,y=0,z=0;
    //tmpVec = vec3(x,y,z) - vVertex;
    tmpVec = vec3(lightsPosx[i],lightsPosy[i],lightsPosz[i]) - vVertex;
	alightVec[i].x = dot(tmpVec, t);
	alightVec[i].y = dot(tmpVec, b);
	alightVec[i].z = dot(tmpVec, n);
    //values[i]=vec3(x,y,z);
    /*
	tmpVec = -vVertex;
	aeyeVec[i].x = dot(tmpVec, t);
	aeyeVec[i].y = dot(tmpVec, b);
	aeyeVec[i].z = dot(tmpVec, n);
    */
	}
   }
   
for (int i=0; i<1; i++) //100 /// removed beacuse ssbo stuff is not working at all and alightVec is calculated in fragment shader
   {
	//if (lightsEnabled[i]>0.0)
	{
    uint x1 = uint(texture(normalMap,vec2(float(i*18+0)*(1.0/2048.0),0.0)).r*255.0);
    uint x2 = uint(texture(normalMap,vec2(float(i*18+1)*(1.0/2048.0),0.0)).r*255.0);
    uint x3 = uint(texture(normalMap,vec2(float(i*18+2)*(1.0/2048.0),0.0)).r*255.0);
    uint x4 = uint(texture(normalMap,vec2(float(i*18+3)*(1.0/2048.0),0.0)).r*255.0);
    uint y1 = uint(texture(normalMap,vec2(float(i*18+4)*(1.0/2048.0),0.0)).r*255.0);
    uint y2 = uint(texture(normalMap,vec2(float(i*18+5)*(1.0/2048.0),0.0)).r*255.0);
    uint y3 = uint(texture(normalMap,vec2(float(i*18+6)*(1.0/2048.0),0.0)).r*255.0);
    uint y4 = uint(texture(normalMap,vec2(float(i*18+7)*(1.0/2048.0),0.0)).r*255.0);
    uint z1 = uint(texture(normalMap,vec2(float(i*18+8)*(1.0/2048.0),0.0)).r*255.0);
    uint z2 = uint(texture(normalMap,vec2(float(i*18+9)*(1.0/2048.0),0.0)).r*255.0);
    uint z3 = uint(texture(normalMap,vec2(float(i*18+10)*(1.0/2048.0),0.0)).r*255.0);
    uint z4 = uint(texture(normalMap,vec2(float(i*18+11)*(1.0/2048.0),0.0)).r*255.0);
    uint intx = (x1 << 24) | (x2 << 16) | (x3 << 8) | x4;
    float x = uintBitsToFloat(intx);
    uint inty = (y1 << 24) | (y2 << 16) | (y3 << 8) | y4;
    float y = uintBitsToFloat(inty);
    uint intz = (z1 << 24) | (z2 << 16) | (z3 << 8) | z4;
    float z = uintBitsToFloat(intz);
    //float x=0,y=0,z=0;
    //tmpVec = vec3(lightsPosx[i],lightsPosy[i],lightsPosz[i]) - vVertex;
    tmpVec = vec3(x,y,z) - vVertex;
    vec3 alightVec_;
	alightVec_.x = dot(tmpVec, t);
	alightVec_.y = dot(tmpVec, b);
	alightVec_.z = dot(tmpVec, n);
    values[i]=alightVec_;//vec3(x,y,z);
	}
   }
   
   
    v=vVertex;
    N=normalize(n);
    T=normalize(t);
    B=normalize(b);
}
