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 });
}
}
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%);
}
<script src="https://robindelaporte.fr/codepen/bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
<div class="mask">
<svg id="Layer_1" width="500.25" height="300.401" viewBox="0 0 124.25 35.401" xmlns="http://www.w3.org/2000/svg"><g id="svgGroup" stroke-linecap="round" fill-rule="evenodd" font-size="9pt" stroke="#000" stroke-width="0.25mm" fill="" ><path class="st0" d="M 0.287 14.019 A 28.282 28.282 0 0 0 0 18.15 A 32.323 32.323 0 0 0 0.167 21.511 Q 0.796 27.521 3.8 31 Q 7.6 35.4 14.525 35.4 Q 21.45 35.4 25.875 30.575 Q 30.3 25.75 30.3 16.75 Q 30.3 12.5 29.225 9.3 Q 28.579 7.375 27.769 5.984 A 10.057 10.057 0 0 0 26.625 4.375 Q 25.1 2.65 22.95 1.625 A 22.239 22.239 0 0 0 22.015 1.205 Q 21.254 0.884 20.556 0.663 A 11.47 11.47 0 0 0 19.1 0.3 Q 17.4 0 15.55 0 A 14.963 14.963 0 0 0 10.221 0.967 A 17.387 17.387 0 0 0 5.45 3.75 A 10.119 10.119 0 0 0 4.91 4.213 Q 3.765 5.263 2.846 6.738 A 17.31 17.31 0 0 0 1.5 9.425 A 17.43 17.43 0 0 0 1.384 9.722 Q 0.631 11.696 0.287 14.019 Z M 15.1 30.7 Q 24.05 30.7 24.05 17.55 A 28.133 28.133 0 0 0 23.703 12.915 Q 22.273 4.4 14.95 4.4 A 9.734 9.734 0 0 0 12.536 4.685 A 7.198 7.198 0 0 0 9.675 6.125 Q 7.6 7.85 6.8 10.425 Q 6 13 6 16.4 A 33.631 33.631 0 0 0 6.32 21.26 Q 7.706 30.7 15.1 30.7 Z" id="0" vector-effect="non-scaling-stroke"/><path class="st0" d="M 33.7 13.4 L 33.7 10.8 A 1.08 1.08 0 0 1 33.737 10.503 Q 33.833 10.17 34.172 10.082 A 1.105 1.105 0 0 1 34.45 10.05 L 41.3 10.05 A 0.819 0.819 0 0 1 41.618 10.108 Q 41.978 10.258 42.05 10.8 L 42.45 13.7 A 8.722 8.722 0 0 1 45.429 10.703 Q 47.085 9.726 49.233 9.542 A 11.966 11.966 0 0 1 50.25 9.5 A 9.347 9.347 0 0 1 52.894 9.848 Q 55.914 10.738 57.1 13.9 A 9.588 9.588 0 0 1 59.583 11.134 Q 61.533 9.704 64.18 9.526 A 11.433 11.433 0 0 1 64.95 9.5 A 10.083 10.083 0 0 1 68.146 9.963 Q 72.659 11.47 72.7 17.882 A 18.445 18.445 0 0 1 72.7 18 L 72.7 30.85 L 75.55 30.85 A 1.08 1.08 0 0 1 75.847 30.887 Q 76.18 30.983 76.268 31.322 A 1.105 1.105 0 0 1 76.3 31.6 L 76.3 34.05 A 1.08 1.08 0 0 1 76.263 34.347 Q 76.168 34.68 75.828 34.768 A 1.105 1.105 0 0 1 75.55 34.8 L 64.55 34.8 A 1.08 1.08 0 0 1 64.253 34.763 Q 63.921 34.668 63.832 34.328 A 1.105 1.105 0 0 1 63.8 34.05 L 63.8 31.6 A 1.08 1.08 0 0 1 63.837 31.303 Q 63.933 30.97 64.272 30.882 A 1.105 1.105 0 0 1 64.55 30.85 L 67.1 30.85 L 67.1 20.5 A 19.73 19.73 0 0 0 67.04 18.905 Q 66.916 17.374 66.531 16.396 A 4.228 4.228 0 0 0 66.3 15.9 A 2.552 2.552 0 0 0 64.913 14.738 Q 64.155 14.45 63.075 14.45 A 7.356 7.356 0 0 0 61.458 14.618 Q 60.129 14.917 59.2 15.75 A 4.704 4.704 0 0 0 58.275 16.857 A 3.756 3.756 0 0 0 57.75 18.8 L 57.75 30.85 L 60.15 30.85 A 1.08 1.08 0 0 1 60.447 30.887 Q 60.78 30.983 60.868 31.322 A 1.105 1.105 0 0 1 60.9 31.6 L 60.9 34.05 A 1.08 1.08 0 0 1 60.863 34.347 Q 60.768 34.68 60.428 34.768 A 1.105 1.105 0 0 1 60.15 34.8 L 49.9 34.8 A 1.08 1.08 0 0 1 49.603 34.763 Q 49.271 34.668 49.182 34.328 A 1.105 1.105 0 0 1 49.15 34.05 L 49.15 31.6 A 1.08 1.08 0 0 1 49.187 31.303 Q 49.283 30.97 49.622 30.882 A 1.105 1.105 0 0 1 49.9 30.85 L 52.15 30.85 L 52.15 20.5 A 19.73 19.73 0 0 0 52.09 18.905 Q 51.966 17.374 51.581 16.396 A 4.228 4.228 0 0 0 51.35 15.9 A 2.534 2.534 0 0 0 50.001 14.758 Q 49.535 14.575 48.943 14.501 A 6.978 6.978 0 0 0 48.075 14.45 A 6.698 6.698 0 0 0 46.432 14.641 A 4.652 4.652 0 0 0 44.175 15.925 A 5.128 5.128 0 0 0 43.106 17.519 A 4.719 4.719 0 0 0 42.75 19.35 L 42.75 30.85 L 45.8 30.85 A 1.08 1.08 0 0 1 46.097 30.887 Q 46.43 30.983 46.518 31.322 A 1.105 1.105 0 0 1 46.55 31.6 L 46.55 34.05 A 1.08 1.08 0 0 1 46.513 34.347 Q 46.418 34.68 46.078 34.768 A 1.105 1.105 0 0 1 45.8 34.8 L 34.5 34.8 A 1.08 1.08 0 0 1 34.203 34.763 Q 33.871 34.668 33.782 34.328 A 1.105 1.105 0 0 1 33.75 34.05 L 33.75 31.6 A 1.08 1.08 0 0 1 33.787 31.303 Q 33.883 30.97 34.222 30.882 A 1.105 1.105 0 0 1 34.5 30.85 L 37.15 30.85 L 37.15 14.15 L 34.45 14.15 A 1.08 1.08 0 0 1 34.153 14.113 Q 33.821 14.018 33.732 13.678 A 1.105 1.105 0 0 1 33.7 13.4 Z" id="1" vector-effect="non-scaling-stroke"/><path class="st0" d="M 93.5 19.95 L 93.5 18.2 A 9.647 9.647 0 0 0 93.39 16.682 Q 93.268 15.915 93.008 15.33 A 2.968 2.968 0 0 0 91.5 13.75 A 4.051 4.051 0 0 0 90.823 13.539 Q 90.105 13.377 89.09 13.354 A 15.117 15.117 0 0 0 88.75 13.35 A 5.387 5.387 0 0 0 87.177 13.563 Q 85.452 14.0