
/*
MS=maxsteps
ST=step
TH=threshold
s=stepcount
t=time
fq=frequency
p1-p3=parametrit
b=brightness
zp=zposition
w=white
k=kaavan arvo
n=normaali
tx=texturemappi
d=diffuse
nd=negatiivinen diffuse (vastavalo)
hl=highlight
*/

/*
2223 :: < kurli> kameraa sit liikutellaan ihan modelview-matriisilla
2224 :: < kurli> lookat ei toiminu ku siitä pitäs ottaa oikeestaan inversematriisi mut se maksaa liikaa bytejä, joten tos on vaan normaalit rotatet ja translatet käytös
*/


#version 120


#define FOG
//#define MEDIAN
//#define PINGPONG
//#define PINGPONG_SIN

varying vec3 p, e;
const float MS  =  90.0;
const float ST  =  0.0075*3.5, TH  =  6.0;
const float NDIST = 1.0/128.0;

uniform float t,fq,p1,p2,p3,p4,b,zp,w;
uniform vec3 lp;
uniform sampler3D tex;
uniform sampler2D tex2;
uniform float texmix;
uniform int textype;
uniform float texinc;

const float PI = 3.14159265358979;
const float PI2 = 3.14159265358979*0.5;


float saw(float a) {
	return abs(mod(a, 2.0)-1.0);
}

vec4 K(in vec3 p) {
/*	p.x += p1*0.01*sin(16.0*(t*0.1415+p.y*PI2+p.z*PI2));
	p.y += p1*0.01*sin(16.0*(t*0.2415+p.x*PI2+p.z*PI));
	p.z += p1*0.01*sin(16.0*(t*0.3415+p.x*PI+p.y*PI));*/

/*	vec3 op = p;
	p.x += floor(op.z)*0.5;
	p.y += floor(op.z)*0.5;*/

	vec3 op = p;

	float p1val = p1*0.00625*sin(p.x*126.0+t*12.77+sin(p.x*75.0+t*6.3))*cos(p.y*64.0+sin(t*5.8)+t*7.5+sin(p.z*84.0+p.y*54.0+t*3.0))*sin(p.z*77.0)*4.0;
	p.y += p1val;
	p.z -= p1val*0.5;

//	p.z += p1*0.25*sin(p.x*43.0+t*11.1+sin(p.x*31.7 +t*7.85));

	float ball = p2*sin(p.x*160.0) + abs(p3*sin(t+p.x*160.0)) /*+ (p4*sin(t+(p.y+p.z)*80.0))*/ +
	             p2*sin(p.y*160.0) + abs(p3*sin(t+p.y*160.0)) /*+ (p4*sin(t+(p.x+p.z)*80.0))*/ +
	             p2*sin(p.z*160.0) + abs(p3*sin(t+p.z*160.0)) /*+ (p4*sin(t+(p.x+p.y)*80.0))*/;


	p.xyz += abs(p4*0.01*vec3(sin((p.y+p.z)*80.0), sin((p.x+p.z)*80.0), sin((p.x+p.y)*80.0)));

	p.xyz += vec3(p3*(sin(t+(p.x*p.y)+sin(t*1.3+(p.y*p.z)+sin(t*1.6+(p.y*p.x))))));

#ifdef MEDIAN
	vec3 r1 = texture3D(tex, vec3(p+vec3(0.0, 0.0, texinc)).xyz).rgb;
	vec3 r2 = texture3D(tex, vec3(p+vec3(0.0, 0.0, texinc)).yzx).rgb;
	vec3 r3 = texture3D(tex, vec3(p+vec3(0.0, 0.0, texinc)).zxy).rgb;
	float v1 = max(r1.r, max(r1.g, r1.b));
	float v2 = max(r2.r, max(r2.g, r2.b));
	float v3 = max(r3.r, max(r3.g, r3.b));
	float val = max(min(max(v1,v2), v3), min(v1,v2));
	vec3 rgb = r1;
	float val = max(rgb.r, max(rgb.g, rgb.b));
#else
	#ifdef PINGPONG
		vec3 rp = p;
		rp = abs(mod(rp, 2.0)-1.0);
		rp += vec3(0.0, 0.0, texinc);
		vec3 rgb = texture3D(tex, rp).rgb;
	#elif defined PINGPONG_SIN
		vec3 rp = p;
//		rp = abs(mod(rp, 2.0)-1.0);
		rp = 0.5-cos(rp*2.0*3.14159)*0.4;
		rp += vec3(0.0, 0.0, texinc);
		vec3 rgb = texture3D(tex, rp).rgb;
	#else
		vec3 rgb = texture3D(tex, p+vec3(0.0, 0.0, texinc)).rgb;
	#endif
	float val = max(rgb.r, max(rgb.g, rgb.b));
#endif

	float d = TH*1.5*val;
	float dmul = d;//(d-0.5)*abs(d-0.5);
	d += ball*dmul;
	return vec4(1.5*rgb, d);

}

vec3 N(in vec3 p, in float val) {
	vec3 n = vec3(
		K(vec3(p.x-NDIST,p.y,p.z)).a - K(vec3(p.x+NDIST,p.y,p.z)).a,
		K(vec3(p.x,p.y-NDIST,p.z)).a - K(vec3(p.x,p.y+NDIST,p.z)).a,
		K(vec3(p.x,p.y,p.z-NDIST)).a - K(vec3(p.x,p.y,p.z+NDIST)).a);
	return normalize(n);
}

void main(void) {
	vec3 pos = vec3(0.0);
	vec3 dir = normalize(p-e)*ST;
	vec4 k = vec4(0.0);
	float s = 2.0;
	vec3 n;
	vec4 hl,d,nd;

#ifdef FOG
	float step = s*0.25;
	vec4 color = vec4(0.0, 0.0, 0.0, 1.0);
	vec4 fog = vec4(0.0, 0.0, 0.0, 1.0);
	float counter;
	for (; s < MS;) {
		pos = e+dir*s;
		color += mix(vec4(max(K(pos).rgb, 0.0), 0.0), fog, clamp(1.0-(MS-s)/MS, 0.0, 1.0));
		counter += 1.5;
		s += step;
		step = min(step*1.03, 2.0);
	}
	counter /= texmix;
	gl_FragColor = color/vec4(counter, counter, counter, 1.0);
#else
	for (; s < MS; ) {
		pos = e+dir*s;
		k = K(pos);
		if (k.a > TH) break;
		s = s+clamp((TH-k.a)*0.20, 0.15, 5.0);
	}

	if (s < MS)
		for (int i = 0; i<9; i++){
			dir = dir*0.5;
			if (k.a > TH) pos = pos-dir;
			else pos = pos+dir;
			k = K(pos);
		}

//	vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
	vec4 color = vec4(k.rgb, 1.0);
	vec4 hlColor = vec4(1.0, 1.0, 1.0, 1.0);
	vec4 fog = vec4(0.0, 0.0, 0.0, 1.0);

	vec3 olp = normalize(dir*lp);

	vec2 tc = vec2(-pos.x, pos.z);
	if (textype == 1) tc = vec2(-pos.x, pos.y);
	if (textype == 2) tc = vec2(pos.z, pos.y);
	if (textype == 3) tc = vec2(-pos.y, pos.x);
	if (textype == 4) tc = vec2(pos.y, pos.z);
	color = vec4(1.0,1.0,1.0,1.0);
//	color = mix(color, texture2D(tex2, tc), clamp(texmix, 0.0, 1.0));

	dir = p-e;
	n = N(pos, k.a);
	hl = vec4(clamp(dot(reflect(normalize(dir), n), olp), 0.0, 1.0));
	hl = hl*hl*hl*hl*hl*hl*color;
/*	tx = sin(pos.z*4.3+n.z*4.0+t*37.3-sin(pos.x*23.4+n.x*4.0-t*21.4))*
		 sin(pos.x*5.2+n.x*4.0-t*28.1+sin(pos.z*21.4+n.z*4.0-t*17.2))*0.5+0.5;
	tx = tx*tx*tx*p3;*/
	nd = clamp(dot(n,-olp),0.0,1.0)*vec4(vec4(1.0)-hlColor);
	d = clamp(dot(n,olp), 0.0, 1.0)*color/**tx*/+nd*nd;

	vec4 lightCol = vec4(mix(hl+d, fog, clamp(1.0-(MS-s)/MS, 0.0, 1.0))*b+vec4(w));

//	gl_FragColor = mix(clamp(k,0.0,1.0)*color, lightCol, lightmix);
//	gl_FragColor = clamp(k, 0.0, 1.0)*vec4(color, 1.0);
	gl_FragColor = clamp(k.a, 0.0, 1.0)*vec4(color)*lightCol;
#endif

}

