shun_iwasawa 36e06f
#ifdef GL_ES
shun_iwasawa 36e06f
precision mediump float;
shun_iwasawa 36e06f
#endif
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
uniform mat3      worldToOutput;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
uniform sampler2D inputImage[1];
shun_iwasawa 36e06f
uniform mat3      outputToInput[1];
shun_iwasawa 36e06f
shun_iwasawa 36e06f
uniform vec2  center;
shun_iwasawa 36e06f
uniform float radius;
shun_iwasawa 36e06f
uniform float blur;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
float det(mat3 m) { return m[0][0] * m[1][1] - m[0][1] * m[1][0]; }
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
mat3 worldToInput = outputToInput[0] * worldToOutput;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
vec2 center_s     = (worldToOutput * vec3(center, 1.0)).xy;
shun_iwasawa 36e06f
float scale_s     = sqrt(abs(det(worldToOutput)));
shun_iwasawa 36e06f
float rad_s       = scale_s * max(radius, 0.0);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
#define STEPS_PER_PIXEL   4.0
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
void main( void )
shun_iwasawa 36e06f
{
shun_iwasawa 36e06f
  // Build lengths on output metrics
shun_iwasawa 36e06f
  vec2  v           = gl_FragCoord.xy - center_s;
shun_iwasawa 36e06f
  float vLength     = length(v);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  float dist_s      = max(vLength - rad_s, 0.0);
shun_iwasawa 36e06f
  float b_s         = blur * dist_s;
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  // Putting a maximum samples count - to prevent freezes; besides, blurring too many
shun_iwasawa 36e06f
  // pixels is typically useless...
shun_iwasawa 36e06f
  int samplesCount  = int(clamp(ceil(b_s * STEPS_PER_PIXEL), 1.0, 2000.0));
shun_iwasawa 36e06f
  float step_s      = b_s / float(samplesCount);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  // Perform filtering
shun_iwasawa 36e06f
  vec2 texPos       = (outputToInput[0] * vec3(gl_FragCoord.xy, 1.0)).xy;
shun_iwasawa 36e06f
  vec4 pix          = texture2D(inputImage[0], texPos);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  vec2 vStep = v * (step_s / max(vLength, 0.01));
shun_iwasawa 36e06f
  vStep      = (outputToInput[0] * vec3(vStep, 0.0)).xy;
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  vec2 tPos0 = texPos + vStep;
shun_iwasawa 36e06f
  vec2 tPos1 = texPos - vStep;
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  for(int s = 1; s < samplesCount; ++s)
shun_iwasawa 36e06f
  {
shun_iwasawa 36e06f
    pix += texture2D(inputImage[0], tPos0);
shun_iwasawa 36e06f
    pix += texture2D(inputImage[0], tPos1);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
    tPos0 += vStep, tPos1 -= vStep;
shun_iwasawa 36e06f
  }
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  gl_FragColor = pix / float(2 * samplesCount - 1);
shun_iwasawa 36e06f
}