Skip to main content

Function: inferAlbedoUvTransform()

inferAlbedoUvTransform(materialX, surfaceShaderNode, options?): any

Infers the combined UV transform a MaterialX-authored albedo graph applies before its image lookup(s) - e.g. a <place2d> doing tiling/rotation, or a <rotate2d> chained with a plain <multiply>/<add> for scale/offset - and folds it into a single THREE.any suitable for NTCNodeMaterial's uvTransform / NTCTextureSource.bakeColorNodeToTexture's inverse bake (see NTCFormat.js's decodeUvTransform/encodeUvTransform for how this round-trips through a .ntc file).

This is deliberately a simple heuristic, not a general MaterialX evaluator:

  • It operates on the raw, uncompiled MaterialX document graph (the MaterialXNode wrapper - getChildByName/hasReference/referencePath /isConst/getVector, the same API MaterialXDocument.js's resolveSurfaceShaderNode and MaterialXCompileRegistry.js's compileGltfTextureNode already use), not the compiled TSL node tree - once compiled, a <rotate2d> is indistinguishable from any other mul/add/sin/cos arithmetic, so this must run before/instead of compilation.
  • Only a fixed, small vocabulary of node categories is recognized: place2d, rotate2d, and the generic add/subtract/multiply/ divide arithmetic nodes (the common hand-authored "offset2d"/"scale2d" pattern - MaterialX's standard library has no node literally named offset2d/transform2d; place2d is MaterialX's actual combined pivot/scale/rotate/offset transform node - see mx_place2d in src/nodes/materialx/MaterialXNodes.js).
  • Only hardcoded parameter values are handled - any transform node whose parameter is itself wired to another node (a computed expression) or a <...> animation input aborts detection entirely, falling back to identity, rather than guessing. See isDynamicChild.
  • For add/subtract/multiply/divide, only the common authoring pattern - in1 carries the UV chain, in2 is a hardcoded vector2/float operand - is recognized; a node with the operands reversed, or with both sides fed by graphs, is not.
  • Conflicting transforms across different channels (e.g. a differently transformed roughness map) are out of scope entirely - only the albedo chain is walked, and its transform is assumed to apply uniformly.
  • The document's own uvSpace (see MaterialXLoader/MaterialXDocument. js) is honored: a document parsed with uvSpace: 'top-left' has an implicit Y-flip between the mesh's raw UV and MaterialX's own (bottom- left-origin) texcoord convention, which every recognized node upstream of the image actually operated on - see inferUvTransformFromImageNode's handling of the texcoord root.
  • Animation and per-pixel/procedural UV manipulation are out of scope - only a plain affine (rotate/scale/offset) composition is representable as a any in the first place.

Falls back to an identity any (this module's stated default) the moment any of the above is violated, rather than partially applying a transform it isn't confident about.

Parameters​

materialX​

any

surfaceShaderNode​

any

options?​

baseColorInputName?​

string

maxNodes?​

number

Returns​

any