Skip to content

VFX Material Parameters

VFX particle systems in League of Legends can attach meshes to bones and apply material effects through VfxEmitterDefinitionData. These parameters are extracted alongside standard StaticMaterialDef data.

Overview

When a VFX emitter renders an attached mesh (via VfxPrimitiveAttachedMesh), it can specify:

  • Texture: The diffuse texture for the mesh
  • UV Scroll: Animated texture offset for scrolling effects (e.g., flowing noodles, energy streams)
  • UV Scale: Texture tiling/repeat for the mesh

These parameters override StaticMaterial shader parameters when present, allowing particle effects to animate mesh textures independently.

Extracted Parameters

birthUvScrollRate

Maps to uvScrollSpeed in GLTF material extras.

Structure in bin data:

json
"birthUvScrollRate": {
  "constantValue": [0.0, 1.0],
  "__type": "ValueVector2"
}

Export format:

  • uvScrollSpeed: [number, number] - UV offset delta per second [x, y]

Frontend behavior:

  • Applied each frame: offset += speed * deltaTime * animationTimeScale
  • Respects animation pause state
  • Requires RepeatWrapping texture mode

uvScale

Maps to uvTile in GLTF material extras.

Structure in bin data:

json
"uvScale": {
  "constantValue": [1.0, 0.5],
  "__type": "ValueVector2"
}

Export format:

  • uvTile: [number, number] - Texture repeat/scale [x, y]

Frontend behavior:

  • Sets texture.repeat on load
  • Values < 1.0 shrink the texture (e.g., 0.5 shows half)
  • Values > 1.0 tile the texture (e.g., 2.0 repeats twice)

Priority and Applicability

IMPORTANT: VFX parameters are ONLY applied to meshes that are initially hidden (in initialSubmeshToHide).

Meshes visible by default (Hair, Body, etc.) do NOT get VFX UV scroll applied to their base material, even if VFX emitters reference them. This is because:

  • Visible meshes have their own base material with shader-defined parameters
  • VFX parameters for visible meshes are for temporary animation effects only
  • Applying VFX params to visible meshes would cause incorrect base rendering

When both VFX and StaticMaterial define scroll/tile parameters:

  1. VFX parameters (from VfxEmitterDefinitionData) - highest priority, ONLY for initially hidden meshes
  2. StaticMaterial parameters (from shader) - used for all visible meshes, fallback for hidden meshes

This ensures VFX-only meshes (like NoodleVfx) get their animation from particle data, while regular meshes use their shader parameters.

Example: Noodle VFX

Chibi Akali Joke Animation (Skin1)

The NoodleVfx submesh shows animated ramen noodles during the joke emote:

  • Mesh: NoodleVfx (attached to character skeleton)
  • Initially Hidden: YES (in initialSubmeshToHide) ✓ VFX params applied
  • VFX System: PetChibiAkali_Skin1_Emote_JokeSubMesh
  • Texture: PetChibiAkali_Base_Noodlevfx_TX_CM.tex
  • UV Scroll: [0.0, 1.0] - scrolls vertically at 1 UV/sec
  • UV Scale: [1.0, 0.5] - shrinks texture to 50% height

This creates the illusion of noodles being slurped into the mouth as the texture scrolls upward.

Counter-example: Hair, Body, Bag (Chibi Akali Dance Animation)

These meshes are referenced by a Dance VFX emitter with UV scroll [0.2, 0.1]:

  • Meshes: Hair, Body, Bag (visible parts of character)
  • Initially Hidden: NO ✗ VFX params NOT applied to base material
  • VFX System: PetChibiAkali_Skin1_Emote_Dance_SubmeshLoop
  • UV Scroll: [0.2, 0.1] - applies ONLY during Dance animation VFX

The VFX scroll is a temporary visual effect during the dance, not a permanent property of these meshes.

Implementation Notes

Extractor (Skin.cs)

  • ExtractMeshAndTextureFromEmitter() - parses VFX emitter properties
  • _vfxMeshMaterialParams - maps mesh name → VFX params
  • GetVfxMaterialParams() - accessor for export

Export (SkinExtensions.cs)

  • Checks isHiddenSubmesh (from initialSubmeshToHide) before applying VFX params
  • Only calls skin.GetVfxMaterialParams() for initially hidden meshes
  • Uses null-coalescing: vfxParams?.UvScrollSpeed ?? staticMaterial?.GetUvScrollSpeed()
  • Prevents VFX params from overriding visible mesh base materials

Frontend (engine/index.ts)

  • handleUvScroll() - registers materials for animation
  • handleUvTile() - applies texture repeat
  • Animation loop updates offsets synced to skeletal animation time

Hash Values

Property hashes (FNV1a lowercase):

  • birthUvScrollRate: 4132956430 (0xf66b780e)
  • uvScale: 4071848866 (0xf2c5e8a2)
  • constantValue: 3916664084 (0xe984e394)

Built for engineers and AI assistants working on Khada.