#version 120

// Description : Array and textureless GLSL 2D/3D/4D simplex 
//               noise functions.
//      Author : Ian McEwan, Ashima Arts.
//  Maintainer : ijm
//     Lastmod : 20110223(ijm), 20110316(stegu)
//     License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//              Distributed under the Artistic License 2.0; See LICENSE-ashima file.

uniform float time;       // Used for texture animation
uniform int   algorithm;  // Used for selection of simplex noise algorithm

varying vec2 v_texCoord2D;
varying vec3 v_texCoord3D;
varying vec4 v_color;


// Example constant with a 289 element permutation
const vec4 pParam = vec4( 17.0*17.0, 34.0, 1.0, 7.0);

// Permutation polynomial evaluation for 1 to 4 components in parallel
float permute(float x, vec3 p) { return floor( mod( (mod((x * p.y),( p.x)) + p.z)*x, p.x)); }
vec2  permute(vec2 x,  vec3 p) { return floor( mod( (mod((x * p.y),( p.x)) + p.z)*x, p.x)); }
vec3  permute(vec3 x,  vec3 p) { return floor( mod( (mod((x * p.y),( p.x)) + p.z)*x, p.x)); }
vec4  permute(vec4 x,  vec3 p) { return floor( mod( (mod((x * p.y),( p.x)) + p.z)*x, p.x)); }

float taylorInvSqrt(float r) { return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r ); }
vec2  taylorInvSqrt(vec2 r)  { return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r ); }
vec3  taylorInvSqrt(vec3 r)  { return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r ); }
vec4  taylorInvSqrt(vec4 r)  { return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r ); }


//
// 2-dimensional simplex noise
//
float simplexNoise(vec2 v)
{
  const vec2 C = vec2(0.211324865405187134, // (3.0-sqrt(3.0))/6.0;
                      0.366025403784438597); // 0.5*(sqrt(3.0)-1.0);
  const vec3 D = vec3( 0.0, 0.5, 2.0) * 3.14159265358979312;
  // First corner
  vec2 i  = floor(v + dot(v, C.yy) );
  vec2 x0 = v -   i + dot(i, C.xx);

  // Other corners
  vec2 i1;
  i1.x = float( (x0.x>x0.y) );
  i1.y = 1.0 - i1.x;

  vec4 xC = x0.xyxy + vec4( C.xx, -1.0 + 2.0 * C.xx);
  xC.xy -= i1;

  // Permutations
  i = mod(i, pParam.x);
  vec3 p = permute( permute( 
             i.y + vec3(0.0, i1.y, 1.0 ), pParam.xyz)
           + i.x + vec3(0.0, i1.x, 1.0 ), pParam.xyz);

  vec3 m = max(0.5 - vec3(dot(x0,x0), dot(xC.xy,xC.xy), dot(xC.zw,xC.zw)), 0.0);
  m = m*m ;
  m = m*m ;
  // ( N points uniformly over a line, mapped onto a diamond.)
  vec3 x = 2.0 * fract(p / pParam.w) - 1.0 ;
  vec3 h = abs(x) - 0.5 ;

  vec3 ox = floor(x+0.5);

  vec3 a0 = x - ox;

  m *= taylorInvSqrt( a0*a0 + h*h );

  vec3 g;
  g.x  = a0.x  * x0.x  + h.x  * x0.y;
  g.yz = a0.yz * xC.xz + h.yz * xC.yw;

  return 160.0 * dot(m, g);
}

//
// 3-dimensional simplex noise
//
float simplexNoise(vec3 v)
{ 
  const vec2  C = vec2(1.0/6.0, 1.0/3.0 ) ;
  const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);

  // First corner
  vec3 i  = floor(v + dot(v, C.yyy) );
  vec3 x0 =   v - i + dot(i, C.xxx) ;

  // Other corners
  vec3 g = vec3( greaterThan(   x0.xyz, x0.yzx) );
  vec3 l = 1.0 - g;
  vec3 i1 = min( g.xyz, l.zxy );
  vec3 i2 = max( g.xyz, l.zxy );

  vec3 x1 = x0 - i1 + 1.0 * C.xxx;
  vec3 x2 = x0 - i2 + 2.0 * C.xxx;
  vec3 x3 = x0 - 1. + 3.0 * C.xxx;

  // Permutations
  i = mod(i, pParam.x ); 
  vec4 p = permute( permute( permute( 
             i.z + vec4(0.0, i1.z, i2.z, 1.0 ), pParam.xyz)
           + i.y + vec4(0.0, i1.y, i2.y, 1.0 ), pParam.xyz) 
           + i.x + vec4(0.0, i1.x, i2.x, 1.0 ), pParam.xyz);

  // Gradients
  // ( N*N points uniformly over a square, mapped onto a octohedron.)
  float n_ = 1.0/pParam.w ;
  vec3  ns = n_ * D.wyz - D.xzx ;

  vec4 j = p - pParam.w*pParam.w*floor(p * ns.z *ns.z);  //  mod(p,N*N)

  vec4 x_ = floor(j * ns.z)  ;
  vec4 y_ = floor(j - pParam.w * x_ ) ;    // mod(j,N)

  vec4 x = x_ *ns.x + ns.yyyy;
  vec4 y = y_ *ns.x + ns.yyyy;
  vec4 h = 1.0 - abs(x) - abs(y);

  vec4 b0 = vec4( x.xy, y.xy );
  vec4 b1 = vec4( x.zw, y.zw );

  vec4 s0 = floor(b0) *2.0 +1.0;
  vec4 s1 = floor(b1) *2.0 +1.0;
  vec4 sh = -vec4(lessThan(h, D.xxxx));

  vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
  vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;

  vec3 p0 = vec3(a0.xy,h.x);
  vec3 p1 = vec3(a0.zw,h.y);
  vec3 p2 = vec3(a1.xy,h.z);
  vec3 p3 = vec3(a1.zw,h.w);

  p0 *= taylorInvSqrt(dot(p0,p0));
  p1 *= taylorInvSqrt(dot(p1,p1));
  p2 *= taylorInvSqrt(dot(p2,p2));
  p3 *= taylorInvSqrt(dot(p3,p3));

  // Mix
  vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.);
  m = m * m;
  return 58.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 
                                dot(p2,x2), dot(p3,x3) ) );
}

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) *pParam.w) * 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;
}

float simplexNoise(vec4 v)
{
  const vec2  C = vec2( 0.138196601125010504,  // (5 - sqrt(5))/20  G4
                        0.309016994374947451); // (sqrt(5) - 1)/4   F4
  // First corner
  vec4 i  = floor(v + dot(v, C.yyyy) );
  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 = isX.x + isX.y + isX.z;
  i0.yzw = 1.0 - isX;

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

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

  // Permutations
  i = mod(i, pParam.x); 
  float j0 = permute( permute( permute( permute (
              i.w, pParam.xyz) + i.z, pParam.xyz) 
            + i.y, pParam.xyz) + i.x, pParam.xyz);
  vec4 j1 = permute( permute( permute( permute (
             i.w + vec4(i1.w, i2.w, i3.w, 1.0 ), pParam.xyz)
           + i.z + vec4(i1.z, i2.z, i3.z, 1.0 ), pParam.xyz)
           + i.y + vec4(i1.y, i2.y, i3.y, 1.0 ), pParam.xyz)
           + i.x + vec4(i1.x, i2.x, i3.x, 1.0 ), pParam.xyz);
  // Gradients
  // ( 7*7*6 points uniformly over a cube, mapped onto a 4-octahedron.)
  // The permutation ring is 17*17, and that should be close
  // to an even multiple of the number of points to avoid
  // directional preferences for the noise field.
  // 7*7*6 = 294, which is close to 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);

  p0 *= taylorInvSqrt(dot(p0,p0));
  p1 *= taylorInvSqrt(dot(p1,p1));
  p2 *= taylorInvSqrt(dot(p2,p2));
  p3 *= taylorInvSqrt(dot(p3,p3));
  p4 *= taylorInvSqrt(dot(p4,p4));

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

}

void main( void )
{
  float n;

  if (algorithm == 2)
    n = simplexNoise(v_texCoord2D * 16.0 + vec2(0.0, time));
  else if (algorithm == 3)
    n = simplexNoise(vec3(2.0 * v_texCoord3D.xyz * (2.0 + sin(0.5 * time))));
  else if (algorithm == 4)
    n = simplexNoise(vec4(4.0 * v_texCoord3D.xyz, 0.5 * time));

  gl_FragColor = v_color * vec4(0.5 + 0.5 * vec3(n, n, n), 1.0);
}
