#version 120

varying vec3 n;

varying vec4 shadowCoord1;
varying vec4 shadowCoord2;
varying vec4 shadowCoord3;

uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D mask;
uniform mat4 viewMatrix;

uniform sampler2DShadow shadowMap1;
uniform sampler2DShadow shadowMap2;
uniform sampler2DShadow shadowMap3;
uniform float shadowMapSize;

float shadowLookup(sampler2DShadow depths, vec4 coord, vec2 offset)
{
    float texelSize = 1.0 / shadowMapSize;
    vec2 v = offset * texelSize * coord.w;
    float z = shadow2DProj(depths, coord + vec4(v.x, v.y, 0.0, 0.0)).z;
    return z;
}

float pcf(sampler2DShadow depths, vec4 coord, float radius)
{
    float s = 0.0;
    float x, y;
	for (y = -radius ; y < radius ; y += 1.0)
	for (x = -radius ; x < radius ; x += 1.0)
    {
	    s += shadowLookup(depths, coord, vec2(x, y));
    }
	s /= radius * radius * 4.0;
    return s;
}

float weight(vec4 tc)
{
    vec2 proj = vec2(tc.x / tc.w, tc.y / tc.w);
    proj = (1.0 - abs(proj * 2.0 - 1.0)) * 8.0;
    proj = clamp(proj, 0.0, 1.0);
    return min(proj.x, proj.y);
}

void main()
{
    vec2 texcoords = gl_TexCoord[0].st;
    vec2 tiledTexcoords = texcoords * 20.0;
    
    vec3 N = normalize(n);
    
    vec3 L = gl_LightSource[0].position.xyz;
    float diffuse = clamp(dot(N, L), 0.0, 1.0);
    //float ambient = 0.2;
    
    float s1 = pcf(shadowMap1, shadowCoord1, 3.0);
    float s2 = pcf(shadowMap2, shadowCoord2, 2.0);
    float s3 = pcf(shadowMap3, shadowCoord3, 2.0);
    
    float w1 = weight(shadowCoord1);
    float w2 = weight(shadowCoord2);
    float w3 = weight(shadowCoord3);
    
    s3 = mix(1.0, s3, w3);
    s2 = mix(s3, s2, w2);
    s1 = mix(s2, s1, w1);

    vec3 tex1 = texture2D(texture1, tiledTexcoords).rgb;
    vec3 tex2 = texture2D(texture2, tiledTexcoords).rgb;
    float mask1 = texture2D(mask, texcoords).r;
    
    vec3 comb1 = tex1 * (1.0 - mask1) + tex2 * mask1;
    
    const vec3 shadowColor = vec3(0.3, 0.5, 0.7);
    const float shadowBrightness = 0.7;
    
    vec3 finalColor = mix(comb1 * shadowColor * shadowBrightness, comb1, diffuse * s1); 
    
    //gl_FragColor = vec4(finalColor, 1.0);
    
    float fogDistance = gl_FragCoord.z / gl_FragCoord.w;
    float fogFactor = clamp((gl_Fog.end - fogDistance) / (gl_Fog.end - gl_Fog.start), 0.0, 1.0);
        
    gl_FragColor = vec4(mix(gl_Fog.color.rgb, finalColor, fogFactor), 1.0);
}
