Skip to content

Latest commit

Β 

History

163 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Godot Vertex Animation Textures Plugin (an Animated MultimeshInstance3D solution)

Important

I have 2 VAT Godot plugins. This one and the OpenVAT for Godot Plugin which relies on the OpenVAT Blender Toolkit that no longer appears to be maintained. Recommend to use this plugin if undecided. Also, VATs that are generated by OpenVAT are not compatible with this plugin, so you will need to rebake your animation using the Blender tools that this plugin requires. The API is similar though.

A plugin that extends the MultiMeshInstance3D node to support instanced vertex animations using vertex texture data generated by a Blender add-on, with a vertex shader inside Godot Engine.

The plugin is designed to simplify the process of animating meshes using VATs, providing a seamless integration with the Godot workflow.

Works on all Godot renderers and HTML builds.

See video of the plugin and demos here:

YouTubeVideo

Easy Mesh2Motion (and Mixamo) to Vertex Animation Textures (VAT)

See video showing complete VAT workflow from Mesh2Motion into Blender into Godot in less than 10 minutes: https://youtu.be/twFFcn4Q0fQ

2026-08-08.17-01-48.mp4

What are Vertex Animation Textures?

Vertex Animation Textures (VAT) bakes animations of a mesh into textures. These textures can then be used to create motion in a game engine.

Best to watch this video to understand fully.

Preview

2026-02-26.08-56-43.mp4

Features

  • Can support multiple baked in animations (supports a total of 8192 combined frames).
  • Animation tracks' metadata is configured in the editor, not the code.
  • Animations tracks can be different frame sizes.
  • Ability to set a unique animation track per instance.
  • Ability to control the alpha channel for individual instances. Also includes easy fade in/out tweened functions.
  • Ability to set a unique fps speed per animation track.
  • Ability to restart the non-looping animation tracks for individual instances.
  • Ability to set animation interpolation (blending) for each animation track. Suggested by: @theHoodaloo
  • Visual Shaders are supported so you can also freely apply your own shader logic while still having VAT animations.
  • All the MultiMeshInstance3D features such as a unique transform (scale, rotation, and position) per instance.
  • Works on all renderers, and on HTML builds.

Limitations

  • Mesh must be less than 8192 vertices.
  • Total number of frames for all animations must be less than 8192.
  • No blending or mixing of animation tracks.
  • Cloth simulations not supported by the Blender tool.
  • Mesh with hard edges will appear smooth shaded. See #6 for a workaround.
  • MultiMeshInstance3D custom_data and instance_color is used by this plugin so you will not have access to it.
  • The new VATMultiMeshInstance3D will have physics_interpolation_mode = Node.PHYSICS_INTERPOLATION_MODE_OFF. The reason is that Godot interpolates the custom_data uniform which we do not want. You can still use physics interpolation in your project though.

Requirements

  • Godot 4.5+
  • Blender 4.x, specifically tested with Blender 4.5.9 LTS using: Godot VAT Blender Tools
  • An animated 3D model with less than 8192 total vertices.

Installing

Maybe if this plugin gets noticed, I will add it to Godot's AssetLib. Until then follow these instructions:

  • Download this repository as a ZIP file.
  • Extract the ZIP file.
  • Copy the addons directory from the extracted ZIP file into your Godot project's res:// filesystem.
  • Go to Project > Project Settings > Plugins and enable Godot Vertex Animation Textures Plugin.
  • Test to see if you can add the new VATMultiMeshInstance3D node into a scene.

Full Mesh2Motion > Blender > Godot workflow video

You will need to follow these steps to get your baked VAT into Godot: https://youtu.be/twFFcn4Q0fQ

VATMultiMeshInstance3D

This plugin provides a new node called VATMultiMeshInstance3D which inherits MultiMeshInstance3D.

The Scene dock with show warnings when you first create a VATMultiMeshInstance3D node indicating that you need to define animation track data and add a MultiMesh.

Error messages will also appear in the Output console.

VATMultiMeshInstance3D Properties

  • Instance Count: int = the number of instances
  • Rand Anim Offset: bool = randomize the animation offset (true/false)
  • Default FPS: int = replaces the framerate of all animation tracks if FPS set to 0.
  • Animation Tracks: Array[VATAnimationTrack] the array of animation tracks.
image

VATMultiMeshInstance3D Update Functions

If you want to change the animation track for a specific instance, use:

update_instance_track(instance_id: int, track_number: int)

If you want to change the alpha of a specific instance use:

update_instance_alpha(instance_id: int, alpha: float)

If you want to change the animation offset of an instance, so that different instances playing the same animation track are not syncronized, use:

update_instance_animation_offset(instance_id: int, animation_offset: float)

You can also change all parameters of a specific instance by using:

update_instance(instance_id: int, animation_offset: float, track_number: int, alpha: float)

You can also change ALL instances by using:

update_all_instances(animation_offset: float, track_number: int, alpha: float)

VATMultiMeshInstance3D Tweened Fade In/Out Functions

You can get Godot to automatically fade out an instance using a Tween with:

fade_out_instance(instance_id: int, fade_out_time: float = 1.0, start_delay: float = 0.0):

You can get Godot to automatically fade in an instance using a Tween with:

fade_in_instance(instance_id: int, fade_in_time: float = 1.0, start_delay: float = 0.0):

VATMultiMeshInstance3D Animation Play Functions

You can play the next animation track of an instance using:

play_next_track_instance(instance_id: int)

Or play the next animation track of all instances using:

play_next_track_all_instances()

VATMultiMeshInstance3D Animation Get Functions

Animation meta data is stored in the vat_animation_tracks variable. It is an Array of VATAnimationTrack:

var vat_animation_tracks: Array[VATAnimationTrack] 

This is the VATAnimationTrack class:

class_name VATAnimationTrack
extends Resource

var name: String
var startFrame: int
var endFrame: int
var isLooping: bool
var isBlended: bool
var isReversed: bool # For future reverse playback
var framerate: int

To get the VATAnimationTrack object from an instance:

get_animation_from_instance(instance_id: int) -> VATAnimationTrack

To get the animation track index from the provided VATAnimationTrack object:

get_track_number_from_animation(animation: VATAnimationTrack) -> int

To get the currently playing animation track index from the instance, use:

get_track_number_from_instance(instance_id: int) -> int

To get the animation track index by animation track name:

get_track_number_from_name(name: String) -> int:

To get the animation track index from the start and end frames, use:

get_track_number_from_start_end_frames(start: int, end: int) -> int

Instanced custom_data and instanced color shader uniforms

The inherited MultiMeshInstance3D custom_data is used by this plugin and instanced shader. Here is how it is used:

  • custom_data.r = animation offset: used to randomize instances playing the same animation track
  • custom_data.g = animation start frame
  • custom_data.b = animation end frame
  • custom_data.a = alpha of mesh: used to fade in/out a unique instance

The inherited MultiMeshInstance3D color_instance is used by this plugin and instanced shader. Here is how it is used:

  • color.r = packed float for use_looping, use_blended, use_reverse where 1.0 = true, 0.0 = false.
  • color.g = timestamp used to keep track of when an animation was set or the one_shot has been reset.
  • color.b = animation frame rate: must be greater than zero
  • color.a = NOT USED

Vertex Animation Shader

The magic of vertex animations happens both in Blender and in the shader. This is why you should understand what is happening in the shader.

To make it easy, use Mesh > Surface_0 > Material to add the a new ShaderMaterial.

In the Shader property select Quick Load and select: vat_multiple_anims.gdshader

Once loaded expand Shader Parametrs and you will have access to configure the following shader parameters:

  • Offset Map: The texture that encodes the position of each vertex for every frame.
  • Normal Map: The texture that encodes the normal of each vertex for every frame.
  • Texture Albedo: The UV color texture that is used for the mesh.
  • Specular, Metallic, Roughness, Normal: See Godot docs for more information.
image

Make sure both offset and normal textures are imported with Lossless format.

The instanced uniforms custom_data and color in the MultiMeshInstance3D are passed to the shader to do its magic. Here is some of the shader code that uses this data:

uniform sampler2D offset_map;
uniform sampler2D normal_map;
uniform sampler2D texture_albedo;

...

varying flat vec4 custom_data;
varying flat vec4 color_data;

void vertex(){
	custom_data = INSTANCE_CUSTOM;
	color_data = COLOR;

	float start_frame = custom_data.g;
	float end_frame = custom_data.b;
	
	float num_frames = end_frame - start_frame;
	float frame_offset = num_frames * custom_data.r;
	
	...
}
		
void fragment(){
	ALBEDO = albedo.rgb * texture(albedo_texture, UV).rgb;

	...

	ALPHA = custom_data.a;  // fader

}

Common Issues

❓Question: My mesh is all white, with no colors or textures. πŸ’‘Answer: You forgot to add Albedo, Metallic, Roughness, Normal textures that came with the original model to the shader.

❓Question: My mesh's verticies are cracked or all over the place. πŸ’‘Answer: Re-import your VAT offsets (.exr file) and VAT normals (.png file) with compress mode as Lossless and turn off Generate Mipmaps.

❓Question: How do I restart a non-looping animation for a specific instance? πŸ’‘Answer: Use reset_one_shot(instance_id) or update_instance_track(instance_id: int, track_number: int) both assume the animation track is set with is_looping = false.

Demos

Demo scenes are in the demo subfolder:

  • Performance Test: 2000 instances (configurable) with 20 animations, with different scales, and positions. Displays FPS, and allows you to disable shadows. See Performance section for detailed performance findings.
  • Alpha Test: Shows how to control alpha so that you can fade in/out individual instances.
  • Visual Shader Test: An example post dissolve effect using Visual Shaders.

The skeleton mesh included in the demo has 20 baked in animations. The Male and Female Mannequins and Kenney's Zombie are from Mesh2Motion.

Godot games made with this plugin

itch.io: Skeletron 2084

YouTube: Skeletron 2084 Gameplay

Performance

Here are the performance test results per renderer, using:

  • Godot 4.7.1 standard (DEBUG mode)
  • Version v0.1.6 of plugin
  • Linux Mint, 32 GB RAM
  • CPU: AMD Ryzen 5500
  • GPU: AMD Radeon RX 9060 XT 16 GB
  • Viewport: 1920x1080 no MSAA

2000 instances

Renderer Shadows On Shadows Off
Compatibility 354 fps 536 fps
Mobile 458 fps 768 fps
Forward+ 349 fps 506 fps

5000 instances

Renderer Shadows On Shadows Off
Compatibility 155 fps 236 fps
Mobile 216 fps 378 fps
Forward+ 165 fps 244 fps

Initial findings is that the Mobile renderer performs the best.

Blender Add-On Guide

  1. Download the files from the correct addon version and install vertex_animation.py in the Blender -> Edit -> Preferences... -> Add-ons -> Install... menu. In the 3D Viewport side bar, you should now have a Not Unreal Tools or Godot Blender Tools menu and if selected it will show a Vertex Animation panel.
  2. In Object Mode select the object you want to process, make sure the current animation you want is selected and playable in the Timeline.
  3. Adjust the Frame Start, End and Step values as required. Changing these settings will update corresponding Timeline values.
  4. Click the Process Anim Meshes button. This will create a new object named export_mesh in the Outliner, this is the special mesh that will be animated. In the source .blend file path there will be a newly created folder called vaexport and inside will be two files; normals.png and offsets.exr.
  5. The export_mesh needs to be exported as a glTF file for importing into Godot. Select the export_mesh object in the Outliner and then from the Blender File menu, select Export -> glTF 2.0 (.glb .gltf). Make the following changes to the export options and then click the Export glTF 2.0 button:
    • Include -> Selected Objects (enable)
    • Geometry -> Materials (disable)
    • Animation -> Animation, Shape Keys, Skinning (disable all)
    • Filename -> can rename to anything

install

tool

Godot Import Guide

  1. You should now have 3 files generated from Blender: normals.png, offsets.exr and export_mesh.glb (whichever filename was chosen, this guide will refer to the default name).
  2. Copy the files into the Godot project folder of your choice. Godot will run the import process as soon as it detects the new files. The import settings for each file still need more changes to ensure all of them work properly with the vertex shader.
  3. In the Godot FileSystem dock, select the glTF file (export_mesh.glb) and then click the Import dock (default location is docked along side of the Scene tree). Godot Docs - Importing 3D Scenes
  4. Make the following adjustments and then click the Reimport button. There should be a new file called export_mesh.mesh in the same folder as the glTF file (export_mesh.glb).
    • Meshes:
      • Compress -> (disable)
      • Ensure Tangents -> (disable)
      • Storage -> Files (.res)
    • Animation:
      • Import -> (disable)
  5. Add a MeshInstance or MultiMeshInstance node to the scene. Drag the export_mesh.mesh file into the Mesh parameter slot for a MeshInstance or the Mesh parameter slot inside the MultiMesh for a MultiMeshInstance node. This guide will not cover loading Mesh resources via script.
  6. The import settings for normals.png and offsets.exr will need to be updated after they are added into the shader parameters since Godot will make changes based on what node the image was applied to (3D nodes apply import settings for images used in 3D).
  7. Apply the custom vertex animation shader material to a MeshInstance/MultiMeshInstance. Recommend using the GeometryInstance -> Geometry -> Material Override slot.
  8. Go to the Shader Parameters and click the drop-down arrow and select load for the following parameters:
    • Offset Map -> load offsets.exr
    • Normal Map -> load normals.png
  9. Now find normals.png and offsets.exr in the FileSystem dock, go to Import settings, make the following changes for both files and click the Reimport button:
    • Compress:
      • Mode -> Lossless for normals.png, Uncompressed for offsets.exr
    • Flags:
      • Repeat -> (disable) when changing the current frame using an AnimationPlayer or via script. (enable) when looping animations using shader TIME.
      • Filter -> (disable)
      • Mipmaps -> (disable)
  10. If you are importing more image files such as albedo textures, refer to Godot Docs - Importing Images. For palettes and texture masks, recommend using Lossless compression and disable Filter and Mipmaps, so there is no blending of the colours.

Assets

Skeleton by Kay Lousberg - CC0 License

Zoimbie Model by Kenney - CC0 License

Male and Female Mannequins by Quaternius - CC0 License

Floor Tile by Kenney - CC0 License

About

A Godot Animated MultimeshInstance3D solution in a plugin that extends the MultiMeshInstance3D node to support instanced vertex animations using vertex texture data.

Topics

Resources

Stars

124 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages