// fisheye.frag
// (c) LLib Source Code Trust. All rights reserved.
//

#version 120

// Uniforms
uniform vec4 v4fUniform0;    // Parameters
uniform sampler2D texUnit0;
uniform float fUniformAlpha;

// Inputs from vertex shader
varying vec2 v2fTexCoord;

// Params from uniforms
// X: Strength [-10.0f, 10.0f] suggested.
// Y: Zoom [0.5f, 1.0f]
// Z: Width
// W: Height
vec4 v4fParams = v4fUniform0;

// Utility functions

vec2 MapUV(in vec2 v2fuv)
{
   float fStrength = v4fParams.x;
   float fZoom = v4fParams.y;
   vec2 v2fSize = v4fParams.zw;
   vec2 v2fHalfSize = v2fSize * 0.5f;               
   vec2 v2fPos = (v2fuv * v2fSize) - v2fHalfSize;
    
   float fLengthSize = length(v2fSize);
   float fInvCorrectionRadius = fStrength / fLengthSize;
   float fMaxRadius = (fLengthSize * 0.5f) * fInvCorrectionRadius;

   float fDistance = sqrt(((v2fPos.x * v2fPos.x) + (v2fPos.y * v2fPos.y)) * 0.5f);
   float fRadius = fDistance * fInvCorrectionRadius;
   if (fStrength < 0.0f) {
      fRadius = abs(fRadius);
      fRadius += (fMaxRadius - sqrt((fMaxRadius * fMaxRadius) - (fRadius * fRadius))) * 0.5f;
   }
   float fTheta = (fRadius == 0.0f) ? 1.0f : (atan(fRadius) / fRadius);
   vec2 v2fSource = v2fHalfSize + (fTheta * v2fPos * fZoom);
   return (v2fSource / v2fSize);
}

vec4 GetColor(in vec2 v2finuv)
{
   vec2 v2fuv = MapUV(v2finuv);
   if (v2fuv.x < 0.0f) return vec4(0.0f);
   if (v2fuv.x > 1.0f) return vec4(0.0f);
   if (v2fuv.y > 1.0f) return vec4(0.0f);
   if (v2fuv.y < 0.0f) return vec4(0.0f);
   return texture2D(texUnit0, v2fuv);
}

void main()
{
   // Apply effect
   vec4 v4fColor = GetColor(v2fTexCoord);
   gl_FragColor = vec4(v4fColor.rgb, v4fColor.a * fUniformAlpha); 
}

