<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre" -->

---
title: Spreading Liquid with Three.js | daily.dev
description: This article explains how the author built a liquid-spreading foundation effect in three.js, originally made for a 2021 cosmetics promo. It reuses the velocity...
canonical: https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Spreading Liquid with Three.js | daily.dev
og:description: This article explains how the author built a liquid-spreading foundation effect in three.js, originally made for a 2021 cosmetics promo. It reuses the velocity...
og:url: https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre
og:image: https://api.daily.dev/og/posts/pPGnv0Dre.png
og:image:alt: Spreading Liquid with Three.js
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Spreading Liquid with Three.js

**[Hacker News](https://daily.dev/sources/hn)** · 10 min read · 9 upvotes · 1 comments

## Summary

This article explains how the author built a liquid-spreading foundation effect in three.js, originally made for a 2021 cosmetics promo. It reuses the velocity map from an earlier Stable Fluids article and adds a height map FBO to represent liquid thickness, updated each frame via backtraced advection. An alpha map records a historical maximum to keep visible traces after liquid thins out. Surface normals are computed from the height map in the fragment shader and rendered with a Matcap texture. The author notes the simulation isn't volume-conserving, and bonus demos compare 8-bit versus 32-bit texture precision and mix three colored liquids using a simplified Kubelka-Munk model.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://mofu-dev.com/en/blog/fluid-foundation>

## Questions this post answers

### How do you simulate liquid thickness spreading in a fragment shader without deforming geometry?

Use a height map stored in an FBO to represent liquid thickness, updated each frame by sampling a velocity map from a fluid simulation. For each pixel, subtract thickness based on local velocity strength, then add thickness sampled from a backtraced source UV position found by tracing velocity backward with a dt-scaled offset, alternating between two FBOs per frame.

_Developers prototyping shader-based fluid effects can find similar GLSL techniques curated on daily.dev._

### How can you make liquid or paint traces remain visible on a surface after the liquid has thinned out in a shader?

Store a historical maximum value in an alpha map's R channel, updated each frame as the max of the current thickness-derived value and the previous maximum, and blend it with the current value in the G channel. Sampling the G channel for final opacity keeps color visible even as thickness drops toward zero, mimicking liquid traces without modeling drying or absorption.

_Anyone building sticky visual trail effects can track shader techniques like this one on daily.dev._

### Why does an 8-bit texture produce visible banding in normals calculated from a height map, compared to a 32-bit float texture?

An 8-bit texture only stores 256 levels per channel, which quantizes height values and creates visible stepped contours in normals and shading once lighting is calculated from them. A 32-bit floating-point texture stores much finer precision, producing smooth contours and shading instead of visible steps.

_Developers debugging banding artifacts in height-map-driven shaders can track precision tips like this on daily.dev._

## Community take

How the wider developer community reacted, aggregated from 1 discussion and 24 comments across hackernews (as of 2026-11-05).

**TL;DR:** Most commenters are impressed by the liquid-spreading demo and its color-mixing effects, while a side debate unfolds about the author's lament that LLMs will absorb such techniques without credit, plus a minor technical nitpick about whether three.js was even necessary.

**Sentiment:** 55% positive · 30% mixed · 15% skeptical

**The case for**

- Many found the effect visually impressive and 'magic', especially the color mixing reminiscent of mixing real paints.
- Some suggested practical extensions, like adapting it into a calligraphy application.
- The infinite-paint color mixing behavior was called out as a particularly cool emergent detail explained in the article.

**The pushback**

- Several noted the simulation doesn't conserve volume, causing fluid to vanish when spread inward.
- One commenter questioned why three.js was needed at all, comparing it to showcasing a CSS effect and crediting React.
- A recurring thread argued that LLMs scraping such techniques will deny original authors credit or recognition going forward.

**By community**

- hackernews (mixed): Technical appreciation for the demo is mixed with a long philosophical debate about authorship and credit in the age of LLMs, plus a minor critique of the choice to use three.js.

**Hottest debate:** Whether creators should feel bad about LLMs absorbing and reproducing techniques like this without crediting the original author.

**Open questions**

- Could the simulation be made volume-conserving?
- Is there a lighter-weight way to achieve the effect without three.js?

**Highlights**

> Next time someone wants to make a spreading liquid effect, their LLM is more likely to know how to make it. They won't have to read this work when looking for references, won't get to know the person who thought of this and shared it with the world. Surely it's at least understandable why the author could be feeling a bit sad about it?
> — [xpct on hackernews · 1 comments](https://news.ycombinator.com/item?id=50376033)

> We are social creatures, and wanting to impress fellow beings is part of the reason why we do original things. When you made something public domain pre-LLMs, you generally could expect people to give kudos to you. With LLMs, if you make something public and an LLM gobbles it up, not only you get zero credit but you also can’t convincingly claim to have come up with it (since anyone can just assume you used an LLM), and neither can anyone else (even if they have come up with it fully independently). If you don’t seek any recognition for your original work, then that’s fine, but I suspect you might be in a minority.
> — [strogonoff on hackernews](https://news.ycombinator.com/item?id=50376931)

> what is the point of three.js in this demo? It feels like showing me a CSS effect on a DIV and saying "built with React". It's a nice demo. But it's not doing anything that needs a giant library to do.
> — [socalgal2 on hackernews · 1 comments](https://news.ycombinator.com/item?id=50376412)

> This is neat. It doesn't seem to conserve volume. If you spread the blob "inward", all the fluid disappears and you get a tiny thin spot. That's a general problem I often run into with simulations. When you get it in the opposite direction it can have some very amusing results (e.g. energy in a physical system continues to increase).
> — [andai on hackernews · 2 comments](https://news.ycombinator.com/item?id=50375485)

> You can also make infinite paint by spinning a small circle, then cycling between larger and small circles! It seems it also converges to secondary colors over time if any other primary color is added. Very cool! They explain why this happens in the article.
> — [Tadpole9181 on hackernews](https://news.ycombinator.com/item?id=50375701)

**Source threads**

- [hackernews](https://news.ycombinator.com/item?id=50341576) · 150 points · 24 comments

## Community discussion

Top comments from developers on daily.dev.

**@akkitto** · 0 upvotes

> Damn! This is really fun! It feels so organic.

## Similar posts on daily.dev

- [Building an Infinite Liquid Glass Grid with Three.js, WebGPU, and TSL](https://daily.dev/posts/building-an-infinite-liquid-glass-grid-with-three-js-webgpu-and-tsl-cwvx0gsr8) · Codrops · 9 upvotes · 1 comments
- [Building a Dual-Scene Fluid X-Ray Reveal Effect in Three.js](https://daily.dev/posts/building-a-dual-scene-fluid-x-ray-reveal-effect-in-three-js-ajz5uu9x7) · Codrops · 3 upvotes · 0 comments
- [Fascinating Particle Simulation Created with WebGPU](https://daily.dev/posts/fascinating-particle-simulation-created-with-webgpu-q0z5bb1e6) · 80 LEVEL · 0 upvotes · 0 comments
- [Shaders 103 - smoke](https://daily.dev/posts/shaders-103---smoke-dqivsjx8i) · Brad Woods' Digital Garden · 1 upvotes · 0 comments

---

Tags: [#game-development](https://daily.dev/tags/game-development), [#webgl](https://daily.dev/tags/webgl), [#threejs](https://daily.dev/tags/threejs)

[View this post on daily.dev](https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Spreading Liquid with Three.js","url":"https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre"},"datePublished":"2026-11-05T10:27:26.951Z","dateModified":"2026-11-05T13:43:21.387Z","description":"This article explains how the author built a liquid-spreading foundation effect in three.js, originally made for a 2021 cosmetics promo. It reuses the velocity...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/75e47e13fa00f1489c36010bea0ee6df?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/75e47e13fa00f1489c36010bea0ee6df?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Hacker News","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Hacker News","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/hn","url":"https://daily.dev/sources/hn"},"commentCount":1,"discussionUrl":"https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":8},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":1}],"keywords":"game-development,webgl,threejs","timeRequired":"PT10M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Hacker News","item":"https://daily.dev/sources/hn"},{"@type":"ListItem","position":3,"name":"Spreading Liquid with Three.js"}]}
{"@context":"https://schema.org","@type":"WebPage","@id":"https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre","comment":[{"@type":"Comment","text":"Damn! This is really fun! It feels so organic.","datePublished":"2026-11-05T21:38:39.953Z","url":"https://daily.dev/posts/pPGnv0Dre#c-MYkmkv1BF","author":{"@type":"Person","name":"Daniel","url":"https://daily.dev/akkitto","image":"https://media.daily.dev/image/upload/s--FtwJqX4c--/f_auto/v1754900041/avatars/avatar_29TCpY2hJR72V3BlxPXzX?_a=BAMClqZW0"}}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/spreading-liquid-with-three-js-ppgnv0dre#faq","mainEntity":[{"@type":"Question","name":"How do you simulate liquid thickness spreading in a fragment shader without deforming geometry?","acceptedAnswer":{"@type":"Answer","text":"Use a height map stored in an FBO to represent liquid thickness, updated each frame by sampling a velocity map from a fluid simulation. For each pixel, subtract thickness based on local velocity strength, then add thickness sampled from a backtraced source UV position found by tracing velocity backward with a dt-scaled offset, alternating between two FBOs per frame. Developers prototyping shader-based fluid effects can find similar GLSL techniques curated on daily.dev."}},{"@type":"Question","name":"How can you make liquid or paint traces remain visible on a surface after the liquid has thinned out in a shader?","acceptedAnswer":{"@type":"Answer","text":"Store a historical maximum value in an alpha map's R channel, updated each frame as the max of the current thickness-derived value and the previous maximum, and blend it with the current value in the G channel. Sampling the G channel for final opacity keeps color visible even as thickness drops toward zero, mimicking liquid traces without modeling drying or absorption. Anyone building sticky visual trail effects can track shader techniques like this one on daily.dev."}},{"@type":"Question","name":"Why does an 8-bit texture produce visible banding in normals calculated from a height map, compared to a 32-bit float texture?","acceptedAnswer":{"@type":"Answer","text":"An 8-bit texture only stores 256 levels per channel, which quantizes height values and creates visible stepped contours in normals and shading once lighting is calculated from them. A 32-bit floating-point texture stores much finer precision, producing smooth contours and shading instead of visible steps. Developers debugging banding artifacts in height-map-driven shaders can track precision tips like this on daily.dev."}}]}
```

