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