Three.js Integration Notes

September 3, 2026 ยท View on GitHub

Notes on Three.js animation and MaterialX systems relevant to Tydra RenderScene conversion and the LightUSD JavaScript viewer.

Animation System

Three.js Animation Hierarchy

Keyframes (raw data)
    -> KeyframeTrack (property animation)
    -> AnimationClip (collection of tracks)
    -> AnimationMixer (playback control)

KeyframeTrack Types

  • VectorKeyframeTrack: For position and scale (3D vectors)
  • QuaternionKeyframeTrack: For rotation (quaternions, NOT Euler angles)
  • NumberKeyframeTrack: For scalar values or morph targets

glTF to Three.js Mapping

glTF PathThree.js Track TypeThree.js Property
translationVectorKeyframeTrack.position
rotationQuaternionKeyframeTrack.quaternion
scaleVectorKeyframeTrack.scale
weightsNumberKeyframeTrack.morphTargetInfluences[i]

Interpolation Modes

  1. STEP (InterpolateDiscrete): No interpolation
  2. LINEAR (InterpolateLinear): Linear (slerp for quaternions)
  3. CUBICSPLINE: Cubic spline with tangents (custom in GLTFLoader)

Key Points

  • All angles in radians, default Euler order 'XYZ'
  • Keyframe data stored in flat arrays: [x0,y0,z0, x1,y1,z1, ...]
  • Time values in seconds (floating point)
  • Always prefer quaternions over Euler angles (avoids gimbal lock)

Tydra Data Structure

Tydra's actual IR splits keyframe data (KeyframeSampler: flat times/values

  • AnimationInterpolation) from bindings (AnimationChannel: path, target_type, node/joint indices, sampler), following the glTF model. See src/tydra/render-data.hh and doc/tydra-animation-spec-en.md for the full structures and the Three.js track export.

MaterialX Support

Three.js MaterialXLoader Status (2024-2025)

Three.js's own MaterialXLoader is WebGPU only (experimental): it supports Standard Surface materials, procedural textures, and noise nodes via TSL (Three Shading Language) for node-based authoring, with no WebGL/WebGL2 fallback.

The LightUSD viewer does not rely on MaterialXLoader. It ships both a WebGPU demo (web/js/materialx-webgpu.js, TSL NodeMaterial) and a WebGL2 demo (web/js/materialx-webgl2.js, a custom OpenPBR WebGL material via LightUSDOpenPBR_WebGL.js) โ€” see the WebGL fallback strategy below.

LightUSD MaterialX Architecture

Supported shader models:

  • MtlxUsdPreviewSurface (src/usdMtlx.hh): MaterialX-extended UsdPreviewSurface
  • MtlxAutodeskStandardSurface (src/usdMtlx.hh): Autodesk Standard Surface
  • OpenPBRSurface (src/usdShade.hh): Academy Software Foundation OpenPBR model

File format support: direct .mtlx loading, USD references (@myshader.mtlx@), embedded MaterialX.

Tydra Conversion Pipeline

USD Stage -> Material with MaterialXConfigAPI -> Tydra RenderMaterial

Dual material output:

class RenderMaterial {
    nonstd::optional<PreviewSurfaceShader> surfaceShader;   // UsdPreviewSurface
    nonstd::optional<OpenPBRSurfaceShader> openPBRShader;   // MaterialX OpenPBR
};

Property Mapping (Tydra -> Three.js)

LightUSD/TydraThree.jsNotes
OpenPBRSurface.base_colorstandard_surface.base_colorDirect
OpenPBRSurface.base_metalnessstandard_surface.metalnessDirect
OpenPBRSurface.specular_weightstandard_surface.specularMay need scaling
OpenPBRSurface.coat_weightstandard_surface.coatDirect
UsdUVTexturetexture2d + place2dCombine nodes

WebGL Fallback Strategy

For WebGL, convert to MeshPhysicalMaterial:

const material = new THREE.MeshPhysicalMaterial({
    color: materialData.base_color,
    metalness: materialData.base_metalness,
    roughness: materialData.base_roughness,
});

References