Skip to content

Texture Atlas Animations

Maurizio Vitale edited this page Jan 27, 2020 · 2 revisions

There are two common ways to achieve texture animations in Urho3D. Most of these revolve around a Texture Atlas and UV manipulation, they are similar in concept to a Sprite2D's Sprite Sheet.

Generic Workflow

Defining a Sheet

Sheets are simply a uniform vec2 where the x and y components are the amount of horizontal and vertical slices in the Texture Atlas. You can get the total amount of frames by multiplying these two components.

uniform vec2 sheet; //vec2(4.0, 4.0) the Texture Atlas has a 4x4 layout
float frames = sheet.x * sheet.y; //This will calculate 16 frames

Calculating Current Frame Coordinates

Because texture animations tend to loop, it is of interest to us that we handle circular indexes in code. We can simply calculate the frame as follows.

uniform float f_idx;

float cur_frame = mod(f_idx, frames);

Once we set up this circular index, we can calculate the offsets of the frame as follows.

float x_frame = mod(cur_frame,sheet.x)*(1/sheet.x);
float y_frame = floor(frame/sheet.y)*(1/sheet.y);
vec2 pos_frame = vec2(x_frame, y_frame);

The Vertex Shader

With the two previous functions, we can now build our Texture Animation as a vertex shader.

uniform vec2 sheet;
uniform float f_idx;

/*
	TextureAnimation
	=================
	Uses uniform sheet and frame index, can be rewritten easily to avoid this.
	Takes in UV coordinates.
	Returns specific frame coordinates.
*/

vec2 TextureAnimation(vec2 texCoord)
{
	//Calculate Frames and Current Frame
	float frames = sheet.x * sheet.y;
	float cur_frame = mod(f_idx, frames);
	
	//Get x and y coordinates of the frame
	float x_frame = mod(cur_frame,sheet.x)*(1/sheet.x);
	float y_frame = floor(frame/sheet.y)*(1/sheet.y);
	vec2 pos_frame = vec2(x_frame, y_frame);

	//Apply it to the passed in UV Coordinates
	return texCoord*(1.0/sheet)+pos_frame;
}

Animating Programatically

Animating programatically is done simply by passing in the sheet parameters and frame speed

	Vector2 sheet = Vector2(4.0, 4.0); //Create a 4x4 sheet

	material->SetShaderParameter("sheet", sheet)
	material->SetShaderParameterAnimationSpeed("f_idx", 1.0f)

For further implentation details, check out ghidra’s commit.

Further Reading

Non-Square Texture Atlases

Developers might want to pack a texture atlas in a non-uniform way to reduce memory consumption. However, the current function only handles square frames for simplicity.

Luckily, tools such as TexturePacker, zwoptex, or Shoebox generate metadata when that can be easily passed in to the shader to handle this. The game will then need to iterate through an array of coordinates in order to animate your packed texture atlas.

Other Implementations

https://discourse.urho3d.io/t/animated-textures/1335

https://pastebin.com/gizQdYb2

https://discourse.urho3d.io/t/animated-sprite-2d-and-loading-screen/2019

https://discourse.urho3d.io/t/solved-playing-spritesheet-animation/2428