
// Uniform variables for texturing
uniform sampler2D 	aaa_tex2d[4];


// Size of Texture for each texture unit
uniform vec2		aaa_tex_size[];

// 0 = time
// 1 = mouse X
// 2 = mouse Y
// 3 = line weight
uniform float		aaa_fu_float[8];

// 0 = iterations
uniform int			aaa_fu_int[4];


// balance between texture and effect
uniform float		aaa_fu_src;
uniform float		aaa_fu_out;


// Colors factors
// 0 = src colors
// 1 = out color
uniform vec4		aaa_fu_vec4[8];

const float iPow = 3.0;


vec4 dnoise(vec3 p);

vec4 quat_rotation( float half_angr, vec3 unitVec );

vec2 screen_uv;
vec4 quat;

float Checker2(vec2 uv)
{
	float s = sin(uv.x)*cos(uv.y);
	s = pow( s, iPow );
	return s;
}

vec4 FlowNoise(vec3 uvw, vec2 uv)
{
	vec4 n = vec4(0.);

	float f = 1.;
	float a = 1.;

	float lac = 2.13;


	for (int i=0; i<5; i++)
	{
		//offsetting swirl angle relative to position seems to flow along the gradient
		float ang = aaa_fu_float[0]*.4;//+uv.y*0.5;

		ang *= Checker2(uvw.xy*0.0125);

		vec3 ax = normalize(vec3(1,1,1));
		quat = quat_rotation( ang*2.*f, normalize(ax) );

		float e = 0.1;//*f;

		//advect by going back in domain along noise gradient
		vec4 dn = dnoise(uvw);
		uvw -= 0.01*dn.xyz;

		n += abs(a*dn);
		uvw *= lac;
		f *= lac;
		a *= (1./lac);
	}

	return n;
}


vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}


// Smooth HSV to RGB conversion
vec3 hsv2rgb_smooth( in vec3 c )
{
    vec3 rgb = clamp( abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 );

	// cubic smoothing
	rgb = rgb*rgb*(3.0-2.0*rgb);

	return c.z * mix( vec3(1.0), rgb, c.y);
}


vec3 hsv2rgb_trigonometric( in vec3 c )
{
    vec3 rgb = 0.5 + 0.5*cos((c.x*6.0+vec3(0.0,4.0,2.0))*3.14159/3.0);

	return c.z * mix( vec3(1.0), rgb, c.y);
}


vec4 quat_rotation( float half_angr, vec3 unitVec )
{
    float s, c;
    s = sin( half_angr );
    c = cos( half_angr );
    return vec4( unitVec*s, c );
}



/* skew constants for 3d simplex functions */
const float F3 =  0.3333333;
const float G3 =  0.1666667;

vec4 dnoise(vec3 p)
{
	 /* 1. find current tetrahedron T and its four vertices */
	 /* s, s+i1, s+i2, s+1.0 - absolute skewed (integer) coordinates of T vertices */
	 /* x, x1, x2, x3 - unskewed coordinates of p relative to each of T vertices*/
	
	 vec3 s = floor(p + (p.x+p.y+p.z)*F3);
	 vec3 x = p - s + (s.x+s.y+s.z)*G3;
	
	 vec3 e = step(vec3(0.0), x - x.yzx);
	 vec3 i1 = e*(1.0 - e.zxy);
	 vec3 i2 = 1.0 - e.zxy*(1.0 - e);
	
	 vec3 x1 = x - i1 + G3;
	 vec3 x2 = x - i2 + 2.0*G3;
	 vec3 x3 = x - 1.0 + 3.0*G3;
	 		
	 /* calculate surflet weights */
	 vec4 w;
	 w.x = dot(x, x);
	 w.y = dot(x1, x1);
	 w.z = dot(x2, x2);
	 w.w = dot(x3, x3);
	
	 /* w fades from 0.6 at the center of the surflet to 0.0 at the margin */
	 w = max(0.6 - w, 0.0);		//aka t0,t1,t2,t3
	 vec4 w2 = w*w;				//aka t20,t21,t22,t23
	 vec4 w4 = w2*w2;			//aka t40,t41,t42,t43
	
	 /* 2. find four surflets and store them in d */
	 vec3 g0 = random3(s);
	 vec3 g1 = random3(s + i1);
	 vec3 g2 = random3(s + i2);
	 vec3 g3 = random3(s + 1.0);
	
	 vec4 d;
	 /* calculate surflet components */
	 d.x = dot(g0, x);		//aka graddotp3( gx0, gy0, gz0, x0, y0, z0 )
	 d.y = dot(g1, x1);
	 d.z = dot(g2, x2);
	 d.w = dot(g3, x3);
	
	 //derivatives as per
	 vec4 w3 = w*w2;
	 vec4 temp = w3*d;
	 vec3 dnoise = temp[0]*x;
	     dnoise += temp[1]*x1;
	     dnoise += temp[2]*x2;
		 dnoise += temp[3]*x3;
		 dnoise *= -8.;
		 dnoise += w4[0]*g0+w4[1]*g1+w4[2]*g2+w4[3]*g3;
		 dnoise *= 52.; //???
		
	 d *= w4;	//aka n0,n1,n2,n3
	
	float n = (d.x+d.y+d.z+d.w)*52.;

	return vec4(dnoise,n);
}

void main(void)
{
	vec2 uv = gl_TexCoord[0].st;

	uv.x *= aaa_tex_size[0].x/aaa_tex_size[0].y;
	uv.y = 1. - uv.y;
	screen_uv = uv;

	float t = aaa_fu_float[0]*0.8;
	vec3 uvw = vec3(uv*1.15+vec2(0.,t),t*0.5);


	vec4 d = FlowNoise(uvw,uv);
	float de = d.w;
	de = length(d.xyz)*.15+.2-d.w*.2;

	gl_FragColor = vec4(de, de, de,1.0);
}