I’ve released HEX TIDE Lite, the first piece in the new Trans Liquid series.
It is an interactive fluid simulation featuring Hawaiian blue liquid (approximately 40%) and air (approximately 60%) inside a container. You can drag to alter the flow, rotate the container 90 degrees, or generate waves. When rotated, the impact causes the liquid to briefly glow pink.
Technically, it is implemented in Three.js / WebGL using a custom cut-cell volume transport method combined with MAC pressure projection.
The most challenging part was reducing the computational load so that the piece runs smoothly on mobile devices as well. I spent considerable time tuning resolution, simulation steps, and rendering parameters to find a stable balance that performs well on both desktop and mobile.
HEX TIDE Lite
Any feedback or comments would be greatly appreciated.
1 Like
Tuning resolution for mobile is where I lost the most time too, and I ended up not picking a fixed value. On touch devices my scene starts at 1 px per CSS pixel and tries 1.25, then 1.5, undoing and locking any step whose 75th-percentile frame time drifts more than 15% above the fastest pace it has held that visit. A fixed 18.5 ms target fooled me on 120 Hz phones, where 60 fps is half speed and the GPU was already maxed. Did you settle on static presets, or does the sim adapt its grid or step count at runtime? With cut-cell transport, grid changes sound expensive.
1 Like
Thanks for sharing the details. One clarification: after several rounds of testing and refinement with Codex, the implementation evolved into direct WebGL code and no longer uses Three.js.
HEX TIDE Lite currently uses fixed settings: a DPR cap of 1.75, a 24³ simulation grid, and fixed ray-marching limits. There’s no frame-time-based quality adaptation at runtime. Simulation steps are at most 1/60 s, with up to eight substeps per frame. The actual number varies with elapsed time, but the budget isn’t performance-adaptive.
Lite retains cut-cell capacities, but uses simplified conservative transport driven by hydrostatic-head differences rather than the full version’s pressure projection. The grid stays fixed throughout the session, so there’s no runtime grid rebuilding or state transfer.
My priority for Lite has been smooth motion while preserving glass refraction and liquid transparency. Your point about 120 Hz is helpful: a fixed 18.5 ms threshold would miss the difference between maintaining 120 fps and dropping to 60.
Thanks, that clears it up, and moving to raw WebGL makes sense when the sim owns every pass. One thing I’d watch with up to eight substeps driven by elapsed time: on a phone that falls behind, a long frame asks for more substeps, which makes the next frame longer. The cap of eight stops a full spiral, but past that point the liquid quietly runs slower than real time instead of the frame rate dropping. Have you tried clamping elapsed time lower on touch devices, so a stutter costs a little sim time rather than eight steps at once?
Thanks for the thoughtful advice! I really appreciate you taking the time to look into the simulation.
The Lite version already clamps elapsed time to 50 ms, so a delayed frame normally calls for up to three substeps. I understand the trade-off you’re pointing out, though: lowering the clamp could reduce the workload, but the liquid might run slower relative to the container.
For now, I’m happy with the current balance and would rather preserve the visual quality and motion than optimize further for lower-spec devices. Thanks again for the helpful insight!