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
mat3              worldToInput = outputToInput[0] * worldToOutput;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
uniform float threshold;
shun_iwasawa 36e06f
uniform float brightness;
shun_iwasawa 36e06f
uniform float radius;
shun_iwasawa 36e06f
uniform float angle;
shun_iwasawa 36e06f
uniform float halo;
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
float scale       = sqrt(abs(det(worldToOutput)));
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
float angle_      = radians(angle);
shun_iwasawa 36e06f
float sin_        = sin(angle_);
shun_iwasawa 36e06f
float cos_        = cos(angle_);
shun_iwasawa 36e06f
float threshold_  = 1.0 - 0.01 * threshold;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
float rad_        = radius * scale;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
const vec3 lVec   = vec3(0.298980712, 0.587036132, 0.113983154);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
#define STEPS_PER_PIXEL  4.0
shun_iwasawa 36e06f
shun_iwasawa 36e06f
float stepsCount = ceil(STEPS_PER_PIXEL * rad_);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
float halo_       = 0.01 * (halo + 1.0) * stepsCount;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
float rayWeight(float s)
shun_iwasawa 36e06f
{
shun_iwasawa 36e06f
  s /= halo_;
shun_iwasawa 36e06f
  return clamp(1.0 - s * s, 0.0, 1.0);
shun_iwasawa 36e06f
}
shun_iwasawa 36e06f
shun_iwasawa 36e06f
vec4 lightValue(const vec2 texCoord)
shun_iwasawa 36e06f
{
shun_iwasawa 36e06f
  vec4 col = texture2D(inputImage[0], texCoord);
shun_iwasawa 36e06f
  float l = dot(lVec, col.rgb);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  return smoothstep(threshold_, 1.0, l) * col;
shun_iwasawa 36e06f
}
shun_iwasawa 36e06f
shun_iwasawa 36e06f
bool filterLine(inout vec4 col, const vec2 p, const vec2 dx, float s_y)
shun_iwasawa 36e06f
{
shun_iwasawa 36e06f
  float rw  = rayWeight(s_y);
shun_iwasawa 36e06f
  if(rw == 0.0)
shun_iwasawa 36e06f
    return false;
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  float dw  = max(1.0 - s_y / stepsCount, 0.0);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  col      += dw * rw * lightValue(p);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  vec2 s    = vec2(0.0, s_y);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  for(s.x = 1.0; s.x < stepsCount; s.x += 1.0)
shun_iwasawa 36e06f
  {
shun_iwasawa 36e06f
    dw = max(1.0 - length(s) / stepsCount, 0.0);
shun_iwasawa 36e06f
    col += rw * dw * (
shun_iwasawa 36e06f
      lightValue(p + s.x * dx) +
shun_iwasawa 36e06f
      lightValue(p - s.x * dx));
shun_iwasawa 36e06f
  }
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  return true;
shun_iwasawa 36e06f
}
shun_iwasawa 36e06f
shun_iwasawa 36e06f
void main( void )
shun_iwasawa 36e06f
{
shun_iwasawa 36e06f
  vec2 texCoord   = (outputToInput[0] * vec3(gl_FragCoord.xy, 1.0)).xy;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  float step      = radius / stepsCount;
shun_iwasawa 36e06f
  mat2  transf    =
shun_iwasawa 36e06f
    mat2((worldToInput * vec3(1.0, 0.0, 0.0)).xy,
shun_iwasawa 36e06f
         (worldToInput * vec3(0.0, 1.0, 0.0)).xy) *             // worldToInput without translational part
shun_iwasawa 36e06f
    mat2(cos_, sin_, -sin_, cos_) *                             // angle shift by uniform parameter
shun_iwasawa 36e06f
    step;                                                       // [-stepsCount,stepsCount]^2 to [-radius, radius]^2
shun_iwasawa 36e06f
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  // Filter lines in the 2 orthogonal directions
shun_iwasawa 36e06f
  vec4 addCol = vec4(0.0);
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  // Horizontal
shun_iwasawa 36e06f
  filterLine(addCol, texCoord, transf[0], 0.0);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  for(float s = 1.0; s < stepsCount; s += 1.0)
shun_iwasawa 36e06f
  {
shun_iwasawa 36e06f
    if(!filterLine(addCol, texCoord + s * transf[1], transf[0], s))
shun_iwasawa 36e06f
      break;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
    filterLine(addCol, texCoord - s * transf[1], transf[0], s);
shun_iwasawa 36e06f
  }
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  // Vertical
shun_iwasawa 36e06f
  filterLine(addCol, texCoord, transf[1], 0.0);
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  for(float s = 1.0; s < stepsCount; s += 1.0)
shun_iwasawa 36e06f
  {
shun_iwasawa 36e06f
    if(!filterLine(addCol, texCoord + s * transf[0], transf[1], s))
shun_iwasawa 36e06f
      break;
shun_iwasawa 36e06f
shun_iwasawa 36e06f
    filterLine(addCol, texCoord - s * transf[0], transf[1], s);
shun_iwasawa 36e06f
  }
shun_iwasawa 36e06f
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  float weight = stepsCount * STEPS_PER_PIXEL;
shun_iwasawa 36e06f
  
shun_iwasawa 36e06f
  vec4 col     = texture2D(inputImage[0], texCoord);
shun_iwasawa 36e06f
  gl_FragColor = col + addCol * (brightness / weight);
shun_iwasawa 36e06f
}