Particle Flipbook Flowmap Smoothing

This shader uses a flowmap to interpolate flipbook animation frames for smoother flipbook playback.

I used one of the free CC0 flipbooks available here for my examples: https://blog.unity.com/engine-platform/free-vfx-image-sequences-flipbooks

And I generated the flowmap with this free tool: https://www.facedownfx.com/

Shader code
shader_type spatial;
render_mode unshaded;

uniform vec4 albedo : source_color;
uniform sampler2D texture_albedo : source_color,filter_linear_mipmap,repeat_disable;
uniform sampler2D texture_flow : hint_normal,filter_linear_mipmap,repeat_disable;
uniform int particles_anim_h_frames;
uniform int particles_anim_v_frames;
uniform bool particles_anim_loop;
uniform bool smoothing = false;
uniform float flow_strength = 0.015;

varying vec2 next_UV;
varying float timer;

void vertex() {
	mat4 mat_world = mat4(normalize(INV_VIEW_MATRIX[0]), normalize(INV_VIEW_MATRIX[1]) ,normalize(INV_VIEW_MATRIX[2]), MODEL_MATRIX[3]);
	mat_world = mat_world * mat4(vec4(cos(INSTANCE_CUSTOM.x), -sin(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(sin(INSTANCE_CUSTOM.x), cos(INSTANCE_CUSTOM.x), 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
	MODELVIEW_MATRIX = VIEW_MATRIX * mat_world;
	MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX);
	float h_frames = float(particles_anim_h_frames);
	float v_frames = float(particles_anim_v_frames);
	float particle_total_frames = float(particles_anim_h_frames * particles_anim_v_frames);
	float particle_frame = floor(INSTANCE_CUSTOM.z * float(particle_total_frames));
	if (!particles_anim_loop) {
		particle_frame = clamp(particle_frame, 0.0, particle_total_frames - 1.0);
	} else {
		particle_frame = mod(particle_frame, particle_total_frames);
	}
	UV /= vec2(h_frames, v_frames);
	next_UV = UV;
	UV += vec2(mod(particle_frame, h_frames) / h_frames, floor((particle_frame + 0.5) / h_frames) / v_frames);
	next_UV += vec2(mod(particle_frame + 1.0, h_frames) / h_frames, floor((particle_frame + 1.0 + 0.5) / h_frames) / v_frames);
	timer = fract(INSTANCE_CUSTOM.y * h_frames * v_frames);
}

void fragment() {
	vec4 albedo_tex;
	if (smoothing) {
		vec2 flow_tex = texture(texture_flow, UV).rg;
		flow_tex -= 0.5;
		flow_tex *= 2.0;
		vec2 flow_uv = UV + flow_tex * timer * -flow_strength;
		vec2 reverse_flow_uv = next_UV + flow_tex * (1.0 - timer) * flow_strength;
		albedo_tex = mix(texture(texture_albedo, flow_uv), texture(texture_albedo, reverse_flow_uv), timer);
	} else {
		albedo_tex = texture(texture_albedo, UV);
	}
	albedo_tex *= COLOR;
	ALBEDO = albedo.rgb * albedo_tex.rgb;
	ALPHA *= albedo.a * albedo_tex.a;
}
Tags
flowmap, smoothing
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 Arnklit

World Normal Mix Shader

Wireframe Shader (Godot 4.0)

Related shaders

Particle Rope

Particle Process V2

Wandering Clipmap – Foliage Particle Process

Subscribe
Notify of
guest

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
ColorauGuiyino
1 year ago

Very impressive.

Alternalo
1 year ago

Thanks man, i’ve made it work in Godot 3.5
https://www.youtube.com/watch?v=my9OX8_AIn4