<div class="mask">
	<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1040 205.1" style="enable-background:new 0 0 1040 205.1;" xml:space="preserve">
        <style type="text/css">
          .st0 {
            fill-rule: evenodd;
            clip-rule: evenodd;
          }
        </style>
        <g>
          <g>
            <path
              class="st0"
              d="M108.7,155.2l24.8,23.3c-2.1,3.1-4.9,6.2-8.3,9.2c-10.2,8.8-26.2,16.4-48.5,16.4C33.4,204.1,1,174.8,1,131.2
      			c0-43.3,32.4-72.6,75.7-72.6c29.8,0,48.4,13.2,56.8,25.5l-28.7,26.7c-5.5-8-14.3-13.2-26.1-13.2c-18.3,0-32.4,12.6-32.4,33.6
      			c0,3.7,0.4,7.2,1.3,10.4c1.5,5.9,4.4,10.8,8.2,14.5c5,4.9,11.6,8,19.1,8.7c1.2,0.1,2.5,0.2,3.8,0.2c10.5,0,18.7-4.6,24.2-11.1
      			c0.7-0.8,1.3-1.6,1.8-2.4L108.7,155.2z"
            />
            <path
              class="st0"
              d="M239.9,59.4v42.5c-2.6-0.6-6.3-1.2-10.9-1.2c-11.5,0-26.7,4.9-32.4,12.6v88.3h-44.2V63.1h44.2V80
      			C205.8,68.8,223.3,59.4,239.9,59.4z"
            />
            <path
              class="st0"
              d="M381.7,181.7c-9.3,9.7-21.1,16.9-34.5,20.4l0.7-0.1L381.7,181.7z"
            />
            <path
              class="st0"
              d="M539.8,92.8c-8.7-26-34.4-34.1-61.4-34.1c-21.2,0-45,6.3-62.8,21.5l7.2,12.6l8.6,15.2
      			c11.2-9.5,25.5-14.6,39.3-14.6c17.8,0,28.1,8,28.1,20.1v16.6c-8.3-10.3-24.7-16.1-43-16.1c-7.1,0-14.8,1.2-21.9,4.1
      			c-14,5.7-25.7,18-25.7,40.3c0,24.8,16.7,39,34.1,43.8c0.7,0.2,1.4,0.4,2.1,0.5c3.8,0.9,7.7,1.3,11.4,1.3c4.3,0,8.5-0.4,12.5-1.2
      			c1.8-0.3,3.5-0.7,5.2-1.2c10.6-2.8,19.6-8.1,25.2-14.9v13.8h44.1V114C542.9,105.9,541.8,98.8,539.8,92.8z M498.8,165.1
      			c-4.6,6.6-14.9,10-24.7,10c-11.8,0-22.1-5.2-22.1-16.1c0-10.9,10.3-16.1,22.1-16.1c9.8,0,20.1,3.4,24.7,9.8V165.1z"
            />
            <path
              class="st0"
              d="M605.3,201.1c-5.9-2.5-10.7-6.2-14.1-11.1C595.1,194.7,599.9,198.5,605.3,201.1z"
            />
            <path
              class="st0"
              d="M656.2,101.5h-28.1v19.6c-1.4-0.1-2.8-0.2-4.2-0.2c-18.2,0-33.7,11.5-39.6,27.5v-46.9h-22.9V63.1h22.9V25.2
      			h43.9v37.9h28.1V101.5z"
            />
            <path
              class="st0"
              d="M660.2,195.9c-2.8,2.6-6.9,4.9-12.4,6.6c-5.1,1.5-11.3,2.5-18.7,2.6c12-1.5,22.4-7.9,29.1-17.2L660.2,195.9z"
            />
            <path
              class="st0"
              d="M725.5,26.2c0,14-11.2,25.5-25.2,25.5s-25.2-11.5-25.2-25.5S686.3,1,700.3,1S725.5,12.2,725.5,26.2z"
            />
            <polygon
              class="st0"
              points="891.5,63.1 879.4,93.8 873.7,108.5 837,201.6 790,201.6 760.2,125.9 747.6,93.8 735.6,63.1 782,63.1
      			792.9,93.8 802.1,119.5 813.2,150.9 825.8,115.8 833.8,93.8 844.8,63.1 		"
            />
            <path
              class="st0"
              d="M939.8,116.6c1.4-8,6.3-18.3,18-22.2c3-1,6.5-1.6,10.4-1.6c20.3,0,27.5,14.1,28.7,23.8H939.8z M968.2,204l2,0
      			c21.2,0,44.1-6,57.9-18.4l-18.6-27.5c-7.7,7.5-24.6,11.8-34.4,11.8c-20.1,0-32.1-11.8-34.7-24.7h98.6v-9.5
      			c0-47-29.8-77.2-70.8-77.2c-28.1,0-50.7,13.6-63.2,34.1c-2,3.3-3.8,6.8-5.2,10.5c-3.4,8.6-5.3,18-5.3,27.9
      			c0,44.3,31.8,71.9,73.5,72.8L968.2,204z"
            />
          </g>
        </g>
        <polyline
          class="st0"
          points="678.2,201.4 678.2,63.1 722.3,63.1 722.3,201.4 "
        />
        <path
          class="st0"
          d="M395.3,135.8c0-10-1.3-19.2-3.8-27.5c-1.7-5.6-3.9-10.8-6.6-15.5c-12.1-21.6-33.9-34.1-60.4-34.1
      	c-9.1,0-17.7,1.4-25.5,4.1c-25.9,11.5-43.9,37.5-43.9,67.8c0,37.8,28.1,69,64.5,73.5c3,0.4,6,0.5,9,0.5c6.4,0,12.7-0.8,18.6-2.4
      	c13.3-3.5,25.2-10.7,34.5-20.4l-15.9-23.5c-7.7,7.5-24.7,11.8-34.4,11.8c-20.1,0-32.1-11.8-34.7-24.7h98.6V135.8z M296.1,116.6
      	c1.7-10,9.2-23.8,28.4-23.8c6.4,0,11.5,1.4,15.5,3.6c8.7,4.8,12.4,13.5,13.1,20.2H296.1z"
        />
        <path
          class="st0"
          d="M658.1,187.8c-6.7,9.3-17.1,15.8-29.1,17.2h0c-1.7,0.2-3.4,0.3-5.2,0.3c-6.6,0-12.9-1.5-18.5-4.2
      	c-5.5-2.7-10.3-6.5-14.1-11.1c0,0,0,0,0-0.1c-4.6-6.5-7-15.1-7-25.6v-15.9c6-16.1,21.4-27.5,39.6-27.5c1.4,0,2.8,0.1,4.2,0.2V152
      	c0,7.1,3.6,12.6,9.8,13.8c0.8,0.1,1.6,0.2,2.5,0.2c4.9,0,9.7-1.7,11.2-3.4l1.9,7.4L658.1,187.8z"
        />
      </svg>
</div>
body {
	position: fixed;
	height: 100%;
  overflow: hidden;
}

canvas {
	position: absolute;
	width: 100%;
	height: 100vh;
	top: 0;
	left: 0;
}

.mask {
	position: absolute;
	z-index: 2;
	background: white;
	height: 100vh;
	width: 100vw;
	mix-blend-mode: screen;
	/* display: none; */
}

svg {
	width: 90%;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
}
var vertex = `
		attribute vec2 uv;
		attribute vec2 position;
		varying vec2 vUv;
		void main() {
				vUv = uv;
				gl_Position = vec4(position, 0, 1);
		}
`;
var fragment = `
		precision highp float;
		precision highp int;
		uniform sampler2D tWater;
		uniform sampler2D tFlow;
		uniform float uTime;
		varying vec2 vUv;
		uniform vec4 res;
		uniform vec2 img;

		vec2 centeredAspectRatio(vec2 uvs, vec2 factor){
				return uvs * factor - factor /2. + 0.5;
		}

		void main() {

			// R and G values are velocity in the x and y direction
			// B value is the velocity length
			vec3 flow = texture2D(tFlow, vUv).rgb;

			vec2 uv = .5 * gl_FragCoord.xy / res.xy ;

			// vec2 uv = .5 * gl_FragCoord.xy / res.xy ;
			vec2 myUV = (uv - vec2(0.5))*res.zw + vec2(0.5);
			myUV -= flow.xy * (0.15 * 1.2);

			vec2 myUV2 = (uv - vec2(0.5))*res.zw + vec2(0.5);
			myUV2 -= flow.xy * (0.125 * 1.2);

			vec2 myUV3 = (uv - vec2(0.5))*res.zw + vec2(0.5);
			myUV3 -= flow.xy * (0.10 * 1.4);

			vec3 tex = texture2D(tWater, myUV).rgb;
			vec3 tex2 = texture2D(tWater, myUV2).rgb;
			vec3 tex3 = texture2D(tWater, myUV3).rgb;

			gl_FragColor = vec4(tex.r, tex2.g, tex3.b, 1.0);
		}
`;
{
	var _size = [2048, 1638];
	var renderer = new ogl.Renderer({ dpr: 2 });
	var gl = renderer.gl;
	document.body.appendChild(gl.canvas);

	// Variable inputs to control flowmap
	var aspect = 1;
	var mouse = new ogl.Vec2(-1);
	var velocity = new ogl.Vec2();
	function resize() {
		gl.canvas.width = window.innerWidth * 2.0;
		gl.canvas.height = window.innerHeight * 2.0;
		gl.canvas.style.width = window.innerWidth + "px";
		gl.canvas.style.height = window.innerHeight + "px";

		var a1, a2;
		var imageAspect = _size[1] / _size[0];
		if (window.innerHeight / window.innerWidth < imageAspect) {
			a1 = 1;
			a2 = window.innerHeight / window.innerWidth / imageAspect;
		} else {
			a1 = window.innerWidth / window.innerHeight * imageAspect;
			a2 = 1;
		}
		mesh.program.uniforms.res.value = new ogl.Vec4(
			window.innerWidth,
			window.innerHeight,
			a1,
			a2
		);

		renderer.setSize(window.innerWidth, window.innerHeight);
		aspect = window.innerWidth / window.innerHeight;
	}
	var flowmap = new ogl.Flowmap(gl, {
		falloff: 0.3,
		dissipation: 0.92,
		alpha: 0.5
	});
	// Triangle that includes -1 to 1 range for 'position', and 0 to 1 range for 'uv'.
	var geometry = new ogl.Geometry(gl, {
		position: {
			size: 2,
			data: new Float32Array([-1, -1, 3, -1, -1, 3])
		},
		uv: { size: 2, data: new Float32Array([0, 0, 2, 0, 0, 2]) }
	});
	var texture = new ogl.Texture(gl, {
		minFilter: gl.LINEAR,
		magFilter: gl.LINEAR
	});
	var img = new Image();
	img.onload = () => (texture.image = img);
	img.crossOrigin = "Anonymous";
	img.src = "https://robindelaporte.fr/codepen/bg3.jpg";

	var a1, a2;
	var imageAspect = _size[1] / _size[0];
	if (window.innerHeight / window.innerWidth < imageAspect) {
		a1 = 1;
		a2 = window.innerHeight / window.innerWidth / imageAspect;
	} else {
		a1 = window.innerWidth / window.innerHeight * imageAspect;
		a2 = 1;
	}

	var program = new ogl.Program(gl, {
		vertex,
		fragment,
		uniforms: {
			uTime: { value: 0 },
			tWater: { value: texture },
			res: {
				value: new ogl.Vec4(window.innerWidth, window.innerHeight, a1, a2)
			},
			img: { value: new ogl.Vec2(_size[1], _size[0]) },
			// Note that the uniform is applied without using an object and value property
			// This is because the class alternates this texture between two render targets
			// and updates the value property after each render.
			tFlow: flowmap.uniform
		}
	});
	var mesh = new ogl.Mesh(gl, { geometry, program });

	window.addEventListener("resize", resize, false);
	resize();

	// Create handlers to get mouse position and velocity
	var isTouchCapable = "ontouchstart" in window;
	if (isTouchCapable) {
		window.addEventListener("touchstart", updateMouse, false);
		window.addEventListener("touchmove", updateMouse, { passive: false });
	} else {
		window.addEventListener("mousemove", updateMouse, false);
	}
	var lastTime;
	var lastMouse = new ogl.Vec2();
	function updateMouse(e) {
		e.preventDefault();
	
		if (e.changedTouches && e.changedTouches.length) {
			e.x = e.changedTouches[0].pageX;
			e.y = e.changedTouches[0].pageY;
		}
		if (e.x === undefined) {
			e.x = e.pageX;
			e.y = e.pageY;
		}
		// Get mouse value in 0 to 1 range, with y flipped
		mouse.set(e.x / gl.renderer.width, 1.0 - e.y / gl.renderer.height);
		// Calculate velocity
		if (!lastTime) {
			// First frame
			lastTime = performance.now();
			lastMouse.set(e.x, e.y);
		}

		var deltaX = e.x - lastMouse.x;
		var deltaY = e.y - lastMouse.y;

		lastMouse.set(e.x, e.y);

		var time = performance.now();

		// Avoid dividing by 0
		var delta = Math.max(10.4, time - lastTime);
		lastTime = time;
		velocity.x = deltaX / delta;
		velocity.y = deltaY / delta;
		// Flag update to prevent hanging velocity values when not moving
		velocity.needsUpdate = true;
	}
	requestAnimationFrame(update);
	function update(t) {
		requestAnimationFrame(update);
		// Reset velocity when mouse not moving
		if (!velocity.needsUpdate) {
			mouse.set(-1);
			velocity.set(0);
		}
		velocity.needsUpdate = false;
		// Update flowmap inputs
		flowmap.aspect = aspect;
		flowmap.mouse.copy(mouse);
		// Ease velocity input, slower when fading out
		flowmap.velocity.lerp(velocity, velocity.len ? 0.15 : 0.1);
		flowmap.update();
		program.uniforms.uTime.value = t * 0.01;
		renderer.render({ scene: mesh });
	}
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js
  2. https://robindelaporte.fr/codepen/bundle.js