
// 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 iIntensity = 0.4; 	// from 0.1 to 0.9;
const int iPass = 16; 			// from 5 to 100

vec2 rotate(vec2 p, float a)
{
	return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a));
}


float n3d(in vec3 x)
{
	vec3 p = floor(x);
	vec3 f = fract(x);
	f = f * f * (3.0 - 2.0 * f);
	vec2 uv = (p.xy + vec2(37.0, 17.0) * p.z) + f.xy;
	vec2 rg = texture2D(aaa_tex2d[0], (uv + 0.5) / 256.0, -100.0).yx;
	return mix(rg.x, rg.y, f.z);
}


float fbm(vec3 p, float x)
{
	vec3 pp = p;
	float t = aaa_fu_float[0];
	float ll = dot(p, p);
	p /= ll;
	p = p * (1.0 + ll * x + ll * ll * 0.01);
	float v = aaa_fu_float[0] * 0.2;
	return (n3d( p + v * vec3( 0.0,  0.0, 1.0)) * 0.5 +
		   n3d((p + v * vec3(-1.0,  0.0, 0.0)) * 2.0 + 5.0) * 0.25 +
		   n3d((p + v * vec3( 0.0, -1.0, 0.0)) * 4.0 - 5.0) * 0.125 +
		   n3d((p + v * vec3( 0.0,  1.0, 0.0)) * 8.0 + 5.0) * 0.0625) * exp(ll * -0.03);
}


float density(vec3 p, float x)
{
	return pow(1.0 - abs(fbm(p, x) * 2.0 - 1.0), 32.0);
}


void main(void)
{
	vec2 uv = gl_TexCoord[0].st;
	uv = 2.0 * uv - 1.0;
	uv.x *= aaa_tex_size[0].x / aaa_tex_size[0].y;

	vec3 ro = vec3(0.0, 0.0, -2.0 + sin(aaa_fu_float[0] * 0.4));
	vec3 rd = normalize(vec3(uv, 1.4));

	ro.xz = rotate(ro.xz, aaa_fu_float[0] * 0.2);

	rd.xz = rotate(rd.xz, aaa_fu_float[0] * 0.2);
	rd.xy = rotate(rd.xy, sin(aaa_fu_float[0] * 0.2) * 0.2);

	float a = 0.0;
	vec3 r = ro + rd * 0.01;
	float x = sin(aaa_fu_float[0] * 0.2) * 0.3 + 0.4;
	for(int i = 0; i < iPass; i ++)
	{
		a += density(r, x);
		r += rd * 4.0 / float(iPass);
	}

	float v = a * 2.0 / float(iPass);
	vec3 col = pow(vec3(v), vec3(1.0-(iIntensity*0.4)) * 5.0) * 60.0;
	col = clamp(col, vec3(0.0), vec3(1.0));
	col = pow(col, vec3(1.0 / 3.2));

	vec4 color = vec4(col, 1.0);

	vec4 src = (texture2D(aaa_tex2d[0], gl_TexCoord[0].st) * aaa_fu_src) * aaa_fu_vec4[0];
	vec4 fx  = (color * aaa_fu_out) * aaa_fu_vec4[1];

	gl_FragColor = vec4( (src + fx) );
}
