#version 130

#define lc 4
varying vec4 diffuse[lc], pos, spos;//, ambient;//, col;
varying vec3 lightDir[lc]/*halfVector[lc], */;
//varying vec3 lightDir[lc]/*halfVector[lc], */;
varying vec3 normal, srcn;
varying float fogCoord, alpha;

uniform int lightsCount;
uniform bool acc_light, acc_fog, has_diffuse, has_bump, is_glass, shadows, soft_shadows;
uniform float bump_scale, reflectivity, iof, cdis;
uniform vec2 vsize;
uniform sampler2D t0, t1, t2;
uniform sampler2D s0;
uniform samplerCube tc, tc0;
uniform mat4 mat;

float light_diffuse(vec3 l, vec3 n, vec3 h, vec3 v, float shininess);
float light_specular(vec3 l, vec3 n, vec3 h, vec3 v, float shininess);

const float bias = 1.;
vec2 sp;
vec4 sc, dc;//ambient;

void calcLight(in int index, in vec3 n, in vec3 v) {
	vec2 scoord, sdt, sdt2;
	vec3 halfV, ldir;
	vec4 lpos = gl_LightSource[index].position;
	float spot, ldist = length(lpos.xyz - pos.xyz), shadow = 1., sdep, ddep;
	ldir = normalize(lpos.xyz - (pos.xyz * lpos.w));
	halfV = normalize(ldir + v);
	//if (dot(ldir, n) > 0) {
		spot = step(0., dot(ldir, n));
		if (gl_LightSource[index].spotCutoff < 180.) {
			spot = max(dot(-ldir, gl_LightSource[index].spotDirection.xyz), 0.);
			spot *= step(gl_LightSource[index].spotExponent, spot);
			spot = pow(spot, (gl_LightSource[index].spotCosCutoff + 0.001));
			if (spot > 0. && shadows) {
				scoord = (spos.xyz / spos.w).xy / 2 + vec2(0.5);
				sdep = texture(s0, scoord.xy).r + bias;
				ddep = pow((spos.z - sdep) / 4., 0.5) * 2.;
				shadow = clamp(sdep - spos.z, 0., 1.);
				if (soft_shadows) {
					sdt = ddep / vsize;
					sdt2 = sdt + sdt;
					shadow += (clamp(texture(s0, scoord.xy + vec2(sdt.x, 0.)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(0, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, 0.)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(0, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, 0)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(0, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, 0)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(0, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt2.x, 0)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(0, sdt2.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt2.x, 0)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(0, -sdt2.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt2.x, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt2.x, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt2.x, -sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt2.x, sdt.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, sdt2.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(sdt.x, -sdt2.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, -sdt2.y)).r + bias - spos.z, 0., 1.) +
							clamp(texture(s0, scoord.xy + vec2(-sdt.x, sdt2.y)).r + bias - spos.z, 0., 1.)) / 29.;
					shadow = clamp(pow(shadow, 0.5), 0., 1);
				}
				spot *= shadow;
			}
		}
		spot /= (gl_LightSource[index].constantAttenuation + ldist * (gl_LightSource[index].linearAttenuation + ldist * gl_LightSource[index].quadraticAttenuation));
		dc += spot * diffuse[index] * light_diffuse(ldir, n, halfV, v, gl_FrontMaterial.shininess);
		sc += spot * gl_FrontMaterial.specular * gl_LightSource[index].specular * light_specular(ldir, n, halfV, v, gl_FrontMaterial.shininess);
	//}
}

void main(void) {
	/*vec3 scoord = spos.xyz / spos.w;
	float sdep = texture(s0, scoord.xy / 2 + vec2(0.5)).r + 1;
	//gl_FragColor.rgb = vec3(step(spos.z, sdep));
	gl_FragColor.rgb = vec3(spos.z - sdep)/10;
	//gl_FragColor.rgb = vec3(texture(s0, scoord.xy+vec2(0.5)).r/100);
	//gl_FragColor.rgb = vec3(texture(s0,).r/100);
	return;*/
	//bias = (vsize.x - vsize.y) / max(vsize.x, vsize.y)*5 - 1.;

	if (!acc_light) {
		if (has_diffuse) gl_FragColor = texture2D(t0, gl_TexCoord[0].xy);
		//else gl_FragColor = gl_Color;
		if (acc_fog)
			gl_FragColor.xyz = mix(gl_FragColor.xyz, gl_Fog.color.xyz, fogCoord);
		return;
	}

	sp = gl_FragCoord.xy / vsize;
	vec3 n, v = normalize(-pos.xyz);
	//v.xy = vec2(1,1)-gl_FragCoord.xy / vsize*2 ;//- vec2(1,1);
	if (has_bump) n = normalize(normal + (texture2D(t1, gl_TexCoord[0].xy).xyz - vec3(0.5, 0.5, 1.)) * bump_scale);
	else n = normalize(normal);
	vec4 color;
	sc = vec4(0.);
	dc = gl_LightModel.ambient * gl_FrontMaterial.ambient;//ambient;
	if (lightsCount > 0) {
		calcLight(0, n, v);
		if (lightsCount > 1) {
			calcLight(1, n, v);
			if (lightsCount > 2) {
				calcLight(2, n, v);
				if (lightsCount > 3) {
					calcLight(3, n, v);
					/*if (lightsCount > 4) {
						calcLight(4, n, v);
						if (lightsCount > 5) {
							calcLight(5, n, v);
							if (lightsCount > 6) {
								calcLight(6, n, v);
								if (lightsCount > 7) {
									calcLight(7, n, v);
								}
							}
						}
					}*/
				}
			}
		}
	}
	sc = max(sc, vec4(0.));
	vec2 spr = sp, spg = sp, spb = sp, spc = sp, spm = sp, spy = sp, dsp;
	vec3 bgf;
	float fresnel = pow(1. - max(dot(v, n), 0.), 1);
	dsp = fresnel * n.xy * (1. - iof);
	spg += dsp;
	if (cdis > 0.) {
		spr += dsp * (1. - cdis - cdis);
		spy += dsp * (1. - cdis);
		spc += dsp * (1. + cdis);
		spb += dsp * (1. + cdis + cdis);
		vec3 bg0 = texture2D(t2, spr).rgb, bg1 = texture2D(t2, spy).rgb, bg2 = texture2D(t2, spg).rgb, bg3 = texture2D(t2, spc).rgb, bg4 = texture2D(t2, spb).rgb;
		//bgf = vec3(bg0.r, bg2.g, bg4.b);
		bgf = vec3((bg0.r + bg1.r) / 2., (bg1.g + bg2.g + bg3.g) / 3., (bg3.b + bg4.b) / 2.);
	} else bgf = texture2D(t2, spg).rgb;
	if (has_diffuse) {
		vec4 tex = texture2D(t0, gl_TexCoord[0].xy);
		dc *= tex;
		color.a = tex.a * alpha;
	} else color.a = alpha;
	color.rgb = dc.rgb;
	vec3 ln = vec3(0);
	if (is_glass) {
		ln = reflect(v, n);
		ln = ln * mat3(gl_ModelViewMatrix);
		ln.y = -ln.y;
		color.rgb = (mix(bgf, textureCube(tc, ln).rgb, 0.2 + fresnel * 0.8) * gl_FrontMaterial.diffuse.rgb + gl_FrontMaterial.emission.rgb) + sc.rgb * color.a;
		color.a = 1.;
	} else {
		if (reflectivity > 0.) {
			ln = reflect(v, n);
			ln = ln * mat3(gl_ModelViewMatrix);
			ln.y = -ln.y;
			color.rgb = mix(color.rgb, textureCube(tc, ln).rgb, reflectivity);
		}
		color.rgb = mix(color.rgb * gl_FrontMaterial.diffuse.rgb + gl_FrontMaterial.emission.rgb, bgf, 1. - alpha) + sc.rgb * color.a;
		color.a = 1;
	}
	if (acc_fog)
		color.rgb = mix(color.rgb, gl_Fog.color.rgb, fogCoord);
		color.r = 250;
	gl_FragColor = color;
	//gl_FragColor.rgb = mix(ldir, texture2D(t2, sp).rgb, 1. - alpha);
}
