skew.glsl 3.25 KB
uniform float left;
uniform float top;
uniform int dir;
uniform float intensity;
uniform float origin;
uniform bool sh;
uniform float shx;
uniform float shy;
uniform float shr;
uniform float shz;
uniform float shv;
uniform float prange;
uniform float progress;
uniform vec4 resolution;
uniform sampler2D src1;
uniform sampler2D src2;
varying vec2 vUv;
float pi = 3.141592653;
float map(float a, float b, float c, float d, float v) {
    return clamp((v - a) * (d - c) / (b - a) + c, 0., 1.);
}
vec2 mirror(vec2 v) {
    vec2 m = mod(v, 2.0);
    return mix(m, 2.0 - m, step(1.0, m));
}
vec2 rotateUV(vec2 uv, float rotation, vec2 mid) {
    return vec2(cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x, cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y);
}
vec2 getAngle(vec2 p1) {
    return vec2(.5, .5) * normalize(p1);
}
float qinticOut(float t, float power) {
    return 1.0 - pow(1. - t, power);
}
float elasticOut(float t) {
    return sin(13.0 * t * pi / shv) * pow(5.5, 3. * (t - 1.0));
}
vec2 shake(vec2 uv, float p, float shx, float shy, float tilt, float z) {
    float m = elasticOut(p);
    float n = (1. - p) * p;
    if (tilt != 0.) {
        float tmc = (1. - m) * m * n;
        uv = rotateUV(uv, tmc * tilt, vec2(.5, .5));
    }
    if (z != 0.) {
        p = p * p;
        uv.x -= 0.5;
        uv.y -= 0.5;
        uv *= (z * p * n + 1.);
        uv.x += 0.5;
        uv.y += 0.5;
    }
    if (shx != 0. && shy != 0.) {
        uv.x += m * shx * 2. * n;
        uv.y -= m * (1. - m) * shy * n;
    }
    return uv;
}
void main() {
    vec2 uv = vUv;
    vec2 vw = uv;
    vec2 vwo = vw;
    float m = progress;
    float steps = 1.0 / (max(abs(left), abs(top)) + 2.);
    float ms = m;
    if (sh) ms = qinticOut(m, 10.);
    float flip = (m - 0.5) * 2.;
    float mult = sin(ms * pi);
    mult = min(mult, 0.5);
    if (dir == 1 || dir == 2) mult /= 10.;
    if (dir == 1) {
        float shift = origin <= 0.5 ? uv.y - origin : origin - uv.y;
        float shift2 = origin == 0. || origin == 1. ? 1. : origin;
        vw.x += sign(left) * mix(shift, shift - 1., ms) * intensity;
    } else if (dir == 2) {
        float shift = origin <= 0.5 ? uv.x - origin : origin - uv.x;
        float shift2 = origin == 0. || origin == 1. ? 1. : origin;
        vw.y += sign(top) * mix(shift, shift - shift2, ms) * intensity;
    } else {
        vec2 d1 = getAngle(vec2(0.5 * top, 0.5 * left));
        vec2 d2 = getAngle(vec2(0.5 * top, 0.5 * left));
        float l1 = length(vec2(left > 0. ? 1. - uv.x : uv.x, top > 0. ? 1. - uv.y : uv.y));
        float l2 = length(vec2(left > 0. ? uv.x : 1. - uv.x, top > 0. ? uv.y : 1. - uv.y));
        vec2 a = vw + l1 * d1 * flip * (step(top * left, 0.) - 0.5) * intensity;
        vec2 b = vw + l2 * d2 * flip * (step(top * left, 0.) - 0.5) * intensity;
        vw = mix(a, b, ms);
    }
    uv = mix(vwo, vw, mult);
    if (sh) uv = shake(uv, 1. - m, shx, shy, shr, shz);
    vec2 nUv = vec2(uv.x + ms * left, uv.y + ms * top);
    nUv = mirror(nUv);
    vec2 nUvIn = nUv;
    if (mod(left, 2.0) != 0.) nUvIn.x *= -1.;
    if (mod(top, 2.0) != 0.) nUvIn.y *= -1.;
    float nprog = map((0.5 - prange), (0.5 + prange), 0., 1., ms);
    vec4 col = mix(TEXTURE2D(src1, nUv), TEXTURE2D(src2, nUvIn), nprog);
    gl_FragColor = col;
}