#version 110

#define M_PI 3.1415926535897932384626433832795

uniform vec2 ove_resolution;
varying vec2 ove_texcoord;

uniform sampler2D tex_in;
uniform vec3 color_in;
uniform float softness_in;
uniform float opacity_in;
uniform float distance_in;
uniform float direction_in;

void main(void) {
    // Use pythagoras with the distance (hypotenuse) to find the shadow offset
    float direction_radians = direction_in * (M_PI/180.0);

    float opposite = sin(direction_radians) * distance_in;
    float adjacent = cos(direction_radians) * distance_in;

    vec2 angle = vec2(adjacent, opposite);

    // Convert distance from pixels to 0.0 - 1.0 texture coordinates
    angle /= ove_resolution;

    float shadow_alpha;

    // For a soft shadow, we use a box blur-like formula
    if (softness_in > 0.0) {
        float radius = ceil(softness_in);
        float divider = 1.0 / pow(softness_in, 2.0);
        shadow_alpha = 0.0;

        for (float x=-radius+0.5;x<=radius;x+=2.0) {
            for (float y=-radius+0.5;y<=radius;y+=2.0) {
                vec2 pixel_coord = ove_texcoord - angle;
                pixel_coord.x += x/ove_resolution.x;
                pixel_coord.y += y/ove_resolution.y;
                vec4 pixel_color = texture2D(tex_in, pixel_coord);

                shadow_alpha += pixel_color.a * divider;
            }
        }
    } else {
        // Perfectly hard shadow
        vec4 src_color = texture2D(tex_in, ove_texcoord - angle);
        shadow_alpha = src_color.a;
    }
    
    vec4 shadow_px = vec4(color_in, shadow_alpha * opacity_in * 0.01);

    // Get current pixel and perform an alpha over for it over the shadow we've made
    vec4 dst_color = texture2D(tex_in, ove_texcoord);
    shadow_px *= (1.0 - dst_color.a);
    shadow_px += dst_color;

    gl_FragColor = shadow_px;
}
