Each inventive studio has its bizarre inner rituals.
Ours? A problem we name “12 Pens in 12 Months” — one experiment every month, no guidelines, no shoppers, simply play.
Someplace between caffeine and chaos, considered one of our devs made this — a wavy, hypnotic, jelly-like movement impact that immediately turned the workforce’s favourite. We didn’t plan to make something “severe”, however individuals began asking the way it works, and right here we’re — writing about it on Codrops!
The Idea
The thought began easy:
What if we may make movement that feels natural — not mechanical, not linear, however one thing that flows?
We needed that “liquid between two worlds” really feel — a movement that appears to breathe, stretch, and chill out.
At its core, it’s a mixture of:
- fragment shaders (to generate geometric wave-like cells)
- math-driven distortion (sine waves, ripples, and refraction)
- and requestAnimationFrame for easy, steady GPU updates.
perform draw(tms) {
const t = tms * 0.001;
// natural movement: a sine wave that lightly distorts the grid measurement over time
const wave = Math.sin(p.x * 0.01 + p.y * 0.015 + t) * 0.25;
const localCell = cell * (1.0 + wave * 0.2);
// ripple impact triggered by consumer interplay (click on)
float ripple = sin(R * 0.06 - dt * 6.0) * env;
// mixing the glass-like refraction with the bottom picture
vec3 col = combine(base, glass, inside);
gl_FragColor = vec4(col, 1.0);
}
requestAnimationFrame(draw);
How It Works
The magic trick right here is in how we recalculate the wave path each body.
As a substitute of animating DOM or CSS properties, we rebuild each pixel dynamically within the shader — body by body.
Every cell behaves like a residing floor — pulsing, refracting, and rippling with time.
Think about drawing a line with a rubber band — every anchor level follows the one earlier than it, with a little bit of delay and overshoot. That delay provides us that deliciously gooey, alive motion.
For efficiency causes, we use:
requestAnimationFramefor easy updates.- GPU-driven math — sine, refraction, ripple computed instantly within the shader.
- requestAnimationFrame to sync GPU frames with the browser’s refresh fee.
// discover the closest cell heart primarily based on the chosen form
void nearestCenter(int form, vec2 p, float cell, out vec2 c, out vec2 lp) {
if (form == 0) {
vec2 qr = hex_pixel_to_axial(p, cell);
vec2 qrr = hex_axial_round(qr);
c = hex_axial_to_pixel(qrr, cell);
lp = p - c;
} else {
vec2 g = flooring(p / cell + 0.5);
c = g * cell;
lp = p - c;
}
}
Presets & Variations
As soon as the core system was working, we couldn’t cease tweaking it.
As a substitute of mounted presets, we constructed a easy management panel — 4 sliders that management the shader parameters instantly:
- Cell measurement (
uCell) — density of the grid - Amplitude (
uAmp) — power of refraction - Chromatic shift (
uChrom) — quantity of colour separation - Velocity (
uSpeed) — how briskly the wave evolves
Altering simply considered one of these immediately transforms the temper of the movement — from mushy and fluid to sharp and energetic.
Each body, the app reads the dwell values from the sliders and sends them straight into the shader —
so any tiny change immediately ripples via the complete floor.
perform draw(tms) {
const t = tms * 0.001;
// dwell parameters from the UI → shader
gl.uniform1f(uCell, parseFloat(cellInp.worth));
gl.uniform1f(uAmp, parseFloat(ampInp.worth));
gl.uniform1f(uChrom, parseFloat(chromInp.worth));
gl.uniform1f(uSpeed, parseFloat(speedInp.worth));
gl.uniform1f(uTime, t);
// replace the video texture (if energetic)
if (videoReady) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoEl);
}
// render + subsequent body
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(draw);
}
Challenges Alongside the Method
In fact, it wasn’t all easy crusing (pun meant).
At one level the wave went full chaos — spikes, sparkles, every part breaking up.
Seems, our smoothing logic was off by one pixel (actually).
One other humorous bug: when testing on high-refresh displays, the movement appeared too easy — prefer it misplaced its texture. So we had so as to add a contact of imperfection to convey again the “handmade” vibe.
Attempt It Your self
The entire setup is open and straightforward to remix — simply fork it and begin taking part in with the parameters.
Attempt altering:
- the variety of factors
- the easing curves
- the colour gradients
We’d like to see what sort of waves you make — tag us or ship your remix!
Closing Ideas
Generally the most effective concepts come from not attempting too exhausting.
This one was speculated to be a fast inner experiment — nevertheless it changed into one thing oddly satisfying and visually wealthy.
We hope you take pleasure in it as a lot as we loved breaking (and fixing) it.
Made with ❤️ by Blacklead Studio as a part of our 12 Pens in 12 Months inventive problem.






![The Most Searched Issues on Google [2025]](https://blog.aimactgrow.com/wp-content/uploads/2025/06/most-searched-keywords-google-sm-120x86.png)

