Toshihiro Shimizu 890ddd
#ifdef GL_ES
Toshihiro Shimizu 890ddd
precision mediump float;
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
uniform mat3      worldToOutput;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
uniform sampler2D inputImage[1];
Toshihiro Shimizu 890ddd
uniform mat3      outputToInput[1];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
uniform vec2  center;
Toshihiro Shimizu 890ddd
uniform float radius;
Toshihiro Shimizu 890ddd
uniform float blur;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
float det(mat3 m) { return m[0][0] * m[1][1] - m[0][1] * m[1][0]; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
mat3 worldToInput = outputToInput[0] * worldToOutput;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
vec2 center_s     = (worldToOutput * vec3(center, 1.0)).xy;
Toshihiro Shimizu 890ddd
float scale_s     = sqrt(abs(det(worldToOutput)));
Toshihiro Shimizu 890ddd
float rad_s       = scale_s * max(radius, 0.0);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#define STEPS_PER_PIXEL   4.0
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void main( void )
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  // Build lengths on output metrics
Toshihiro Shimizu 890ddd
  vec2  v           = gl_FragCoord.xy - center_s;
Toshihiro Shimizu 890ddd
  float distance_s  = length(v);
Toshihiro Shimizu 890ddd
  float angle       = atan(v.y, v.x);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  float dist_s      = max(distance_s - rad_s, 0.0);
Toshihiro Shimizu 890ddd
  float blurLen_s   = radians(max(blur, 0.0)) * dist_s;
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  float blur_       = blurLen_s / max(distance_s, 0.01);        // Jump the singularity
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  // Putting a maximum samples count - to prevent freezes; besides, blurring too many
Toshihiro Shimizu 890ddd
  // pixels is typically useless...
Toshihiro Shimizu 890ddd
  int samplesCount = int(clamp(ceil(blurLen_s * STEPS_PER_PIXEL), 1.0, 2000.0));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  float angle_step  = blur_ / float(samplesCount);
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  float cos_step    = cos(angle_step);
Toshihiro Shimizu 890ddd
  float sin_step    = sin(angle_step);
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  mat2 rot_step0    = mat2(cos_step, sin_step, -sin_step, cos_step);
Toshihiro Shimizu 890ddd
  mat2 rot_step1    = mat2(cos_step, -sin_step, sin_step, cos_step);
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  // Perform filtering
Toshihiro Shimizu 890ddd
  vec4 pix          = texture2D(inputImage[0], (outputToInput[0] * vec3(gl_FragCoord.xy, 1.0)).xy);
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  vec2 v0 = rot_step0 * v, v1 = rot_step1 * v;
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
  for(int s = 1; s < samplesCount; ++s)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    pix += texture2D(inputImage[0], (outputToInput[0] * vec3(center_s + v0, 1.0)).xy);
Toshihiro Shimizu 890ddd
    pix += texture2D(inputImage[0], (outputToInput[0] * vec3(center_s + v1, 1.0)).xy);
Toshihiro Shimizu 890ddd
  
Toshihiro Shimizu 890ddd
    v0 = rot_step0 * v0, v1 = rot_step1 * v1;
Toshihiro Shimizu 890ddd
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  gl_FragColor = pix / float(2 * samplesCount - 1);
Toshihiro Shimizu 890ddd
}