//

// Fragment shader for radial blur
//
// Author: Blah, i can neither confirm nor deny i wrote this
//
//

#version 330

#include "alpha.h"

uniform sampler2DRect inputTex;
uniform sampler2DRect maskTex;
uniform float blendValue;
uniform float uBlendValue=1.0;
uniform float iterations=6.;
uniform float decay=.97;

in vec2 fsTexture;
in vec2 fsMaskTexture;
in vec2 fsNormalizedUV;
in vec2 fsTextureSize;
in float fsTime;
out vec4 outColor;


// 2x1 hash. Used to jitter the samples.
float hash( vec2 p ){ return fract(sin(dot(p, vec2(41, 289)))*45758.5453); }


// Light offset.
//
// I realized, after a while, that determining the correct light position doesn't help, since
// radial blur doesn't really look right unless its focus point is within the screen boundaries,
// whereas the light is often out of frame. Therefore, I decided to go for something that at
// least gives the feel of following the light. In this case, I normalized the light position
// and rotated it in unison with the camera rotation. Hacky, for sure, but who's checking? :)
vec3 lOff(){
    
    vec2 u = sin(vec2(1.57, 0) - fsTime/2.);
    mat2 a = mat2(u, -u.y, u.x);
    
    vec3 l = normalize(vec3(1.5, 1., -0.5));
    l.xz = a * l.xz;
    l.xy = a * l.xy;
    
    return l;
    
}



void main()
{
    
    // Screen coordinates.
    vec2 uv = fsNormalizedUV;
    
    // Radial blur factors.
    //
    // Falloff, as we radiate outwards.
//    float decay = 0.97;
    // Controls the sample density, which in turn, controls the sample spread.
    float density = 0.5;
    // Sample weight. Decays as we radiate outwards.
    float weight = 0.1;
    
    // Light offset. Kind of fake. See above.
    vec3 l = lOff();
    
    // Offset texture position (uv - .5), offset again by the fake light movement.
    // It's used to set the blur direction (a direction vector of sorts), and is used
    // later to center the spotlight.
    //
    // The range is centered on zero, which allows the accumulation to spread out in
    // all directions. Ie; It's radial.
    vec2 tuv =  uv - .5 - l.xy*.45;
    
    // Dividing the direction vector above by the sample number and a density factor
    // which controls how far the blur spreads out. Higher density means a greater
    // blur radius.
    vec2 dTuv = tuv*density/iterations;
    
    // Grabbing a portion of the initial texture sample. Higher numbers will make the
    // scene a little clearer, but I'm going for a bit of abstraction.
    vec4 col = texture(inputTex, uv.xy*fsTextureSize);
    col = col*0.25;

    // Jittering, to get rid of banding. Vitally important when accumulating discontinuous
    // samples, especially when only a few layers are being used.
    uv += dTuv*(hash(uv.xy + fract(fsTime))*2. - 1.);
    
    // The radial blur loop. Take a texture sample, move a little in the direction of
    // the radial direction vector (dTuv) then take another, slightly less weighted,
    // sample, add it to the total, then repeat the process until done.
    for(float i=0.; i < iterations; i++)
    {
        uv -= dTuv;
        vec4 c = texture(inputTex, uv*fsTextureSize);
        col += c * weight;
        weight *= decay;
    }
    
    // Multiplying the final color with a spotlight centered on the focal point of the radial
    // blur. It's a nice finishing touch... that Passion came up with. If it's a good idea,
    // it didn't come from me. :)
    col *= (1. - dot(tuv, tuv)*.75);
    
    // Smoothstepping the final color, just to bring it out a bit, then applying some
    // loose gamma correction.
    vec4 blurColor = sqrt(smoothstep(0., 1., col));
    outColor=texture(inputTex,fsTexture);

    float blendValue2=uBlendValue*blendValue;
#ifdef USE_MASK
    blendValue2*=texture(maskTex,fsMaskTexture).a;
#endif
    mixColor(outColor, outColor, blurColor, blendValue2);
}
