Skip to content
← Back to Blog 3d-modeling

Vertex Animation Textures (VAT): Bake Physics and Crowd Simulations into Game-Ready Textures with Blender and Unreal Engine 5

By BitSoul3D6 min read165 views

Rigid body simulations, cloth physics, and crowd animations look spectacular — until you try to run them in a game engine in real time. Vertex Animation Textures (VATs) solve this by baking every vertex position from a simulation into a texture, then replaying it in a shader at essentially zero CPU cost. If you've been avoiding complex animated effects because of performance budgets, VATs are the technique that changes everything.

Vertex Animation Textures (VAT): Bake Physics and Crowd Simulations into Game-Ready Textures with Blender and Unreal Engine 5

What Are Vertex Animation Textures and Why Use Them?

A Vertex Animation Texture stores per-vertex world-space positions (and optionally normals) across every frame of an animation. Instead of running a physics solver at runtime, the GPU simply samples the texture to look up where each vertex should be on any given frame. The result is visually identical to the original simulation but costs almost nothing to render — a crowd of 10,000 animated characters can run with fewer draw calls than a single fully-rigged skeletal mesh.

VATs are ideal for:

The technique works in any engine that supports custom vertex shaders — UE5, Unity, and Godot 4 all support it. This guide focuses on the Blender-to-UE5 pipeline.

Setting Up Your Blender Scene for VAT Baking

Setting Up Your Blender Scene for VAT Baking — illustrated

Before you bake, your scene needs to meet strict requirements or the exported texture will produce garbage results in engine.

Mesh requirements:

Timeline setup:

Bake the simulation to keyframes first:

# In Blender's Python console or a script:
import bpy

obj = bpy.context.active_object
# Bake cloth/rigid body sim to keyframes
bpy.ops.object.paths_calculate()
# Or for point cache: Object > Apply > Visual Geometry to Mesh per frame
# Use a frame-by-frame export script for reliability

For complex sims, the most reliable approach is a frame-by-frame mesh export script that writes one OBJ per frame, which you then recombine. Several free Blender addons (SideFX Houdini VAT exporter ports, the community "VAT Exporter" addon) automate this entirely — search the BitSoul marketplace for ready-to-use VAT-baked assets if you want to skip the baking step entirely.

Baking the VAT: Export Settings and Texture Layout

The VAT consists of two textures: a Position texture (RGB = XYZ offset from rest pose in world space) and a Normal texture (RGB = packed normal vector). Both must be EXR or 16-bit PNG — 8-bit will produce visible stepping artifacts.

Python bake script (simplified):

import bpy, bmesh, struct, math
from mathutils import Vector

obj = bpy.context.active_object
scene = bpy.context.scene
vert_count = len(obj.data.vertices)
frame_count = scene.frame_end - scene.frame_start + 1

# Build flat array: [frame0_v0_xyz, frame0_v1_xyz, ..., frame1_v0_xyz, ...]
positions = []
for f in range(scene.frame_start, scene.frame_end + 1):
    scene.frame_set(f)
    depsgraph = bpy.context.evaluated_depsgraph_get()
    eval_obj = obj.evaluated_get(depsgraph)
    mesh = eval_obj.to_mesh()
    for v in mesh.vertices:
        positions.append(v.co.copy())
    eval_obj.to_mesh_clear()

# Write to EXR via Blender's image API
# tex_width = vert_count, tex_height = frame_count
img = bpy.data.images.new('VAT_Position', width=vert_count, height=frame_count, float_buffer=True)
pixels = []
for pos in positions:
    pixels += [pos.x, pos.y, pos.z, 1.0]  # RGBA
img.pixels = pixels
img.filepath_raw = '//vat_position.exr'
img.file_format = 'OPEN_EXR'
img.save()
print(f'Baked {vert_count} verts × {frame_count} frames')

Critical export settings:

SettingValue
Position texture formatEXR 32-bit float
Normal texture formatEXR 16-bit or PNG 16-bit
Coordinate spaceWorld space
Texture widthVertex count (power of 2 preferred)
Texture heightFrame count (power of 2 preferred)
Base meshRest pose, same vert count, exported as FBX

Importing and Playing VATs in Unreal Engine 5

Importing and Playing VATs in Unreal Engine 5 — illustrated

With your EXR textures and rest-pose FBX in hand, the UE5 setup takes about 15 minutes.

Import steps:

  1. Import the rest-pose FBX as a Static Mesh (not Skeletal Mesh)
  2. Import both EXR textures. Set Compression Settings → HDR (RGB, no sRGB) on both — this is critical; sRGB compression will destroy your floating-point position data
  3. Disable Mip Maps on both VAT textures — you never want filtered mips on data textures

Material setup in UE5 Material Editor:

The core logic is a World Position Offset node chain:

TexCoord [UV1 for VAT] 
  → AppendVector(U=vertex_index / vert_count, V=time / frame_count)
  → Texture Sample (VAT_Position, Sampler: Explicit)
  → Multiply (by bbox_range)
  → Add (bbox_min)
  → World Position Offset

Key material parameters to expose:

For the vertex index lookup, use the VertexID material node (available in UE5 under Coordinates). Divide by your total vertex count to get a normalized U coordinate that maps each vertex to its column in the VAT texture.

Once the material is set up, instance it per-asset and drive VATPlaybackSpeed through Blueprints or Niagara parameter bindings to randomize playback offsets across crowd instances — this prevents all characters from being on the same frame and kills the "clone army" look instantly.

Performance Budgeting and LOD Strategy for VAT Assets

VATs shift cost from CPU/game thread to GPU texture sampling, which is almost always the right trade for background elements. But they're not free — plan your budget carefully.

Texture memory cost:
tex_width × tex_height × 4 bytes (EXR) × 2 textures (pos + normal)

A 512×64 VAT pair costs 256 KB — negligible. A 2048×256 pair costs 4 MB per asset. Stream them with standard UE5 texture streaming; their small size means they'll stay resident in even modest VRAM budgets.

LOD recommendations for VAT meshes:

Instancing: Always render VAT meshes with Instanced Static Mesh or Hierarchical Instanced Static Mesh components. VATs are static meshes by definition, so GPU instancing applies fully — thousands of instances render in a single draw call. Pair with UE5's Mass Entity system for crowd scenarios exceeding 50,000 agents.

Find a growing library of pre-baked VAT assets and optimized game-ready meshes at the BitSoul marketplace.

Wrapping Up

Vertex Animation Textures are one of the most underused techniques in indie and mid-size studio pipelines. The bake happens once in Blender, the runtime cost is negligible, and the visual results — hundreds of animated objects filling your world — are genuinely difficult to achieve any other way at this performance point. Set up the pipeline once, and you'll reach for VATs constantly.

Browse pre-baked VAT assets and game-ready 3D models at the BitSoul marketplace and skip straight to the engine integration step.


Need drop-in assets for this workflow? Grab the 70-model Food Bundle on the BitSoul marketplace and drop them straight into your project.

Tags: food

Skip the modeling — download it instead

A free BitSoul3D account gets you 2 GLB downloads every month for personal use plus 25 one-time AI Engine credits, no card required. PBR-textured GLB downloads with a full 3D preview before you buy, for Unreal, Unity, Godot or Blender — OBJ and 3D-printable STL come with any purchase or paid plan.

Browse 1,051 models — from $4.99 → or start free (2 downloads a month)