Shader based foliage wind in Godot 4
Last Updated on 29. January 2025
I’m currently developing an unannounced video game in the Godot engine. To bring my vegetation to life, I needed a vertex shader that allows me to have trees sway in the wind and have their branches move at the tips. This article gives a rough overview over my approach. It’s not a detailed tutorial, but I share my entire shader graph both as code and as a picture. Feel free to use and modify it. Attribution is always welcome but not required.
As a base for the movement, I use FastNoiseLite texture nodes that are panned over time. These noises are then fed into the vertex position data of my material. By themselves, these noises would move all tree vertices, but to simulate wind, I want to affect the branch tips, but not their bases. I also do not want the trunk to move. And I also need to move the bases of my branches to stick to the moving trunk.
Vertex color masks
I use vertex color masks that are created in Blender to solve these problems. This is what the tree’s vertex colors look like:
It looks complicated, but it’s just the outcome of two simple masks. The first mask is a linear gradient in the red channel. This gradient is multiplied as a factor with all motion. This keeps the trunk in place and makes the top sway. It also reduces the motion of branches that are closer to the ground.
Because branches and the trunk share the same values at the same vertical height, branches move in unison with the trunk.
The second mask is in the green channel. It’s a gradient from branch base to tip. This keeps the branch’s base from moving around and only allows the tips to flutter.
Adding world space offsets
With just the masks and the noise, every tree would move exactly the same. You can see at the end of the video that the trees aren’t exectly the same, it’s as if the wind moves over them in larger gusts. This is done by feeding each tree node’s world position as a seed into a RandomRange node. This is then added to the Time, which in turn is used as an offset for the noise panner. By doing this, each tree becomes uniquely affected by the wind. That is, as long as the trees aren’t perfectly evenly spaced.
Making rotated trees sway in the correct direction
There’s one big remaining problem. Trees only sway in the same rotation as long as the tree nodes aren’t rotated in the scene. Rotating them is necessary though to avoid repeating patterns. But it also causes rotated trees to sway in different directions, because the vertices are displaced locally, not globally.
I solve this by feeding the vertex motion into a TransformVectorMult node, set the node to B*A and use the model_matrix as the other input. This applies the tree node’s rotation to the vertex motion and makes all trees – rotated or not – sway in the same direction.