precision mediump float; varying vec2 vTextureCoord; uniform sampler2D uSampler; uniform float radius; uniform float angle; uniform vec2 offset; uniform vec4 filterArea; vec2 mapCoord( vec2 coord ) { coord *= filterArea.xy; coord += filterArea.zw; return coord; } vec2 unmapCoord( vec2 coord ) { coord -= filterArea.zw; coord /= filterArea.xy; return coord; } vec2 twist(vec2 coord) { coord -= offset; float dist = length(coord); if (dist < radius) { float ratioDist = (radius - dist) / radius; float angleMod = ratioDist * ratioDist * angle; float s = sin(angleMod); float c = cos(angleMod); coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c); } coord += offset; return coord; } void main(void) { vec2 coord = mapCoord(vTextureCoord); coord = twist(coord); coord = unmapCoord(coord); gl_FragColor = texture2D(uSampler, coord ); }