#version 330
#extension GL_ARB_explicit_uniform_location : enable

in vec4 coord;
in vec4 color;
in vec4 normal;
out vec4 fragcolor;
uniform vec3 lightdir;


uniform sampler2D shadowmap_soft;
uniform mat4 shadowmatrix_soft;
uniform sampler2D shadowmap_hard;
uniform mat4 shadowmatrix_hard;

float getshadowsample_hard(vec4 coord)
{
    float shadowdepth = texture(shadowmap_hard, coord.xy).r;

    if (shadowdepth < coord.z ||
        coord.w < 0.0 || 
        coord.x < 0.0 ||
        coord.y < 0.0 ||
        coord.x > 1.0 ||
        coord.y > 1.0)
    {
        return 0.0;
    }
    return 1.0;
}

float getshadowsample_soft(vec4 coord)
{
    float shadowdepth = texture(shadowmap_soft, coord.xy).r;

    if (shadowdepth < coord.z ||
        coord.w < 0.0 || 
        coord.x < 0.0 ||
        coord.y < 0.0 ||
        coord.x > 1.0 ||
        coord.y > 1.0)
    {
        return 0.0;
    }
    return 1.0;
}

vec2 poissonDisk[16] = vec2[](
vec2( -0.94201624, -0.39906216 ),
vec2( 0.94558609, -0.76890725 ),
vec2( -0.094184101, -0.92938870 ),
vec2( 0.34495938, 0.29387760 ),
vec2( -0.91588581, 0.45771432 ),
vec2( -0.81544232, -0.87912464 ),
vec2( -0.38277543, 0.27676845 ),
vec2( 0.97484398, 0.75648379 ),
vec2( 0.44323325, -0.97511554 ),
vec2( 0.53742981, -0.47373420 ),
vec2( -0.26496911, -0.41893023 ),
vec2( 0.79197514, 0.19090188 ),
vec2( -0.24188840, 0.99706507 ),
vec2( -0.81409955, 0.91437590 ),
vec2( 0.19984126, 0.78641367 ),
vec2( 0.14383161, -0.14100790 )
);



void main()
{	
    vec3 N = normalize(normal.xyz);
    vec3 L = normalize(lightdir - coord.xyz);
    float l = max(dot(N,L),0.0) * 1.5;    
    vec4 col = color * max(l, l * l);
    
////
    vec4 s = vec4(1,1,1,1);
    vec4 shadowcoord_hard = shadowmatrix_hard * coord;
    shadowcoord_hard /= shadowcoord_hard.w;
    vec4 shadowcoord_soft = shadowmatrix_soft * coord;
    shadowcoord_soft /= shadowcoord_soft.w;
    
    
    float shade_hard = 0;
    float shade_soft = 0;
    for (int i = 0; i < 16; i++)
    {
        vec4 temp = shadowcoord_hard;
        temp.xy += poissonDisk[i]/400.0;
        shade_hard += getshadowsample_hard(temp);

        temp = shadowcoord_soft;
        temp.xy += poissonDisk[i]/100.0;
        shade_soft += getshadowsample_soft(temp);
    }
    shade_hard = shade_hard / 16.0;
    shade_soft = shade_soft / 16.0;
    s = (s * 3 + s * shade_soft) * 0.25 * shade_hard;
    s.w = 1;
////
    col *= s;
    
    
    fragcolor = col;
}