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