varying vec2 pos;
varying vec3 RayOrg;
varying vec3 RayDir;
varying vec4 light1;
varying vec4 light1_color;
varying vec4 sphere[3];

uniform float time;
uniform int ScreenWidth;
uniform int ScreenHeight;
uniform sampler2D tex0;

int RayBoxIntersection(vec3 BBMin, vec3 BBMax, vec3 RayOrg, vec3 RayDirInv, float out tmin, float out tmax, vec3 out normal)
{
	float t=-2013210;
	float l1   = (BBMin.x - RayOrg.x) * RayDirInv.x;
	float l2   = (BBMax.x - RayOrg.x) * RayDirInv.x;
	tmin = min(l1,l2);
	tmax = max(l1,l2);

	l1   = (BBMin.y - RayOrg.y) * RayDirInv.y;
	l2   = (BBMax.y - RayOrg.y) * RayDirInv.y;
	tmin = max(min(l1,l2), tmin);
	tmax = min(max(l1,l2), tmax);

	l1   = (BBMin.z - RayOrg.z) * RayDirInv.z;
	l2   = (BBMax.z - RayOrg.z) * RayDirInv.z;
	tmin = max(min(l1,l2), tmin);
	tmax = min(max(l1,l2), tmax);

	int ret = ((tmax >= tmin) && (tmax >= 0.0f));

	if (ret > 0) {
	vec3 hit = RayOrg + vec3(1,1,1)/RayDirInv*tmin;

	t=1000;
	if (t > distance(BBMin.x, hit.x)) {
		normal = vec3(-1,0,0);
		t = distance(BBMin.x, hit.x);
	}
	if (t > distance(BBMax.x, hit.x)) {
		normal = vec3(1,0,0);
		t = distance(BBMax.x, hit.x);
	}
	if (t > distance(BBMin.y, hit.y)) {
		normal = vec3(0,-1,0);
		t = distance(BBMin.y, hit.y);
	}
	if (t > distance(BBMax.y, hit.y)) {
		normal = vec3(0,1,0);
		t = distance(BBMax.y, hit.y);
	}
	if (t > distance(BBMin.z, hit.z)) {
		normal = vec3(0,0,-1);
		t = distance(BBMin.z, hit.z);
	}
	if (t > distance(BBMax.z, hit.z)) {
		normal = vec3(0,0,1);
		t = distance(BBMax.z, hit.z);
	}
	}
	return ret;
}

int BBox(vec3 BBMin, vec3 BBMax, vec3 RayOrg, vec3 RayDirInv, float out tmin, float out tmax)
{
	float l1   = (BBMin.x - RayOrg.x) * RayDirInv.x;
	float l2   = (BBMax.x - RayOrg.x) * RayDirInv.x;
	tmin = min(l1,l2);
	tmax = max(l1,l2);

	l1   = (BBMin.y - RayOrg.y) * RayDirInv.y;
	l2   = (BBMax.y - RayOrg.y) * RayDirInv.y;
	tmin = max(min(l1,l2), tmin);
	tmax = min(max(l1,l2), tmax);

	l1   = (BBMin.z - RayOrg.z) * RayDirInv.z;
	l2   = (BBMax.z - RayOrg.z) * RayDirInv.z;
	tmin = max(min(l1,l2), tmin);
	tmax = min(max(l1,l2), tmax);
	return ((tmax >= tmin) && (tmax >= 0.0f));
}

vec4 TraceRay(bool shadowTrace, bool out trace) {
	trace=false;
	vec3 col = vec3(0,0,0);
	float diffuse = 0.8;
	float specular = 0.5;
	float smin=1000000;
	vec3 normal;
	int hito = -1;


	float light_dist=0;
	if (shadowTrace) {
		light_dist = distance(light1.xyz, RayOrg);
	}

	float bmin=10000, bmax=100000;
	float tbmin, tbmax;
	vec3 box_normal;
	vec3 tbox_normal;
	int bi=0;
	int t2 = 0;
	t2 = RayBoxIntersection(vec3(-1000,-16,-1000), vec3(1000,-15,1000), RayOrg, vec3(1.0/RayDir.x, 1.0/RayDir.y, 1.0/RayDir.z), tbmin, tbmax, tbox_normal);
	if (t2 > 0 && tbmin < smin && tbmin < bmin) {
		hito = 4;
		bmin = tbmin;
		bmax = tbmax;
		box_normal=tbox_normal;
		col = vec3(0.5,0.5,0.5);
		trace=true;
		if (shadowTrace && bmin < light_dist) {
			return vec4(1,1,1,1);
		}
	}

	float mx=190;
	float my=0;
	float credwidth=32;
	float mz=mod(time, (60/130*8))*74-3800;
	float mboxsize=12.0;
	t2 = BBox(vec3(mx,my,max(mz,0)), vec3(mx-credwidth*mboxsize,my+mboxsize,max(mz+320*mboxsize,0)), RayOrg, vec3(1.0/RayDir.x, 1.0/RayDir.y, 1.0/RayDir.z), tbmin, tbmax);
	if (t2 > 0) {
	for (int ii=0;ii<10;ii++) {
		if (mz+(credwidth*(ii+1))*mboxsize > 0) {
		t2 = BBox(vec3(mx,my,mz+credwidth*ii*mboxsize), vec3(mx-credwidth*mboxsize,my+mboxsize,mz+(credwidth*(ii+1))*mboxsize), RayOrg, vec3(1.0/RayDir.x, 1.0/RayDir.y, 1.0/RayDir.z), tbmin, tbmax);
		if (t2 > 0) {
		for (float y=credwidth*ii;y<credwidth*(ii+1);y++) {
			float boxsize = mboxsize;
			if (mz+y*boxsize+boxsize > 0) {
			t2 = BBox(vec3(mx,my,mz+y*boxsize), vec3(mx-credwidth*boxsize,my+boxsize,mz+y*boxsize+boxsize), RayOrg, vec3(1.0/RayDir.x, 1.0/RayDir.y, 1.0/RayDir.z), tbmin, tbmax);
			if (t2 > 0) {
				for (float x=0;x<credwidth;x++) {
					vec2 uv = vec2(x/credwidth, y/320);
					vec3 col2 = texture2D(tex0,uv).xyz;
					if (col2.x > 0) {
						vec3 box_min = vec3(mx-x*boxsize, my, mz+y*boxsize);
						vec3 box_max = vec3(mx-x*boxsize+boxsize-(cos(time*5)*0+0), my+boxsize-(cos(time*5)*0+0), mz+y*boxsize+boxsize-(cos(time*5)*0+0));
						if (box_min.z > 0) {
						t2 = RayBoxIntersection(box_min, box_max, RayOrg, vec3(1.0/RayDir.x, 1.0/RayDir.y, 1.0/RayDir.z), tbmin, tbmax, tbox_normal);
						if (t2 > 0 && tbmin < smin && tbmin < bmin) {
							hito = 4;
							bmin = tbmin;
							bmax = tbmax;
							box_normal=tbox_normal;
							col = col2;
							trace=false;
							if (shadowTrace && bmin < light_dist) {
								return vec4(1,1,1,1);
							}
						}
						}
					}
				}
				}
			}
		}
		}
		}
	}
	}
	vec3 v0 = vec3(-40,0,0);
	vec3 v1 = vec3(-41,0,0);
	vec3 v2 = vec3(-41,1,0);
	vec3 e1 = v0-v1;
	vec3 e2 = v2-v1;

	vec2 uv;
	float t3 = 10000;
	if (hito == 4) {
		vec3 hit = RayOrg+RayDir*bmin;
		normal = box_normal;
		vec3 L = normalize(light1.xyz - hit);
		vec3 tcol = vec3(0,0,0);
		vec3 R = L - 2.0f * dot( L, normal ) * normal;
		vec3 V = RayDir;
		float dotS = dot( V, R );
		float dotD = dot( L, normal );
		if (dotD > 0) {
			tcol += dotD * col * diffuse * light1_color.xyz * light1_color.w;
		}
		if (dotS > 0) {
			float spec = pow( dotS, 20 ) * specular;
			tcol += spec*light1_color.xyz * light1_color.w;
		}
		col = tcol;
		RayOrg=RayOrg+RayDir*(bmin-0.1);
		if (trace == true) {
			RayDir = normalize(reflect(RayDir, -normal));
		}
	}

	return vec4(col,0);
}

void main()
{
	vec3 col=vec3(0,0,0);
	vec3 orgRayOrg = RayOrg;
	vec3 orgRayDir=RayDir;
	int aa = 1;
	for (int a=0;a<aa;a++) {
		RayOrg = orgRayOrg;
		RayDir = orgRayDir;
		vec4 res[4];
		int depth=0;
		bool trace=true;
		while (trace && depth < 4) {
			res[depth] = TraceRay(false, trace);
			bool st=true;
			vec3 tr = RayDir;
			vec3 tro = RayOrg;
			float s=0;
			int shadowTests=1;
			for (int i=0;i<shadowTests;i++) {
				RayDir = normalize((light1.xyz)-RayOrg);
				vec4 shadow = TraceRay(true, st);
				if (shadow.w==1) {
					s += 0.5;
				}
			}
			s /= (float)shadowTests;
			RayDir=tr;
			RayOrg=tro;
			if (s>0) {
				res[depth] *= 1-s;
			}
			depth++;
		}
		for (int c=depth-1;c>=0;c--) {
			if (depth == 10) {
				col = res[c];
			}
			else {
				col += (col*0.5+res[c]*0.5)/aa/depth;
			}
		}
	}
	gl_FragColor = vec4(col,1.0);
}

