body {
margin: 0;
}
canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
import {
Renderer,
Program,
Texture,
Mesh,
Vec2,
Flowmap,
Triangle,
TextureLoader
} from "https://cdn.skypack.dev/ogl@0.0.93";
const vertex = /* glsl */ `
attribute vec2 uv;
attribute vec2 position;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 0, 1);
}
`;
const fragment = /* glsl */ `
precision highp float;
uniform sampler2D tImage;
uniform sampler2D tFlow;
uniform float uTime;
varying vec2 vUv;
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;
// Use flow to adjust the uv lookup of a texture
vec2 uv = vUv;
uv += (flow.rg * flow.b * 50.0);
// uv += (flow.rg * 5.0);
vec3 tex = texture2D(tImage, uv).rgb;
gl_FragColor.rgb = tex;
// gl_FragColor.rgb = flow;
gl_FragColor.a = 1.0;
}
`;
const renderer = new Renderer();
const gl = renderer.gl;
document.body.appendChild(gl.canvas);
const mouse = new Vec2(0.5);
const lastMouse = new Vec2(0.5);
const velocity = new Vec2();
let aspect = 1;
function resize() {
aspect = renderer.width / renderer.height;
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener("resize", resize, false);
resize();
const flowmap = new Flowmap(gl, { falloff: 0.4, dissipation: 0.99, size: 512 });
const geometry = new Triangle(gl);
const texture = TextureLoader.load(gl, {
wrapS: gl.MIRRORED_REPEAT,
wrapT: gl.MIRRORED_REPEAT,
src: {
jpg:
"https://images.unsplash.com/photo-1572040917409-60ca0cfcc2df?crop=entropy&cs=tinysrgb&fm=jpg&ixlib=rb-1.2.1&q=80&raw_url=true&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1024"
}
});
const program = new Program(gl, {
vertex,
fragment,
uniforms: {
uTime: { value: 0 },
tImage: { value: texture },
tFlow: flowmap.uniform
}
});
const mesh = new Mesh(gl, { geometry, program });
function updateMouse({ clientX, clientY }) {
const rect = renderer.gl.canvas.getBoundingClientRect();
const aspect = renderer.width / renderer.height;
const x = (clientX - rect.x) / renderer.width;
const y = 1 - (clientY - rect.y) / renderer.height;
mouse.set(x, y);
}
const isTouchCapable = "ontouchstart" in window;
if (isTouchCapable) {
window.addEventListener("touchstart", updateMouse, false);
window.addEventListener("touchmove", updateMouse, false);
} else {
window.addEventListener("mousemove", updateMouse, false);
}
const spring = 0.02;
const friction = 0.85;
const springVel = new Vec2();
function update(t) {
springVel.copy(mouse).sub(lastMouse).multiply(spring);
velocity.add(springVel).multiply(friction);
lastMouse.add(velocity);
flowmap.mouse.copy(lastMouse);
flowmap.velocity.copy(velocity);
flowmap.aspect = aspect;
flowmap.update();
renderer.render({ scene: mesh });
requestAnimationFrame(update);
}
requestAnimationFrame(update);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.