|
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 |
}
|