
uniform sampler2D texMap0;
uniform sampler2D texMap1;
uniform sampler2D noiseTexture;
uniform int texFlag;
uniform int cycleMode;
uniform ivec4 combineC1;
uniform ivec4 combineC2;
uniform ivec4 combineA1;
uniform ivec4 combineA2;
uniform vec4 fillColor;
uniform vec4 primColor;
uniform vec4 envColor;
uniform vec4 fogColor;
uniform float primLodFrac;

varying vec2 Texcoord0;
varying vec2 Texcoord1;

vec4 tex0Color = vec4(0.0, 0.0, 0.0, 0.0);
vec4 tex1Color = vec4(0.0, 0.0, 0.0, 0.0);
vec4 stage1Color = vec4(0.0, 0.0, 0.0, 0.0);

vec3 getColorElement(int elem)
{
	switch(elem)
	{
		case 0: // combined
			return stage1Color.xyz;
		case 1: // tex0
			return tex0Color.xyz;
		case 2: // tex1
			return tex1Color.xyz;
		case 3: // primitive
			return primColor.xyz;
		case 4: // shade
			return gl_Color.xyz;
		case 5: // enviroment
			return envColor.xyz;
		case 6: // one
			return vec3( 1.0, 1.0, 1.0);
		case 7: // combined alpha
			return stage1Color.www;
		case 8: // tex0 alpha
			return tex0Color.www;
		case 9: // tex1 alpha
			return tex1Color.www;
		case 10: // primitive alpha
			return primColor.www;
		case 11: // shade alpha
			return gl_Color.www;
		case 12: // enviroment alpha
			return envColor.www;
		case 13: // revisit
			return vec3( 1.0, 1.0, 1.0);
		case 14: // prim_lod_frac
			return vec3( primLodFrac, primLodFrac, primLodFrac);
		case 16:
			return texture2D( noiseTexture, Texcoord0).xyz;
		case 31: // zero
			return vec3( 0.0, 0.0, 0.0);
	}
	
	return vec3(0.0, 0.0, 0.0);
}

float getAlphaElement(int elem)
{
	switch(elem)
	{
		case 0: // combined
			return stage1Color[3];
		case 1: // tex0
			return tex0Color[3];
		case 2: // tex1
			return tex1Color[3];
		case 3: // primitive
			return primColor[3];
		case 4: // shade
			return gl_Color[3];
		case 5: // enviroment
			return envColor[3];
		case 6: // one
			return 1.0;
		case 7: // zero
			return 0.0;
		case 8: // special for prim_lod_frac
			return primLodFrac;
	}
	
	return 0.0;
}
vec4 invert4(vec4 v)
{
	vec4 ret = v;
	if(ret.x < 0.0)
		ret.x = 1.0 + ret.x;
	if(ret.y < 0.0)
		ret.y = 1.0 + ret.y;
	if(ret.z < 0.0)
		ret.z = 1.0 + ret.z;
	if(ret.w < 0.0)
		ret.w = 0.0;
	return ret;
}
vec3 invert3(vec3 v)
{
	vec3 ret = v;
	if(ret.x < 0.0)
	{
		ret.x = 0.0;
		ret.y = 0.0;
		ret.z = 0.0;
		return ret;
	}
	if(ret.y < 0.0)
	{
		ret.y = 0.3 + ret.y;
	}
	else
	{
		ret.x -= 0.2;
		ret.y = 0.0;
		ret.z = 0.0;
	}
//	if(ret.y < 0.0)
//		ret.y = 0.5 + ret.y;
//	if(ret.z < 0.0)
//		ret.z = 0.5 + ret.z;
	return ret;
}

vec3 clamp3(vec3 v)
{
	vec3 ret = v;
//	ret.x = clamp(ret.x, 0.0, 1.0);
//	ret.y = clamp(ret.y, 0.0, 1.0);
//	ret.z = clamp(ret.z, 0.0, 1.0);
	return ret;
}
vec4 clamp4(vec4 v)
{
	vec4 ret = v;
	ret.x = clamp(ret.x, 0.0, 1.0);
	ret.y = clamp(ret.y, 0.0, 1.0);
	ret.z = clamp(ret.z, 0.0, 1.0);
	ret.w = clamp(ret.w, 0.0, 1.0);
	return ret;
}

void main(void)
{
	switch(texFlag)
	{
	case 0:
		break;
	case 1:
		tex0Color = texture2D( texMap0, Texcoord0);
		break;
	case 2:
		tex1Color = texture2D( texMap1, Texcoord1);
		break;
	case 3:
		tex0Color = texture2D( texMap0, Texcoord0);
		tex1Color = texture2D( texMap1, Texcoord1);
		break;
	}
	
	switch(cycleMode)
	{
	case 0: //cycle 1
		{
			vec3 ca, cb, cc, cd;
			float aa, ab, ac, ad;
			
			ca = getColorElement(combineC1[0]);
			cb = getColorElement(combineC1[1]);
			cc = getColorElement(combineC1[2]);
			cd = getColorElement(combineC1[3]);
			aa = getAlphaElement(combineA1[0]);
			ab = getAlphaElement(combineA1[1]);
			ac = getAlphaElement(combineA1[2]);
			ad = getAlphaElement(combineA1[3]);
			
			gl_FragColor.xyz = (ca - cb) * cc + cd;
			gl_FragColor[3] = (aa - ab) * ac + ad;
		}
		break;
	case 1: //cycle 2
		{
			vec3 ca, cb, cc, cd;
			float aa, ab, ac, ad;
			
			aa = getAlphaElement(combineA1[0]);
			ab = getAlphaElement(combineA1[1]);
			ac = getAlphaElement(combineA1[2]);
			ad = getAlphaElement(combineA1[3]);
			stage1Color[3] = (aa - ab) * ac + ad;

			ca = getColorElement(combineC1[0]);
			cb = getColorElement(combineC1[1]);
			cc = getColorElement(combineC1[2]);
			cd = getColorElement(combineC1[3]);
			
			stage1Color.xyz = (ca - cb) * cc + cd;

			ca = getColorElement(combineC2[0]);
			cb = getColorElement(combineC2[1]);
			cc = getColorElement(combineC2[2]);
			cd = getColorElement(combineC2[3]);
			aa = getAlphaElement(combineA2[0]);
			ab = getAlphaElement(combineA2[1]);
			ac = getAlphaElement(combineA2[2]);
			ad = getAlphaElement(combineA2[3]);
			
			gl_FragColor.xyz = (ca - cb) * cc + cd;
			gl_FragColor[3] = (aa - ab) * ac + ad;
		}
		break;
	case 2: //copy
		{
			gl_FragColor = tex0Color;
		}
		break;
	case 3: //fill
		{
			gl_FragColor = fillColor;
		}
		break;
	case 6:
		{
			gl_FragColor = fogColor;
		}
		break;
	case 7:
		{
//			tex0Color = 1.0;
//			tex1Color = 0.5;

			
			stage1Color.xyz = ((tex1Color.xyz- tex0Color.xyz) * tex0Color.xyz) + envColor.xyz;
			stage1Color.w = (tex1Color.w - primColor.w) * envColor.w + tex0Color.w;

			stage1Color.xyz = clamp3(stage1Color.xyz);

			gl_FragColor.xyz = (stage1Color.xyz - tex0Color.xyz) * tex1Color.xyz + primColor.xyz;
			gl_FragColor.w = stage1Color.w * tex0Color.w;

//			gl_FragColor.w = 1.0;//abs(gl_FragColor.w);
//			gl_FragColor.xyz = abs((tex1Color.xyz- tex0Color.xyz) * tex0Color.xyz);// + envColor.xyz;
			gl_FragColor.xyz = invert3(gl_FragColor.xyz);
//			gl_FragColor.xyz = invert3(-tex0Color.xyz);

		}
		break;
	}
}
