2D wind sway

Make a sprite sway, like it is affected by the wind. See the animation below for example. There are several parameters to control:

  • Speed – The speed of the wind movement.
  • Min Strength – The minimal strength of the wind movement.
  • Max Strength – The maximal strength of the wind movement.
  • Strength Scale – Scalefactor for the wind strength.
  • Interval – The time between minimal and maximal strength changes.
  • Detail – The detail (number of waves) of the wind movement.
  • Distortion – The strength of geometry distortion.
  • Height Offset – The height where the wind begins to move. By default 0.0.
  • Offset – Set different moves for each asset.
Shader code
// original wind shader from https://github.com/Maujoe/godot-simple-wind-shader-2d/tree/master/assets/maujoe.simple_wind_shader_2d
// original script modified by HungryProton so that the assets are moving differently : https://pastebin.com/VL3AfV8D
//
// speed - The speed of the wind movement.
// minStrength - The minimal strength of the wind movement.
// maxStrength - The maximal strength of the wind movement.
// strengthScale - Scalefactor for the wind strength.
// interval - The time between minimal and maximal strength changes.
// detail - The detail (number of waves) of the wind movement.
// distortion - The strength of geometry distortion.
// heightOffset - The height where the wind begins to move. By default 0.0.

shader_type canvas_item;
render_mode blend_mix;

// Wind settings.
uniform float speed = 1.0;
uniform float minStrength : hint_range(0.0, 1.0) = 0.05;
uniform float maxStrength : hint_range(0.0, 1.0) = 0.01;
uniform float strengthScale = 100.0;
uniform float interval = 3.5;
uniform float detail = 1.0;
uniform float distortion : hint_range(0.0, 1.0);
uniform float heightOffset : hint_range(0.0, 1.0);

// With the offset value, you can if you want different moves for each asset. Just put a random value (1, 2, 3) in the editor. Don't forget to mark the material as unique if you use this
uniform float offset = 0; 


float getWind(vec2 vertex, vec2 uv, float time){
    float diff = pow(maxStrength - minStrength, 2.0);
    float strength = clamp(minStrength + diff + sin(time / interval) * diff, minStrength, maxStrength) * strengthScale;
    float wind = (sin(time) + cos(time * detail)) * strength * max(0.0, (1.0-uv.y) - heightOffset);
    
    return wind; 
}

void vertex() {
    vec4 pos = WORLD_MATRIX * vec4(0.0, 0.0, 0.0, 1.0);
    float time = TIME * speed + offset;
    //float time = TIME * speed + pos.x * pos.y  ; not working when moving...
    VERTEX.x += getWind(VERTEX.xy, UV, time);
}
Tags
2d, tree, vertex, wind
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from godotshaders

Invert color

Realistic Water

Pixel transition

Related shaders

Pixel Art Wind Sway (MeshInstance3D, Godot 4.0)

Billboard Sprite3D Sway (Godot 4.0)

3d Pixel Sway – Godot 4

Subscribe
Notify of
guest

15 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
mohd
mohd
3 years ago

how do you use the shader

summer
summer
3 years ago
Reply to  mohd

make a sprite node – see inspector of the sprite node – material – new shader material – shader – new shader and copy paste the code to the shader code panel

ZODY
4 months ago
Reply to  summer

I did the same thing and it didn’t work does it have to be a sprite tree ?

sarapan_malam
2 years ago

Thanks for creating this shader, I’ve used it in a few of my projects and I really like it.
I’m trying to do a little experiment by making the object skewed when the player touches it
https://sarapan-malam-games.itch.io/interactive-foliage

Jeno
Jeno
1 year ago

Thanks so much for this shader. The effect is really nice.
I tried applying it to many tree instances at once and noticed a fast performance drop. Is there any way to use this shader for large amounts of plants and foliage with good performance or would you suggest another method for that?

lpares12
lpares12
1 year ago

Just for people coming after me, after Godot4 beta9 WORLD_MATRIX has been renamed to MODEL_MATRIX

mxk
mxk
1 year ago

Any idea why this wouldn’t work with a Light2D node? It has a material attached and has coordinates too, but the shader has no effect when applied to a light texture?

Lennix
Lennix
1 year ago

this does not work under iOS, does anyone have an idea why? under PC/MacOS it works

Munucrafts
8 months ago

WORLD_MATRIX is now MODEL_MATRIX, in case anyone is stuck there. Have a nice day.

Roman
Roman
7 months ago

im getting an error message on line 22, (void vertex() {, saying that the void value is not allowed in the expression, anyone know why this happening?

BFVDev
BFVDev
6 months ago

for anyone wondering to make it work in godot 4. change world matrix to model matrix

foxingstar
foxingstar
16 days ago
Reply to  BFVDev

thanks

etherealxx
2 months ago

The info below the tags says that this shader is CC0. The original shader were licensed under MIT, so this modification/derivative should be licensed as MIT too.

Sai
Sai
1 month ago

in tilemaplayer, can not work!

Fxlmine
1 month ago
Reply to  Sai

It’s possible! Use a scene collection instead of a tile atlas and apply the shader to the scene instead.