2d fluid simulation on the GPU

Here is a simple 2d fluid solver I made as part of my masters thesis project. It was originally written in CUDA but has been moved to GLSL. The repo is here with some more information:


Let me know what you think!
touchFluid.toe (11.2 KB)

1 Like

This is excellent. Thanks for sharing. Here are some of my comments.

In the buoyancy shader, it seems like the direction of the buoyancy should be turned into a texture lookup rather than a constant.

vec2 buoy = (dt * (densTemp.b - ambTemp) * sigma - densTemp.g * kappa ) * vec2(0.01) * vec2(0., 1.);

That vec2(0., 1.) could come from a texture. Then we could make generative buoyancy maps and see some really interesting fluids.

You have “res” as a uniform on a lot of shaders. This generally isn’t necessary since you can refer to the input resolution and texel size with uTD2DInfos[0].res

Using expressions on GLSL TOPs can slow them down quite a bit, although this project runs at 60fps. Using a Parameter CHOP and exports would be more efficient at the risk of losing some exports once in a while.

Also, I’m curious since this project is packed full of features. Is there any fluid simulation concept that you haven’t included?

Hey David, thanks for the suggestions.

Glad to see you saw the buoyancy direction was hard coded. In making this, I had to make some choices that balanced simplicity and features, and for that one I chose simplicity. Actually, nearly every parameter can be spatialized with a texture: diffusion rate, curl amount, even delta time. You can go nuts. The nice thing with this version, as opposed to CUDA, is that it’s easily hackable which I encourage everyone to do.

The resolution parameter is definitely something I want to change. There were a lot of people having some major issues with the CUDA version and I wanted to push this out ASAP. I’ll move to using the built in uniforms. Just FYI, when changing the resolution, the Feedback TOPs need to be reset.

I didn’t realize using expressions in GLSL TOPs can be slow. Is there a reason for this? Does it apply to expressions on the resolution/Custom tab parameters or just everything, including uniforms? Honestly I’m not a Touch ninja and don’t really understand exports that well, so I use expressions all the time.

CFD is a huge topic. There are tons of things you can do. Some examples off the top of my head are free surface boundaries (non-solid boundaries, i.e. water vs air), combustion/chemical mixing, multiphase flow, and more accurate advection schemes such as the MacCormack method. You could also go in another direction entirely with SPH. There are many, many more phenomena out there. SIGGRAPH is always a big inspiration in that regard.

This is great, and many thanks for sharing!!

Regarding exports:

Expressions essentially end up getting evaluated every frame that a given op cooks, which is what ends up being costly.

Exports end up being more like pointers and don’t need to be evaluated.

You can see a whole breakdown of the various ways you can reference / export and their respective cooktimes here:


Long story short, expressions tend to be about 5x as expensive, though that’s always subject to their complexity.

Generally speaking, I tend to use exports on ops that cook frequently or every frame, and expressions when ops cook infrequently - though to be honest it’s frequently project and resource specific.

Ideologically, exports are set at the source and push to the destination; expressions are set at the destination and pull from the source.

There’s also a really good fluid sim project in Java here: [url]https://github.com/diwi/PixelFlow/tree/master/src/com/thomasdiewald/pixelflow/glsl/Fluid[/url] (MIT license)

It has some major savings in its jacobi shader github.com/diwi/PixelFlow/blob/ … acobi.frag
because it precomputes the obstacle in a single texture
github.com/diwi/PixelFlow/blob/ … ounds.frag

When you get rid of the python expressions and improve the shader this way, it’s a lot faster :slight_smile:

Thanks so much for the suggestions Matthew and David! I updated the repo with some of the changes you guys mentioned.

Matthew, that cooktimes tox is really cool and well put together, thanks for sharing. I removed all Python expressions on TOPs and switched to using exports. If I missed anything please let me know. I also removed the resolution parameter entirely- it’s now just based on the input resolution of the velocity/obstacle texture. If that changes, you still need to hit the Reset pulse to clear the Feedback TOPs.

Thanks for the heads up about PixelFlow David. Precomputing the obstacle neighbors is a super smart idea. I rolled that into touchFluid and linked to PixelFlow in the obstacleBounds.frag shader.

hi, any tips on how to change the resolution of this
i tried just changing the values in the constant and resetting but the fluid dosent move well in the area beyond 1280x720 in this snip you can see the fluid values (idk velocity?) are concentrated in the lower left 1280x720 of the 1920x1080

nothing makes me feel stupid as glsl…


if anyone is reading this you can get the fluid to flow through a higher res by resetting the “feedback jacobi” op

Is there a fix for Jacobi shader to run smoothly on an AMD card on OSX? I experience a big fps drop on the AMD, but on nvidia it works at 60fps.