uppers
downers
screamers
laughers
DISPLACEMENT EFFECT
.displace-flash

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
<script>
    var zoomDisplaceEffect = function (params) {
        var parent = params.parent || console.warn("no parent");
        var displacementImage = params.displacementImage || console.warn("displacement image missing");
        var image1 = params.image1 || console.warn("first image missing");
        var image2 = params.image2 || console.warn("second image missing");
        var intensity = params.intensity || 1;
        var speed = params.speed || 1.6;
        var easing = params.easing || Power2.easeInOut;

        var isMobile = function () {
            var userAgent = navigator.userAgent || navigator.vendor || window.opera;
            return /android|bb\d+|meego|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(userAgent.substr(0, 4));
        };

        var scene = new THREE.Scene();
        var camera = new THREE.OrthographicCamera(
            parent.offsetWidth / -2, parent.offsetWidth / 2,
            parent.offsetHeight / 2, parent.offsetHeight / -2,
            1, 1000
        );
        camera.position.z = 1;

        var renderer = new THREE.WebGLRenderer({ antialias: false });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setClearColor(0xffffff, 0);
        renderer.setSize(parent.offsetWidth, parent.offsetHeight);
        parent.appendChild(renderer.domElement);

        var loader = new THREE.TextureLoader();
        loader.crossOrigin = "";
        var texture1 = loader.load(image1);
        var texture2 = loader.load(image2);
        var displacement = loader.load(displacementImage);
        displacement.wrapS = displacement.wrapT = THREE.RepeatWrapping;

        texture1.magFilter = texture2.magFilter = THREE.LinearFilter;
        texture1.minFilter = texture2.minFilter = THREE.LinearFilter;
        texture1.anisotropy = renderer.getMaxAnisotropy();
        texture2.anisotropy = renderer.getMaxAnisotropy();

        var shaderMaterial = new THREE.ShaderMaterial({
            uniforms: {
                effectFactor: { type: "f", value: intensity },
                dispFactor: { type: "f", value: 0 },
                zoomFactor: { type: "f", value: 1.0 },
                texture: { type: "t", value: texture1 },
                texture2: { type: "t", value: texture2 },
                disp: { type: "t", value: displacement }
            },
            vertexShader: `
                varying vec2 vUv;
                uniform float zoomFactor;
                void main() {
                    vUv = (uv - 0.5) * zoomFactor + 0.5;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                }
            `,
            fragmentShader: `
                varying vec2 vUv;
                uniform sampler2D texture;
                uniform sampler2D texture2;
                uniform sampler2D disp;
                uniform float dispFactor;
                uniform float effectFactor;
                void main() {
                    vec2 uv = vUv;
                    vec4 disp = texture2D(disp, uv);
                    vec2 distortedPosition = uv + dispFactor * (disp.r * effectFactor) * (0.5 - uv);
                    vec2 distortedPosition2 = uv - (1.0 - dispFactor) * (disp.r * effectFactor) * (0.5 - uv);

                    vec4 _texture = texture2D(texture, distortedPosition);
                    vec4 _texture2 = texture2D(texture2, distortedPosition2);
                    vec4 finalTexture = mix(_texture, _texture2, dispFactor);

                    gl_FragColor = finalTexture;
                }
            `,
            transparent: true,
            opacity: 1
        });

        var geometry = new THREE.PlaneBufferGeometry(parent.offsetWidth, parent.offsetHeight, 1);
        var mesh = new THREE.Mesh(geometry, shaderMaterial);
        scene.add(mesh);

        var zoomDisplaceAnimation = function () {
            TweenMax.to(shaderMaterial.uniforms.zoomFactor, speed, {
                value: 1,
                ease: easing,
                repeat: -1,
                yoyo: false
            });
            TweenMax.to(shaderMaterial.uniforms.dispFactor, speed, {
                value: 1,
                ease: easing,
                repeat: -1,
                yoyo: false
            });
        };

        var animate = function () {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        };

        animate();
        zoomDisplaceAnimation();
    };

    var myZoomDisplaceEffect = new zoomDisplaceEffect({
        parent: document.querySelector('.displace-flash .tn-atom'),
        image1: 'https://static.tildacdn.com/tild6433-6365-4235-a234-366531393166/Galaxy.png',
        image2: 'https://static.tildacdn.com/tild6433-6365-4235-a234-366531393166/Galaxy.png',
        displacementImage: 'https://static.tildacdn.com/tild6433-6365-4235-a234-366531393166/Galaxy.png',
        speed: 3.0,
        easing: Linear.easeNone
    });
</script>