Foliage animation

Animate your backgrounds tree, or grass, with X, Y movement and global wind waves.

Shader code
shader_type canvas_item;

uniform float x_intensity = 3.0;
uniform float y_intensity = 0.5;
uniform float offset = 0.0;
uniform float speed : hint_range(0, 20) = 2.0;
uniform float wave_frequency : hint_range(0, 100) = 20;
uniform float wave_length : hint_range(50, 800) = 200.0;

void fragment() {
	vec2 real_uv = vec2(UV.x, UV.y);
	
	vec2 vecToBottom = vec2(1, 1) - UV.y; 
	float distToBottom = length(vecToBottom);
	
	float final_speed = TIME * (speed / 4.0) + offset;
	
	float time_var = (cos(final_speed) * cos(final_speed * 4.0) * cos(final_speed * 2.0))/(200.0);
	float time_var2 = (cos(final_speed) * cos(final_speed * 6.0) * cos(final_speed * 2.0))/(200.0);
	
	float wave_from_x = (cos(real_uv.x * 100.0)/1000.0);
	float wave_large_from_x = cos(TIME + (real_uv.x * wave_frequency))/wave_length;
	
	float wave_from_y = (cos(real_uv.y * 99000.0)/90000.0);
	
	float new_x = real_uv.x + time_var * (distToBottom * x_intensity) + wave_from_x + (wave_large_from_x);
	float new_y = real_uv.y + time_var2 * (distToBottom * y_intensity);
	
	vec2 new_uv1 = vec2(new_x, new_y);
	vec4 new_texture = texture(TEXTURE, new_uv1);
	
	if(new_texture.rgb != vec3(1,1,1)){
		COLOR.rgba = new_texture.rgba;
	}
}
Tags
animation, movement, time, 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.

Related shaders

Foliage Wind Shader

Wobbly Effect – Hand painted animation

Undertale Animation Skew

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Nick
Nick
2 months ago

Hey, thank you for such a great shader! And I am noob 🙂
I have MeshInstanse, with QuadMesh and Surface Material Override. This Surface Material Override has Albedo (main texture) and NormalMap. So, I’ve converted this Material Override to Shader. And then inserted your code.
But my shader has format: shader_type spatial;
So, I have an error in these lines:

if(new_texture.rgb != vec3(1,1,1)){
		COLOR.rgba = new_texture.rgba;

I’ve tried to change ALBEDO or NORMAL MAP, but shader works weird: my main texture and normal map are not synchronized. This is my code for now:

 
Code
shader_type spatial; render_mode blend_mix,depth_draw_always,cull_back,diffuse_burley,specular_schlick_ggx; uniform vec4 albedo : source_color; uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_disable; uniform float alpha_scissor_threshold; uniform float point_size : hint_range(0,128); uniform float roughness : hint_range(0,1); uniform sampler2D texture_metallic : hint_default_white,filter_linear_mipmap,repeat_disable; uniform vec4 metallic_texture_channel; uniform sampler2D texture_roughness : hint_roughness_r,filter_linear_mipmap,repeat_disable; uniform float specular; uniform float metallic; uniform sampler2D texture_normal : hint_roughness_normal,filter_linear_mipmap,repeat_disable; uniform float normal_scale : hint_range(-16,16); uniform vec3 uv1_scale; uniform vec3 uv1_offset; uniform vec3 uv2_scale; uniform vec3 uv2_offset; uniform float x_intensity = 1.0; uniform float y_intensity = 0.5; uniform float offset = 0.0; uniform float speed : hint_range(0, 20) = 20.0; uniform float wave_frequency : hint_range(0, 100) = 100; uniform float wave_length : hint_range(50, 800) = 50.0; void vertex() { //UV=UV*uv1_scale.xy+uv1_offset.xy; //VERTEX.x += 0.1*UV.y - sin(10.0*TIME)*sin(5.0*TIME)*0.002*(1.0*UV.y - 0.8); } void fragment() { vec2 base_uv = UV; vec4 albedo_tex = texture(texture_albedo,base_uv); ALBEDO = albedo.rgb * albedo_tex.rgb; float metallic_tex = dot(texture(texture_metallic,base_uv),metallic_texture_channel); METALLIC = metallic_tex * metallic; vec4 roughness_texture_channel = vec4(1.0,0.0,0.0,0.0); float roughness_tex = dot(texture(texture_roughness,base_uv),roughness_texture_channel); ROUGHNESS = roughness_tex * roughness; SPECULAR = specular; NORMAL_MAP = texture(texture_normal,base_uv).rgb; NORMAL_MAP_DEPTH = normal_scale; ALPHA *= albedo.a * albedo_tex.a; ALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold; vec2 real_uv = vec2(UV.x, UV.y); vec2 vecToBottom = vec2(1, 1) - UV.y;  float distToBottom = length(vecToBottom); float final_speed = TIME * (speed / 4.0) + offset; float time_var = (cos(final_speed) * cos(final_speed * 4.0) * cos(final_speed * 2.0))/(200.0); float time_var2 = (cos(final_speed) * cos(final_speed * 6.0) * cos(final_speed * 2.0))/(200.0); float wave_from_x = (cos(real_uv.x * 100.0)/1000.0); float wave_large_from_x = cos(TIME + (real_uv.x * wave_frequency))/wave_length; float wave_from_y = (cos(real_uv.y * 99000.0)/90000.0); float new_x = real_uv.x + time_var * (distToBottom * x_intensity) + wave_from_x + (wave_large_from_x); float new_y = real_uv.y + time_var2 * (distToBottom * y_intensity); vec2 new_uv1 = vec2(new_x, new_y); vec4 new_texture = texture(texture_albedo, new_uv1); if(new_texture.rgb != vec3(1,1,1)){ ALBEDO.rgb = new_texture.rgb; NORMAL_MAP.rgb = new_texture.rgb; } }