The tyVAT modifier can be used to export VATs (Vertex Animation Textures) in various formats.
Click “VAT HLSL Shader” in the menu on the left to see an example of a Unity HLSL shader that implements tyVAT’s various modes and features.
Modern game engines (ex: Unreal, Unity, etc) have the ability to import animations from 3D software using popular formats like FBX or Alembic. However, these formats have limitations that make them less than ideal in a lot of situations:
They have no/limited support for non-skinned mesh deformation animation.
On platforms that have no/limited support for GPU skinning (ex: mobile), CPU skinning can pose a performance bottleneck.
In situations where a large number of imported objects/particles require animation, the per-frame update of those elements can pose a performance bottleneck on both the CPU and GPU.
Using VATs to handle animation in those cases, can significantly improve performance - especially on mobile platforms.
The concept behind VATs is simple: instead of animating mesh vertices on the CPU, animate them on the GPU in a shader by having the mesh perform a texture lookup where the texture (VAT) contains deformation information instead of color information. tyFlow’s VAT implementation improves on this concept by not only supporting raw deformations, but also full VAT-based mesh skinning, allowing for a significant reduction in VAT size for animations that are driven by animated bones or particles.
VATs do still have some limitations - the main one being that topological changes in meshes over time are not supported (mesh vertex/face count must stay consistent over the range of animated frames). And since VATs update mesh animation on the GPU (in a shader), it can be tricky to synchronize scene objects to a matching state (ex: synchronizing the animation of a collider in the scene to the animation of a VAT shader). Furthermore, blending between multiple VAT animations in the same shader can also be challenging, making them less than ideal for complex animation transitions.
However, apart from these limitations, the convenience and power of VATs for game development cannot be ignored - hence their inclusion within tyFlow’s ever-growing set of tools.
The input analysis panel of the tyVAT modifier displays information related to the tyVAT settings when applied to the current mesh. Most importantly, it shows how many frames of animation can fit into the specified VAT resolution, and the minimum VAT resolution required to store the specified number of frames. This information is important for understanding how your VAT settings translate into an output VAT file.
Mode: the tyVAT modifier offers serveral VAT export modes. Understanding how each mode works is key to efficiently working with VAT data.
Absolute positions (raw): this mode exports absolute, object-space positions of mesh vertices to a VAT. In this mode, the data will be exported at full, floating-point precision to a format which supports floating-point numbers (EXR).
Relative offsets (raw): this mode exports relative (to the mesh start pose), object-space positions of mesh vertices to a VAT. In this mode, the data will be exported at full, floating-point precision to a format which supports floating-point numbers (EXR).
Absolute positions (RGBA): this mode exports absolute, object-space positions of mesh vertices to a VAT. In this mode, the data will be encoded to RGBA values (4 bytes per float, encoded to the 4 RGBA values of a pixel), to a format which supports RGBA values (PNG or EXR).
Relative offsets (RGBA): this mode exports relative (to the mesh start pose), object-space positions of mesh vertices to a VAT. In this mode, the data will be encoded to RGBA values (4 bytes per float, encoded to the 4 RGBA values of a pixel), to a format which supports RGBA values (PNG or EXR).
Include normals: when enabled, not only will the absolute/relative positions/offsets of a mesh be encoded to a VAT, but the deformed normals of the mesh will be encoded as well. This allows a VAT shader to compute both changes to vertices and normals as a result of any deformations that occur.
The “absolute positions” and “relative offsets” modes are typically the quickest to compute within a shader (because they require the least number of VAT texture lookups per vertex), but generate the largest VAT files. This is because the position or offset of every vertex in a mesh must be stored for every frame of animation exported to a VAT. So, for example, a mesh with 100000 vertices and 100 frames of animation would require at minimum a 8192x4096 resolution VAT to store all the required data (required pixel count = 3 floating point values per vertex, multiplied by the total number of vertices, multiplied by the total number of frames). A VAT of that resolution may not even be supported on all target platforms, and would be very large in size. For this reason, these VAT modes should be reserved for lower-resolution meshes, or situations where the individual deformations of every single vertex must be stored (ie, situations where animation cannot be reduced to rigid/deforming skin).
Deforming skin (RGBA): this mode exports the bone animation of a Skin modifier to a VAT. It also encodes the skin weights of the mesh to corresponding UVW channels. This data, combined, makes it possible for a VAT shader to display deforming skin animation. This mode will encode VAT data to RGBA values (4 bytes per float, encoded to the 4 RGBA values of a pixel). This mode only supports PNG export.
Source: the “deforming skin” mode only supports a Skin modifier (placed above the tyVAT modifier in the object’s modifier stack) as its animation source.
The “deforming skin” mode requires a Skin modifier to be applied to the mesh, above the tyVat modifier. This mode is basically a way to directly encode a Skin modifier setup to a VAT (up to 7 bone weights per vertex are supported). So, for example, if you’ve animated a character and have skinned it with a set of bones using a normal Skin modifier, this mode is a very efficient way to recreate the skin setup and animation in an HLSL shader with a VAT. This mode only supports deformations created with a Skin modifier. Deformations generated in the modifier stack with other modifiers (ex: a Morpher modifier) will be ignored. Because the only data that the VAT needs to store in this mode is the transform animation of the Skin modifier’s bones, this mode is a very efficient way to store Skin-modifier-based deformation data in a VAT. So, for example, a mesh with 100000 vertices (skinned to 100 bones) and 100 frames of animation would require a 512x256 resolution VAT to store all the required data - which is substantially smaller than the minimum size required by the “absolute positions” or “relative offsets” modes.
Rigid skin (RGBA): this mode exports the “rigid skin” animation of a mesh to a VAT. It also encodes the rigid weights of the mesh to a corresponding UVW channel. This data, combined, makes it possible for a VAT shader to display rigid skin animation. This mode will encode VAT data to RGBA values (4 bytes per float, encoded to the 4 RGBA values of a pixel). This mode only supports PNG export.
Source: determines the source of the rigid skin’s transform animation. “Elements” extracts the mesh’s elements at each frame during export, and derives transform animation from the motion of the elements over time (the vertices of each element will be weighted to the extracted transform). “Particles” extract’s transform animation from the particle interface of the object (requires a tyFlow or tyCache as input) - (the vertices of each particle will be weighted to the corresponding particle transform). “Particle skin” extracts transform animation from the specified particle system (requires a tyFlow or tyCache as input) and then weights the vertices of the mesh to the nearest particle mesh (and corresponding transform) of the specified particle system.
The “rigid skin” mode is similar to the “deforming skin” mode, except instead of supporting multiple bone weights per vertex, each vertex of a mesh is weighted to exactly 1 underlying animated transform. Furthermore, this mode is not dependent on a Skin modifier existing in the modifier stack. It can convert underlying particles, or a specified particle system, or extracted mesh elements into trackable transforms which it will convert into the “bones” that the mesh will weight each vertex to. So, for example, you can use this mode to convert a particle system into a VAT. Or convert a mesh whose individual elements are deformed rigidly into a VAT. Or choose an external particle system to “skin” the mesh to and convert the result into a VAT. While the “deforming skin” mode is required if any vertex of a mesh needs to be weighted to more than one underlying bone, the “rigid skin” mode is more efficient and flexible in situations where all vertices of a mesh can be “skinned” to a single “bone” transform (either explicit particles or implicit element transforms).
VATs exported using any of the “RGBA” modes must be imported losslessly into a game engine for them to work with a VAT shader, because they encode the bytes of floating-point values to RGBA values with exact bit precision. This means that any lossy compression or gamma/color correction applied to the VAT will corrupt its data! In Unity, VAT PNGs should be imported using the following settings: Texture type: Lightmap, Generate mipmaps: Off, Filter mode: Point, Format: RGBA 32 bit, Compression: None. Any deviation from these settings may prevent a VAT shader from producing expected results. Also, because tyVAT bakes metadata into meshes prior to export, ensure that your game engine has mesh compression/optimization/welding disabled in your import settings for affected meshes.
Components: specifies which components of extracted transforms (in either skin mode) to store in a VAT.
Rot: only the rotation component of animated transforms will be stored in the VAT. This results in the smallest VAT size, but limits the VAT to rotation animation only. Example usage: exporting the rotational sway of leaves or grass, attached to a static surface or object.
Pos/Rot: only the position and rotation components of animated transforms will be stored in the VAT. This results in a small VAT size, at the exclusion of any scale animation on exported transforms. Example usage: exporting the motion of PhysX rigidbodies, whose scale will not change over time.
Pos/Rot/ScaleAve: position, rotation and (uniform/averaged) scale of animated transforms will be stored in the VAT. This results in a larger VAT size, but not as large as Pos/Rot/ScaleXYZ because transform scale is stored as a single, uniform/averaged value (instead of a separate value for each axis). Example usage: exporting the motion of various particles, whose scale may uniformly change over time.
Pos/Rot/ScaleXYZ: position, rotation and scale of animated transforms will be stored in the VAT. This results in the largest VAT size, because per-axis scale values will be stored in the VAT. Example usage: exporting the motion of various particles, whose per-axis (non-uniform) scale values must be preserved over time.
Auto: the resolution of the VAT will automatically be determined by the export mode and specified number of animated frames.
Manual: the resolution of the VAT will be set to the specified width/height.
VATs should always be exported with “power-of-two” widths/heights. These are widths and heights that are equal to 2 raised to some exponent (2^X). For example, 128 (2^7), 256 (2^8), 512 (2^9), 1024 (2^10), etc. The VAT’s width and height don’t need to be equal (ex: 256x512), but each dimension should follow the “power-of-two” rule.
The specified start frame should be equal to the frame at which the VAT’s corresponding mesh will be exported. For example, if you set the “frame start” to 15, make sure you export the mesh’s corresponding FBX/Alembic file at frame 15 as well.
Frame count: the total number of 3ds Max frames to iterate over during export. Note: the actual number of frames exported may be different than this value, if the “time step” is set to something other than 1.
Time step: the number of 3ds Max frames to process, each time a VAT frame is exported, while progressing from the start frame to the end frame (start frame + frame count).
Setting the “time step” to a value greater than 1 will decrease the overall size of the VAT (because frames will be skipped, resulting in a decrease of frames to export). Similarly, setting the “time step” to a value less than 1 will increase the overall size of the VAT (beacuse subframes will be exported in addition to whole frames) In situations where per-frame animation fidelity is not required (for example: when exporting gentle motion that can be interpolated across skipped frames without loss in quality), this is an easy way to export much smaller VATs for the same overall duration of animation. So, for example, if you set the “frame count” to 100 but “time step” to 2, only 50 frames will ultimately be exported (every other frame). Keep in mind that if frames are skipped, VAT playback speed will need to be adjusted in your VAT shader to compensate. For example, if you set “time step” to 3 (resulting in only every 3rd frame being exported), then playback speed will need to be reduced to 33% to have the animation play back at the same speed as it would if “time step” were set to 1. Similarly, if subframes are exported (ex: “time step” set to 0.5), then playback speed may need to be increased to compensate. Also, depending on your specified time step, subframe interpolation may need to be implemented in whatever VAT shader you’re using, in order to smoothly interpolate (potentially) missing/skipped frame data.
The tyVAT modifier only exports VAT files. Corresponding mesh files required for VAT materials/shaders must be exported by the user manually in whatever format is required for their target game engine (ex: FBX or Alembic).
If you need more than one non-VAT-related map channel to be stored in a mesh, you can increase the “VAT data channel” value. However, in “deforming skin” mode, this may limit the max number of bones you can specify for the VAT setup, because some platforms or engines may have limited support for large numbers of map channels. For example, Unity only supports up to 8 UV channels in a mesh, meaning if you set your “VAT data channel” value to 3, you’ll only be able to have 6 (or fewer) bones influence any given vertex in the mesh (2 base channels + 6 bones channels (starting at channel 3) = 8 total channels required). Also, if you change the “VAT data channel” value, make sure you adjust your VAT shader to account for this change as well.
Because VATs work within a shader, and shaders are hard to debug, it can be difficult to troubleshoot VAT issues if things aren’t working properly. Here is a checklist you can go through, to ensure you’ve taken all the necessary steps to get a VAT working in your game engine:
Ensure the VAT shader you’re using in your game engine is derived from the “VAT HLSL Shader” in the menu on the left. tyVAT’s exported data may not be in the same format expected by 3rd party VAT shaders, and/or 3rd party VAT shaders may not support all of tyVAT’s export modes.
Ensure your tyVAT modifier is applied to the same mesh you’re exporting to your game engine (the tyVAT modifier adds metadata to meshes when using rigid/deforming skin modes, which is read by VAT shaders - if that metadata is missing, VAT skin animation won’t work).
Ensure your mesh export format supports up to 8 UV channels as full floats (ex: FBX), and ensure your game engine’s importer is able to bring in all of those channels without modification (those channels are where tyVAT metadata is stored).
Ensure you’re exporting your mesh at the same frame that you’ve assigned as the start frame in your tyVAT modifier.
Ensure you’re importing your VATs with all compression and gamma/color correction disabled (if the VAT is encoded as RGBA data).
Ensure your shader’s VAT settings are identical to your tyVAT export settings. This includes matching your precision settings, export mode settings, export component settings, etc.
Ensure the VAT shader’s import scale settings matches your game engine’s mesh import scale setting (in Unity the default is 0.01).
Ensure your VAT’s resolution is not being clamped in your game engine, if it exceeds the engine’s default maximum texture size (ex: the default maximum in Unity is 2048, so if your VAT has a dimension larger than 2048, make sure you increase its import resolution as well).