#ifdef GL_ES
// define default precision for float, vec, mat.
precision lowp float;
precision lowp sampler2D;
#endif

varying vec4 outColor;
//varying vec4 outTColor;
varying vec2 outTexc;
varying vec4 outFogColor;

varying vec4 outSpecColor;

uniform vec4 tcolor0;
uniform vec4 tcolor1;
uniform sampler2D baseTex;
uniform sampler2D coatTex;
uniform sampler2D maskTex;

#ifdef SHADOW_MAP
varying vec4 outShadowProj;
uniform sampler2D shadowTex;
//uniform vec2 shadowTexelSize;
varying vec4 outDiffusePrim;
varying vec4 outDiffuseSec;
#endif
#ifdef SHADOW_MAP_PCF
#define SAMPLES_COUNT 36
varying vec4 outShadowProj;
uniform sampler2D shadowTex;
uniform vec2 shadowTexelSize;
uniform vec2 shadowSamples[SAMPLES_COUNT];
varying vec4 outDiffusePrim;
varying vec4 outDiffuseSec;
#endif


/*float linstep(in float slopeStart, in float slopeEnd, in float value)
{
    float diff = slopeEnd - slopeStart;
    // this check can be skipped if we know that slopeStart != slopeEnd
    //if (diff == 0)
    //    return step(slopeStart, value);
    return clamp((value - slopeStart) / diff, 0.0, 1.0);
}
*/


float unpacFloatFromVec2(const vec2 value)
{
	const vec2 bitSh = vec2(1.0 / 256.0, 1.0);
	return dot(value,bitSh) * 15.0;
}

vec2 rotatePoint(float Angle, vec2 Point)
{
	vec2 sc = vec2(sin(Angle), cos(Angle));
	return vec2(Point.x * sc.y - Point.y * sc.x, Point.x * sc.x + Point.y * sc.y);
}

void main()
{
	float shadowFactor = 1.0;
#ifdef SHADOW_MAP
	vec2 projectedUV = (outShadowProj.xy / outShadowProj.w);
	
	vec2 samp = texture2D(shadowTex, projectedUV).xy;
	float sample = unpacFloatFromVec2(samp);
	shadowFactor = 0.51;
	if (sample > outShadowProj.w)
		shadowFactor = 1.0;
#endif
#ifdef SHADOW_MAP_PCF
	vec2 projectedUV = (outShadowProj.xy / outShadowProj.w);

	float sum = 0.0;
	int i;
	for (i = 0; i < SAMPLES_COUNT; i++)
	{
		float sample = unpacFloatFromVec2(texture2D(shadowTex,  projectedUV + shadowSamples[i]).xy);
		sum += clamp(float(sample > outShadowProj.w)*1.5,0.4,1.0);
	}
	//float shadowFactor = max(0.42, sum / float(SAMPLES_COUNT));
	shadowFactor = sum / float(SAMPLES_COUNT);
	/*vec4 packedShadowSample12;
	vec4 packedShadowSample34;
	vec4 unpackedShadowSamples;
	bvec4 shadowValues;
	
	const vec2 bitSh = vec2(1.0 / 256.0, 1.0);
	const float minShadow = 0.25;

	float offset = 1.0;
	float offset2 = 2.0;
	float offset4 = 4.0;
	float offset8 = 8.0;

	packedShadowSample12.xy = texture2D(shadowTex, projectedUV + vec2(-offset,  offset) * shadowTexelSize).xy;
	packedShadowSample12.zw = texture2D(shadowTex, projectedUV + vec2(-offset4,  offset2) * shadowTexelSize).xy;
	packedShadowSample34.xy = texture2D(shadowTex, projectedUV + vec2(-offset2, 0.0) * shadowTexelSize).xy;
	packedShadowSample34.zw = texture2D(shadowTex, projectedUV + vec2(-offset4, -offset4) * shadowTexelSize).xy;
	
	unpackedShadowSamples = vec4(dot(packedShadowSample12.xy,bitSh),
									  dot(packedShadowSample12.zw,bitSh),
									  dot(packedShadowSample34.xy,bitSh),
									  dot(packedShadowSample34.zw,bitSh)) * 15.0;
									  
	shadowValues = greaterThan(unpackedShadowSamples, outShadowProj.wwww);
	
	float shadowFactor = dot(max(vec4(shadowValues), minShadow), vec4(0.25, 0.25, 0.25, 0.25));

	packedShadowSample12.xy = texture2D(shadowTex, projectedUV + vec2(-offset, -offset2) * shadowTexelSize).xy;
	packedShadowSample12.zw = texture2D(shadowTex, projectedUV + vec2( offset4, offset4) * shadowTexelSize).xy;
	packedShadowSample34.xy = texture2D(shadowTex, projectedUV + vec2( offset2, offset2) * shadowTexelSize).xy;
	packedShadowSample34.zw = texture2D(shadowTex, projectedUV + vec2( offset2, offset) * shadowTexelSize).xy;
	
	unpackedShadowSamples = vec4(dot(packedShadowSample12.xy,bitSh),
									  dot(packedShadowSample12.zw,bitSh),
									  dot(packedShadowSample34.xy,bitSh),
									  dot(packedShadowSample34.zw,bitSh)) * 15.0;
									  
	shadowValues = greaterThan(unpackedShadowSamples, outShadowProj.wwww);	
	
	shadowFactor += dot(max(vec4(shadowValues), minShadow), vec4(0.25, 0.25, 0.25, 0.25));
	
	packedShadowSample12.xy = texture2D(shadowTex, projectedUV).xy;
	packedShadowSample12.zw = texture2D(shadowTex, projectedUV + vec2(offset, -offset4) * shadowTexelSize).xy;
	packedShadowSample34.xy = texture2D(shadowTex, projectedUV + vec2(offset4, -offset2) * shadowTexelSize).xy;
	packedShadowSample34.zw = texture2D(shadowTex, projectedUV + vec2(offset2, -offset4) * shadowTexelSize).xy;
	
	unpackedShadowSamples = vec4(dot(packedShadowSample12.xy,bitSh),
									  dot(packedShadowSample12.zw,bitSh),
									  dot(packedShadowSample34.xy,bitSh),
									  dot(packedShadowSample34.zw,bitSh)) * 15.0;
									  
	shadowValues = greaterThan(unpackedShadowSamples, outShadowProj.wwww);	
	
	shadowFactor += dot(max(vec4(shadowValues), minShadow), vec4(0.25, 0.25, 0.25, 0.25));
	
	shadowFactor *= 0.25;*/
#endif

	vec4 baseColor = texture2D(baseTex, outTexc) + tcolor0;
	vec4 coatColor = texture2D(coatTex, outTexc) + tcolor1;
	#ifdef GL_ES
    mediump float mask = texture2D(maskTex, outTexc).r;
    mediump float outColora = outColor.a;
    mediump float maskedColor  = outColora * mask;
	#else
    float mask = texture2D(maskTex, outTexc).r;
    float outColora = outColor.a;
    float maskedColor  = outColora * mask;
	#endif
    // coat alpha threshold is at 0.3
    //lowp float alpha = linstep(0.28, 0.32, maskedColor);
    float alpha = clamp((maskedColor - 0.28) * 25.0, 0.0, 1.0);
    float dimmer = 1.0 - alpha;
    vec4 texColor = mix(baseColor * dimmer, coatColor, alpha);

	//mediump float specVal = (mask - 0.6) / 0.4;
	//float specMask = 0.5 + clamp(specVal, 0.0, 0.5);
	float specMask = clamp(mask, 0.6, 0.8) * 2.5 - 0.8;

	vec4 specular = (outSpecColor * specMask * (0.5 + alpha*0.5));

	vec4 color;
#if !defined(SHADOW_MAP) && !defined(SHADOW_MAP_PCF)
	color = outColor * texColor + specular;
#endif
#ifdef SHADOW_MAP_PCF
	color = (outDiffusePrim * shadowFactor + outDiffuseSec + outColor) * texColor + specular * shadowFactor;
#endif
#ifdef SHADOW_MAP
	color = (outDiffusePrim * shadowFactor + outDiffuseSec + outColor) * texColor + specular * shadowFactor;
#endif
	gl_FragColor = vec4(mix(color.xyz, outFogColor.xyz, outFogColor.w), color.w);
}
