Urgent.News

What's breaking now, across thousands of outlets.

Tech

Simulating Capillary Action in a WebGL Shader for a UI Press Effect

Most "ink spreading" effects on the web are the same three ingredients: a radial-gradient , a blur filter, and an opacity transition on a timer. They look fine. None of them are dye, and none of them move like dye. I wanted to see what changed if the effect actually followed the physics of a fluid wicking through cloth, so I built it as a real-time WebGL fragment shader, driven by the same…

Most ink spreading effects on the web share a similar formula: a radial-gradient, a blur filter, and an opacity transition that occurs over time. These effects appear visually acceptable but lack the realistic movement of actual dye. The goal was to create an effect that adheres to the physics of fluid wicking through cloth by building it as a real-time WebGL fragment shader.

This shader is driven by the Lucas–Washburn equation, which describes how a wetting front advances through a porous medium. The equation, formulated by Lucas in 1918 and extended by Washburn in 1921, indicates that the distance a capillary front travels is proportional to the square root of elapsed time: L ∝ √t.

This concept diverges from the typical exponential saturation curve, p(t) = 1 − e^(−kt), which accurately represents how wet a single point becomes as dye accumulates there, but not where the front actually reaches. When driven as a radius, the exponential curve quickly stalls, being roughly 92% stopped by the time it's three-quarters through its duration. Real capillary flow, on the other hand, maintains a significant fraction of its peak speed even at the end of the animation.

The equation requires two adjustments for practical use. First, at t=0, the equation predicts an infinite front speed, which is physically impossible. To address this, a small regularizing constant, t0, is introduced to ensure the front's initial speed is finite yet fast. A second adjustment is for anisotropy, as real fabric does not wet uniformly in all directions but rather more along the thread direction.

The function wickRadii takes the cover radius and the progress of the front, then returns the radii in the X and Y directions, resulting in an elongated front that better represents real fabric behavior. At progress = 0, the front is a perfect circle, and at progress = 1, it is noticeably elongated.

The shader runs on the GPU rather than in CSS, enabling a more realistic wet edge with a fibrous, torn appearance. This is achieved by using domain-warped value noise to displace the front outward unevenly, mimicking the natural behavior of capillary action. The two constants that parameterize the curve, the regularization constant and the anisotropy factor, are directly interpolated into the GLSL source code at load time, ensuring consistency across different engines.

A notable technical challenge is Safari's hard cap on the number of live WebGL contexts, which can cause surfaces to go dark mid-scroll. To overcome this, a shared offscreen canvas is used, allowing one WebGL context to render every dye surface, and each surface then blits the result onto its own cheap 2D canvas. This approach ensures that page-wide context count remains constant, regardless of the number of surfaces, and is verified by testing the actual count in a real browser.

The dye engine is integrated into Tantu, a React design system inspired by handloom weaving rather than soft-UI conventions. The system features square corners, a 12-thread grid, and three custom typefaces built from stroke skeletons. The implementation, including the shader and test suite, is available at https://github.com/rajatarun/aiweave, and a live demo is accessible at https://tantu-playground.netlify.app, where users can explore the effect in the "Vat" section.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

The Google TV Streamer now costs $50 more

Google raised the price of its 4K streaming box to $149, up $50 from its original $99 price. The new price is currently live at the Google Store and Best Buy, but Amazon appears to still be offering…

More from Monday 31 August →