From fef39719547278330100ff91f447305a1fcaf5bb Mon Sep 17 00:00:00 2001 From: Ben Houston Date: Mon, 20 Jul 2026 17:05:46 -0400 Subject: [PATCH 1/3] Materialx upgrade (#33485) Co-authored-by: Cursor Co-authored-by: sunag --- examples/jsm/loaders/MaterialXLoader.js | 1107 +---------------- .../jsm/loaders/materialx/MaterialXArchive.js | 108 ++ .../loaders/materialx/MaterialXDocument.js | 878 +++++++++++++ .../jsm/loaders/materialx/MaterialXHextile.js | 183 +++ .../materialx/MaterialXInterfaceValidation.js | 376 ++++++ .../jsm/loaders/materialx/MaterialXLog.js | 75 ++ .../MaterialXNodeInterfaceRegistry.js | 4 + .../loaders/materialx/MaterialXNodeLibrary.js | 1021 +++++++++++++++ .../materialx/MaterialXSurfaceMappings.js | 661 ++++++++++ .../jsm/loaders/materialx/MaterialXUtils.js | 57 + .../compile/MaterialXCompileRegistry.js | 997 +++++++++++++++ .../materialx/parse/MaterialXParser.js | 28 + .../materialx/gltf_pbr_glass_dispersion.mtlx | 17 + .../materialx/open_pbr_surface_honey.mtlx | 14 + .../materialx/open_pbr_surface_pearl.mtlx | 20 + .../materialx/open_pbr_surface_velvet.mtlx | 13 + ...standard_surface_color3_vec3_cm_test.mtlx} | 3 +- ...lx => standard_surface_combined_test.mtlx} | 4 +- ...tandard_surface_conditional_if_float.mtlx} | 0 ...tlx => standard_surface_heightnormal.mtlx} | 0 ..._surface_heighttonormal_normal_input.mtlx} | 0 ... => standard_surface_image_transform.mtlx} | 0 ...st.mtlx => standard_surface_ior_test.mtlx} | 2 +- ...> standard_surface_opacity_only_test.mtlx} | 4 +- ...tlx => standard_surface_opacity_test.mtlx} | 2 +- ...lx => standard_surface_rotate2d_test.mtlx} | 1 - ...lx => standard_surface_rotate3d_test.mtlx} | 13 +- ...x => standard_surface_roughness_test.mtlx} | 2 +- ....mtlx => standard_surface_sheen_test.mtlx} | 0 ...lx => standard_surface_specular_test.mtlx} | 0 ...tandard_surface_texture_opacity_test.mtlx} | 8 +- ...ard_surface_thin_film_ior_clamp_test.mtlx} | 4 +- ...ndard_surface_thin_film_rainbow_test.mtlx} | 4 +- ...ndard_surface_transmission_only_test.mtlx} | 2 +- ... standard_surface_transmission_rough.mtlx} | 2 +- ...> standard_surface_transmission_test.mtlx} | 2 +- .../screenshots/webgpu_backdrop_water.jpg | Bin 45237 -> 46251 bytes examples/screenshots/webgpu_geometry_loft.jpg | Bin 40175 -> 40150 bytes .../screenshots/webgpu_lights_projector.jpg | Bin 30410 -> 29645 bytes .../screenshots/webgpu_loader_materialx.jpg | Bin 69016 -> 36149 bytes .../screenshots/webgpu_materialx_noise.jpg | Bin 44200 -> 41534 bytes examples/screenshots/webgpu_portal.jpg | Bin 17945 -> 17293 bytes examples/screenshots/webgpu_tsl_graph.jpg | Bin 43410 -> 43154 bytes examples/webgpu_backdrop_water.html | 37 +- examples/webgpu_lights_projector.html | 2 +- examples/webgpu_loader_materialx.html | 106 +- examples/webgpu_materialx_noise.html | 252 +++- src/Three.TSL.js | 6 + .../{lib/mx_hsv.js => MaterialXColor.js} | 9 +- ...rm_color.js => MaterialXColorTransform.js} | 9 +- src/nodes/materialx/MaterialXCore.js | 37 + src/nodes/materialx/MaterialXNodes.js | 136 +- .../{lib/mx_noise.js => MaterialXNoise.js} | 623 +++++++--- 53 files changed, 5387 insertions(+), 1442 deletions(-) create mode 100644 examples/jsm/loaders/materialx/MaterialXArchive.js create mode 100644 examples/jsm/loaders/materialx/MaterialXDocument.js create mode 100644 examples/jsm/loaders/materialx/MaterialXHextile.js create mode 100644 examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js create mode 100644 examples/jsm/loaders/materialx/MaterialXLog.js create mode 100644 examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js create mode 100644 examples/jsm/loaders/materialx/MaterialXNodeLibrary.js create mode 100644 examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js create mode 100644 examples/jsm/loaders/materialx/MaterialXUtils.js create mode 100644 examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js create mode 100644 examples/jsm/loaders/materialx/parse/MaterialXParser.js create mode 100644 examples/materialx/gltf_pbr_glass_dispersion.mtlx create mode 100644 examples/materialx/open_pbr_surface_honey.mtlx create mode 100644 examples/materialx/open_pbr_surface_pearl.mtlx create mode 100644 examples/materialx/open_pbr_surface_velvet.mtlx rename examples/materialx/{color3_vec3_cm_test.mtlx => standard_surface_color3_vec3_cm_test.mtlx} (92%) rename examples/materialx/{combined_test.mtlx => standard_surface_combined_test.mtlx} (85%) rename examples/materialx/{conditional_if_float.mtlx => standard_surface_conditional_if_float.mtlx} (100%) rename examples/materialx/{heightnormal.mtlx => standard_surface_heightnormal.mtlx} (100%) rename examples/materialx/{heighttonormal_normal_input.mtlx => standard_surface_heighttonormal_normal_input.mtlx} (100%) rename examples/materialx/{image_transform.mtlx => standard_surface_image_transform.mtlx} (100%) rename examples/materialx/{ior_test.mtlx => standard_surface_ior_test.mtlx} (90%) rename examples/materialx/{opacity_only_test.mtlx => standard_surface_opacity_only_test.mtlx} (83%) rename examples/materialx/{opacity_test.mtlx => standard_surface_opacity_test.mtlx} (89%) rename examples/materialx/{rotate2d_test.mtlx => standard_surface_rotate2d_test.mtlx} (94%) rename examples/materialx/{rotate3d_test.mtlx => standard_surface_rotate3d_test.mtlx} (90%) rename examples/materialx/{roughness_test.mtlx => standard_surface_roughness_test.mtlx} (89%) rename examples/materialx/{sheen_test.mtlx => standard_surface_sheen_test.mtlx} (100%) rename examples/materialx/{specular_test.mtlx => standard_surface_specular_test.mtlx} (100%) rename examples/materialx/{texture_opacity_test.mtlx => standard_surface_texture_opacity_test.mtlx} (72%) rename examples/materialx/{thin_film_ior_clamp_test.mtlx => standard_surface_thin_film_ior_clamp_test.mtlx} (85%) rename examples/materialx/{thin_film_rainbow_test.mtlx => standard_surface_thin_film_rainbow_test.mtlx} (85%) rename examples/materialx/{transmission_only_test.mtlx => standard_surface_transmission_only_test.mtlx} (92%) rename examples/materialx/{transmission_rough.mtlx => standard_surface_transmission_rough.mtlx} (92%) rename examples/materialx/{transmission_test.mtlx => standard_surface_transmission_test.mtlx} (92%) rename src/nodes/materialx/{lib/mx_hsv.js => MaterialXColor.js} (88%) rename src/nodes/materialx/{lib/mx_transform_color.js => MaterialXColorTransform.js} (63%) create mode 100644 src/nodes/materialx/MaterialXCore.js rename src/nodes/materialx/{lib/mx_noise.js => MaterialXNoise.js} (74%) diff --git a/examples/jsm/loaders/MaterialXLoader.js b/examples/jsm/loaders/MaterialXLoader.js index ae7d74b2c6b982..ff5277bf8f1ddf 100644 --- a/examples/jsm/loaders/MaterialXLoader.js +++ b/examples/jsm/loaders/MaterialXLoader.js @@ -1,202 +1,44 @@ -import { - FileLoader, Loader, ImageBitmapLoader, Texture, RepeatWrapping, MeshBasicNodeMaterial, - MeshPhysicalNodeMaterial, DoubleSide, -} from 'three/webgpu'; - -import { - float, bool, int, vec2, vec3, vec4, color, texture, - positionLocal, positionWorld, uv, vertexColor, - normalLocal, normalWorld, tangentLocal, tangentWorld, - mul, abs, sign, floor, ceil, round, sin, cos, tan, - asin, acos, sqrt, exp, clamp, min, max, normalize, length, dot, cross, normalMap, - remap, smoothstep, luminance, mx_rgbtohsv, mx_hsvtorgb, - mix, saturation, transpose, determinant, inverse, log, reflect, refract, element, - mx_ramplr, mx_ramptb, mx_splitlr, mx_splittb, - mx_fractal_noise_float, mx_noise_float, mx_cell_noise_float, mx_worley_noise_float, - mx_transform_uv, - mx_safepower, mx_contrast, - mx_srgb_texture_to_lin_rec709, - mx_add, mx_atan2, mx_divide, mx_modulo, mx_multiply, mx_power, mx_subtract, - mx_timer, mx_frame, mat3, mx_ramp4, - mx_invert, mx_ifgreater, mx_ifgreatereq, mx_ifequal, distance, - mx_separate, mx_place2d, mx_rotate2d, mx_rotate3d, mx_heighttonormal, - mx_unifiednoise2d, mx_unifiednoise3d -} from 'three/tsl'; - -const colorSpaceLib = { - mx_srgb_texture_to_lin_rec709 -}; - -class MXElement { - - constructor( name, nodeFunc, params = [] ) { - - this.name = name; - this.nodeFunc = nodeFunc; - this.params = params; +import { FileLoader, Loader } from 'three/webgpu'; - } +import { MaterialXDocument } from './materialx/MaterialXDocument.js'; +import { MaterialXLog } from './materialx/MaterialXLog.js'; +import { isZipBuffer, readMtlxArchive, createArchiveResolver } from './materialx/MaterialXArchive.js'; + +const _textDecoder = new TextDecoder(); + +function getResourcePath( loaderPath, url ) { + + if ( loaderPath ) return loaderPath; + + const index = url.lastIndexOf( '/' ); + return index === - 1 ? '' : url.slice( 0, index + 1 ); } -// Ref: https://github.com/mrdoob/three.js/issues/24674 - -// Enhanced separate node to support multi-output referencing (outx, outy, outz, outw) - -// Type/arity-aware MaterialX node wrappers - -const MXElements = [ - - // << Math >> - new MXElement( 'add', mx_add, [ 'in1', 'in2' ] ), - new MXElement( 'subtract', mx_subtract, [ 'in1', 'in2' ] ), - new MXElement( 'multiply', mx_multiply, [ 'in1', 'in2' ] ), - new MXElement( 'divide', mx_divide, [ 'in1', 'in2' ] ), - new MXElement( 'modulo', mx_modulo, [ 'in1', 'in2' ] ), - new MXElement( 'absval', abs, [ 'in1', 'in2' ] ), - new MXElement( 'sign', sign, [ 'in1', 'in2' ] ), - new MXElement( 'floor', floor, [ 'in1', 'in2' ] ), - new MXElement( 'ceil', ceil, [ 'in1', 'in2' ] ), - new MXElement( 'round', round, [ 'in1', 'in2' ] ), - new MXElement( 'power', mx_power, [ 'in1', 'in2' ] ), - new MXElement( 'sin', sin, [ 'in' ] ), - new MXElement( 'cos', cos, [ 'in' ] ), - new MXElement( 'tan', tan, [ 'in' ] ), - new MXElement( 'asin', asin, [ 'in' ] ), - new MXElement( 'acos', acos, [ 'in' ] ), - new MXElement( 'atan2', mx_atan2, [ 'in1', 'in2' ] ), - new MXElement( 'sqrt', sqrt, [ 'in' ] ), - new MXElement( 'ln', log, [ 'in' ] ), - new MXElement( 'exp', exp, [ 'in' ] ), - new MXElement( 'clamp', clamp, [ 'in', 'low', 'high' ] ), - new MXElement( 'min', min, [ 'in1', 'in2' ] ), - new MXElement( 'max', max, [ 'in1', 'in2' ] ), - new MXElement( 'normalize', normalize, [ 'in' ] ), - new MXElement( 'magnitude', length, [ 'in1', 'in2' ] ), - new MXElement( 'dotproduct', dot, [ 'in1', 'in2' ] ), - new MXElement( 'crossproduct', cross, [ 'in' ] ), - new MXElement( 'distance', distance, [ 'in1', 'in2' ] ), - new MXElement( 'invert', mx_invert, [ 'in', 'amount' ] ), - //new MtlXElement( 'transformpoint', ... ), - //new MtlXElement( 'transformvector', ... ), - //new MtlXElement( 'transformnormal', ... ), - new MXElement( 'transformmatrix', mul, [ 'in1', 'in2' ] ), - new MXElement( 'normalmap', normalMap, [ 'in', 'scale' ] ), - new MXElement( 'transpose', transpose, [ 'in' ] ), - new MXElement( 'determinant', determinant, [ 'in' ] ), - new MXElement( 'invertmatrix', inverse, [ 'in' ] ), - new MXElement( 'creatematrix', mat3, [ 'in1', 'in2', 'in3' ] ), - //new MtlXElement( 'rotate2d', rotateUV, [ 'in', radians( 'amount' )** ] ), - //new MtlXElement( 'rotate3d', ... ), - //new MtlXElement( 'arrayappend', ... ), - //new MtlXElement( 'dot', ... ), - - new MXElement( 'length', length, [ 'in' ] ), - new MXElement( 'crossproduct', cross, [ 'in1', 'in2' ] ), - new MXElement( 'floor', floor, [ 'in' ] ), - new MXElement( 'ceil', ceil, [ 'in' ] ), - - // << Adjustment >> - new MXElement( 'remap', remap, [ 'in', 'inlow', 'inhigh', 'outlow', 'outhigh' ] ), - new MXElement( 'smoothstep', smoothstep, [ 'in', 'low', 'high' ] ), - //new MtlXElement( 'curveadjust', ... ), - //new MtlXElement( 'curvelookup', ... ), - new MXElement( 'luminance', luminance, [ 'in', 'lumacoeffs' ] ), - new MXElement( 'rgbtohsv', mx_rgbtohsv, [ 'in' ] ), - new MXElement( 'hsvtorgb', mx_hsvtorgb, [ 'in' ] ), - - // << Mix >> - new MXElement( 'mix', mix, [ 'bg', 'fg', 'mix' ] ), - - // << Channel >> - new MXElement( 'combine2', vec2, [ 'in1', 'in2' ] ), - new MXElement( 'combine3', vec3, [ 'in1', 'in2', 'in3' ] ), - new MXElement( 'combine4', vec4, [ 'in1', 'in2', 'in3', 'in4' ] ), - - // << Procedural >> - new MXElement( 'ramplr', mx_ramplr, [ 'valuel', 'valuer', 'texcoord' ] ), - new MXElement( 'ramptb', mx_ramptb, [ 'valuet', 'valueb', 'texcoord' ] ), - new MXElement( 'ramp4', mx_ramp4, [ 'valuetl', 'valuetr', 'valuebl', 'valuebr', 'texcoord' ] ), - new MXElement( 'splitlr', mx_splitlr, [ 'valuel', 'valuer', 'texcoord' ] ), - new MXElement( 'splittb', mx_splittb, [ 'valuet', 'valueb', 'texcoord' ] ), - new MXElement( 'noise2d', mx_noise_float, [ 'texcoord', 'amplitude', 'pivot' ] ), - new MXElement( 'noise3d', mx_noise_float, [ 'texcoord', 'amplitude', 'pivot' ] ), - new MXElement( 'fractal3d', mx_fractal_noise_float, [ 'position', 'octaves', 'lacunarity', 'diminish', 'amplitude' ] ), - new MXElement( 'cellnoise2d', mx_cell_noise_float, [ 'texcoord' ] ), - new MXElement( 'cellnoise3d', mx_cell_noise_float, [ 'texcoord' ] ), - new MXElement( 'worleynoise2d', mx_worley_noise_float, [ 'texcoord', 'jitter' ] ), - new MXElement( 'worleynoise3d', mx_worley_noise_float, [ 'texcoord', 'jitter' ] ), - new MXElement( 'unifiednoise2d', mx_unifiednoise2d, [ 'type', 'texcoord', 'freq', 'offset', 'jitter', 'outmin', 'outmax', 'clampoutput', 'octaves', 'lacunarity', 'diminish' ] ), - new MXElement( 'unifiednoise3d', mx_unifiednoise3d, [ 'type', 'texcoord', 'freq', 'offset', 'jitter', 'outmin', 'outmax', 'clampoutput', 'octaves', 'lacunarity', 'diminish' ] ), - // << Supplemental >> - //new MtlXElement( 'tiledimage', ... ), - //new MtlXElement( 'triplanarprojection', triplanarTextures, [ 'filex', 'filey', 'filez' ] ), - //new MtlXElement( 'ramp4', ... ), - new MXElement( 'place2d', mx_place2d, [ 'texcoord', 'pivot', 'scale', 'rotate', 'offset', 'operationorder' ] ), - new MXElement( 'safepower', mx_safepower, [ 'in1', 'in2' ] ), - new MXElement( 'contrast', mx_contrast, [ 'in', 'amount', 'pivot' ] ), - //new MtlXElement( 'hsvadjust', ... ), - new MXElement( 'saturate', saturation, [ 'in', 'amount' ] ), - new MXElement( 'extract', element, [ 'in', 'index' ] ), - new MXElement( 'separate2', mx_separate, [ 'in' ] ), - new MXElement( 'separate3', mx_separate, [ 'in' ] ), - new MXElement( 'separate4', mx_separate, [ 'in' ] ), - new MXElement( 'reflect', reflect, [ 'in', 'normal' ] ), - new MXElement( 'refract', refract, [ 'in', 'normal', 'ior' ] ), - - new MXElement( 'time', mx_timer ), - new MXElement( 'frame', mx_frame ), - new MXElement( 'ifgreater', mx_ifgreater, [ 'value1', 'value2', 'in1', 'in2' ] ), - new MXElement( 'ifgreatereq', mx_ifgreatereq, [ 'value1', 'value2', 'in1', 'in2' ] ), - new MXElement( 'ifequal', mx_ifequal, [ 'value1', 'value2', 'in1', 'in2' ] ), - - // Placeholder implementations for unsupported nodes - new MXElement( 'rotate2d', mx_rotate2d, [ 'in', 'amount' ] ), - new MXElement( 'rotate3d', mx_rotate3d, [ 'in', 'amount', 'axis' ] ), - new MXElement( 'heighttonormal', mx_heighttonormal, [ 'in', 'scale', 'texcoord' ] ), - -]; - -const MtlXLibrary = {}; -MXElements.forEach( element => MtlXLibrary[ element.name ] = element ); - -/** - * A loader for the MaterialX format. - * - * The node materials loaded with this loader can only be used with {@link WebGPURenderer}. - * - * ```js - * const loader = new MaterialXLoader().setPath( SAMPLE_PATH ); - * const materials = await loader.loadAsync( 'standard_surface_brass_tiled.mtlx' ); - * ``` - * - * @augments Loader - * @three_import import { MaterialXLoader } from 'three/addons/loaders/MaterialXLoader.js'; - */ class MaterialXLoader extends Loader { - /** - * Constructs a new MaterialX loader. - * - * @param {LoadingManager} [manager] - The loading manager. - */ constructor( manager ) { super( manager ); + this.archiveDisposer = null; + + } + + dispose() { + + if ( this.archiveDisposer ) { + + this.archiveDisposer(); + this.archiveDisposer = null; + + } + + return this; + } - /** - * Starts loading from the given URL and passes the loaded MaterialX asset - * to the `onLoad()` callback. - * - * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI. - * @param {function(Object)} onLoad - Executed when the loading process has been finished. - * @param {onProgressCallback} onProgress - Executed while the loading is in progress. - * @param {onErrorCallback} onError - Executed when errors occur. - * @return {MaterialXLoader} A reference to this loader. - */ - load( url, onLoad, onProgress, onError ) { + load( url, onLoad, onProgress, onError, options = {} ) { const _onError = function ( e ) { @@ -214,11 +56,12 @@ class MaterialXLoader extends Loader { new FileLoader( this.manager ) .setPath( this.path ) - .load( url, async ( text ) => { + .setResponseType( 'arraybuffer' ) + .load( url, ( data ) => { try { - onLoad( this.parse( text ) ); + onLoad( this.parseBuffer( data, url, options ) ); } catch ( e ) { @@ -232,892 +75,78 @@ class MaterialXLoader extends Loader { } - /** - * Parses the given MaterialX data and returns the resulting materials. - * - * Supported standard_surface inputs: - * - base, base_color: Base color/albedo - * - opacity: Alpha/transparency - * - specular_roughness: Surface roughness - * - metalness: Metallic property - * - specular: Specular reflection intensity - * - specular_color: Specular reflection color - * - ior: Index of refraction - * - specular_anisotropy, specular_rotation: Anisotropic reflection - * - transmission, transmission_color: Transmission properties - * - thin_film_thickness, thin_film_ior: Thin film interference - * - sheen, sheen_color, sheen_roughness: Sheen properties - * - normal: Normal map - * - coat, coat_roughness, coat_color: Clearcoat properties - * - emission, emissionColor: Emission properties - * - * @param {string} text - The raw MaterialX data as a string. - * @return {Object} A dictionary holding the parse node materials. - */ - parse( text ) { - - return new MaterialX( this.manager, this.path ).parse( text ); - - } - -} - -class MaterialXNode { - - constructor( materialX, nodeXML, nodePath = '' ) { - - if ( ! materialX || typeof materialX !== 'object' ) { - - console.warn( 'MaterialXNode: materialX argument is not an object!', { materialX, nodeXML, nodePath } ); - - } - - this.materialX = materialX; - this.nodeXML = nodeXML; - this.nodePath = nodePath ? nodePath + '/' + this.name : this.name; - - this.parent = null; - - this.node = null; - - this.children = []; - - } - - get element() { - - return this.nodeXML.nodeName; - - } - - get nodeGraph() { - - return this.getAttribute( 'nodegraph' ); - - } - - get nodeName() { - - return this.getAttribute( 'nodename' ); - - } - - get interfaceName() { - - return this.getAttribute( 'interfacename' ); - - } - - get output() { - - return this.getAttribute( 'output' ); - - } - - get name() { - - return this.getAttribute( 'name' ); - - } - - get type() { - - return this.getAttribute( 'type' ); - - } - - get value() { - - return this.getAttribute( 'value' ); - - } - - getNodeGraph() { - - let nodeX = this; - - while ( nodeX !== null ) { - - if ( nodeX.element === 'nodegraph' ) { - - break; - - } - - nodeX = nodeX.parent; - - } - - return nodeX; - - } - - getRoot() { - - let nodeX = this; - - while ( nodeX.parent !== null ) { - - nodeX = nodeX.parent; - - } - - return nodeX; - - } - - get referencePath() { - - let referencePath = null; - - if ( this.nodeGraph !== null && this.output !== null ) { - - referencePath = this.nodeGraph + '/' + this.output; - - } else if ( this.nodeName !== null || this.interfaceName !== null ) { - - referencePath = this.getNodeGraph().nodePath + '/' + ( this.nodeName || this.interfaceName ); - - } - - return referencePath; - - } - - get hasReference() { - - return this.referencePath !== null; - - } - - get isConst() { - - return this.element === 'input' && this.value !== null && this.type !== 'filename'; - - } - - getColorSpaceNode() { - - const csSource = this.getAttribute( 'colorspace' ); - const csTarget = this.getRoot().getAttribute( 'colorspace' ); - - const nodeName = `mx_${ csSource }_to_${ csTarget }`; - - return colorSpaceLib[ nodeName ]; - - } - - getTexture() { - - const filePrefix = this.getRecursiveAttribute( 'fileprefix' ) || ''; - const uri = filePrefix + this.value; - - if ( this.materialX.textureCache.has( uri ) ) { - - return this.materialX.textureCache.get( uri ); - - } - - let loader = this.materialX.textureLoader; + loadAsync( url, onProgress, options = {} ) { - if ( uri ) { + if ( onProgress && typeof onProgress === 'object' ) { - const handler = this.materialX.manager.getHandler( uri ); - if ( handler !== null ) loader = handler; + options = onProgress; + onProgress = undefined; } - const texture = new Texture(); - texture.wrapS = texture.wrapT = RepeatWrapping; + return new Promise( ( resolve, reject ) => { - this.materialX.textureCache.set( uri, texture ); - - loader.load( uri, function ( imageBitmap ) { - - texture.image = imageBitmap; - texture.needsUpdate = true; + this.load( url, resolve, onProgress, reject, options ); } ); - return texture; - } - getClassFromType( type ) { - - let nodeClass = null; - - if ( type === 'integer' ) nodeClass = int; - else if ( type === 'float' ) nodeClass = float; - else if ( type === 'vector2' ) nodeClass = vec2; - else if ( type === 'vector3' ) nodeClass = vec3; - else if ( type === 'vector4' || type === 'color4' ) nodeClass = vec4; - else if ( type === 'color3' ) nodeClass = color; - else if ( type === 'boolean' ) nodeClass = bool; - - return nodeClass; - - } - - getNode( out = null ) { - - let node = this.node; - - if ( node !== null && out === null ) { - - return node; - - } - - // Handle - if ( - this.element === 'input' && - this.name === 'texcoord' && - this.type === 'vector2' - ) { - - // Try to get index from defaultgeomprop (e.g., "UV0" => 0) - let index = 0; - const defaultGeomProp = this.getAttribute( 'defaultgeomprop' ); - if ( defaultGeomProp && /^UV(\d+)$/.test( defaultGeomProp ) ) { - - index = parseInt( defaultGeomProp.match( /^UV(\d+)$/ )[ 1 ], 10 ); - - } - - node = uv( index ); - - } - - // Multi-output support for separate/separate3 - if ( - ( this.element === 'separate3' || this.element === 'separate2' || this.element === 'separate4' ) && - out && typeof out === 'string' && out.startsWith( 'out' ) - ) { - - const inNode = this.getNodeByName( 'in' ); - return mx_separate( inNode, out ); - - } - - // - - const type = this.type; - - if ( this.isConst ) { - - const nodeClass = this.getClassFromType( type ); - - node = nodeClass( ...this.getVector() ); - - } else if ( this.hasReference ) { - - if ( this.element === 'output' && this.output && out === null ) { - - out = this.output; - - } - - node = this.materialX.getMaterialXNode( this.referencePath ).getNode( out ); - - } else { - - const element = this.element; - - if ( element === 'convert' ) { - - const nodeClass = this.getClassFromType( type ); - - node = nodeClass( this.getNodeByName( 'in' ) ); - - } else if ( element === 'constant' ) { - - node = this.getNodeByName( 'value' ); - - } else if ( element === 'position' ) { - - const space = this.getAttribute( 'space' ); - node = space === 'world' ? positionWorld : positionLocal; - - } else if ( element === 'normal' ) { - - const space = this.getAttribute( 'space' ); - node = space === 'world' ? normalWorld : normalLocal; - - } else if ( element === 'tangent' ) { - - const space = this.getAttribute( 'space' ); - node = space === 'world' ? tangentWorld : tangentLocal; - - } else if ( element === 'texcoord' ) { - - const indexNode = this.getChildByName( 'index' ); - const index = indexNode ? parseInt( indexNode.value ) : 0; - - node = uv( index ); - - } else if ( element === 'geomcolor' ) { - - const indexNode = this.getChildByName( 'index' ); - const index = indexNode ? parseInt( indexNode.value ) : 0; - - node = vertexColor( index ); - - } else if ( element === 'tiledimage' ) { + parseBuffer( data, url = '', options = {} ) { - const file = this.getChildByName( 'file' ); + this.dispose(); - const textureFile = file.getTexture(); - const uvTiling = mx_transform_uv( ...this.getNodesByNames( [ 'uvtiling', 'uvoffset' ] ) ); + let text; + let archiveResolver = null; - node = texture( textureFile, uvTiling ); + if ( data && ( isZipBuffer( data ) || /\.mtlx\.zip$/i.test( url ) ) ) { - const colorSpaceNode = file.getColorSpaceNode(); + const archive = readMtlxArchive( data ); + text = archive.text; - if ( colorSpaceNode ) { + const resolver = createArchiveResolver( archive.files ); + archiveResolver = resolver.resolve; + this.archiveDisposer = resolver.dispose; - node = colorSpaceNode( node ); + } else if ( typeof data === 'string' ) { - } - - } else if ( element === 'image' ) { - - const file = this.getChildByName( 'file' ); - const uvNode = this.getNodeByName( 'texcoord' ); - - const textureFile = file.getTexture(); - - node = texture( textureFile, uvNode ); - - const colorSpaceNode = file.getColorSpaceNode(); - - if ( colorSpaceNode ) { - - node = colorSpaceNode( node ); - - } - - } else if ( MtlXLibrary[ element ] !== undefined ) { - - const nodeElement = MtlXLibrary[ element ]; - - if ( ! nodeElement ) { - - throw new Error( `THREE.MaterialXLoader: Unexpected node ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` ); - - } - - if ( ! nodeElement.nodeFunc ) { - - throw new Error( `THREE.MaterialXLoader: Unexpected node 2 ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` ); - - } - - if ( out !== null ) { - - node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ), out ); - - } else { - - node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ) ); - - } - - } - - } - - // - - if ( node === null ) { - - console.warn( `THREE.MaterialXLoader: Unexpected node ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` ); - - node = float( 0 ); - - } - - // + text = data; - const nodeToTypeClass = this.getClassFromType( type ); + } else if ( data instanceof Uint8Array ) { - if ( nodeToTypeClass !== null ) { - - node = nodeToTypeClass( node ); + text = _textDecoder.decode( data ); } else { - console.warn( `THREE.MaterialXLoader: Unexpected node ${ new XMLSerializer().serializeToString( this.nodeXML ) }.` ); - node = float( 0 ); + text = _textDecoder.decode( new Uint8Array( data ) ); } - node.name = this.name; - - this.node = node; - - return node; - - } - - getChildByName( name ) { - - for ( const input of this.children ) { - - if ( input.name === name ) { - - return input; - - } - - } - - } - - getNodes() { - - const nodes = {}; - - for ( const input of this.children ) { - - const node = input.getNode(); - - nodes[ node.name ] = node; - - } - - return nodes; - - } - - getNodeByName( name ) { - - const child = this.getChildByName( name ); - - return child ? child.getNode( child.output ) : undefined; - - } - - getNodesByNames( ...names ) { - - const nodes = []; - - for ( const name of names ) { - - const node = this.getNodeByName( name ); - - if ( node ) nodes.push( node ); - - } - - return nodes; - - } - - getValue() { - - return this.value.trim(); - - } - - getVector() { - - const vector = []; - - for ( const val of this.getValue().split( /[,|\s]/ ) ) { - - if ( val !== '' ) { - - vector.push( Number( val.trim() ) ); - - } - - } - - return vector; - - } - - getAttribute( name ) { - - return this.nodeXML.getAttribute( name ); - - } - - getRecursiveAttribute( name ) { - - let attribute = this.nodeXML.getAttribute( name ); - - if ( attribute === null && this.parent !== null ) { - - attribute = this.parent.getRecursiveAttribute( name ); - - } - - return attribute; - - } - - setStandardSurfaceToGltfPBR( material ) { - - const inputs = this.getNodes(); - - // - - let colorNode = null; - - if ( inputs.base && inputs.base_color ) colorNode = mul( inputs.base, inputs.base_color ); - else if ( inputs.base ) colorNode = inputs.base; - else if ( inputs.base_color ) colorNode = inputs.base_color; - - // - - let opacityNode = null; - - if ( inputs.opacity ) opacityNode = inputs.opacity; - - // - - let roughnessNode = null; - - if ( inputs.specular_roughness ) roughnessNode = inputs.specular_roughness; - - // - - let metalnessNode = null; - - if ( inputs.metalness ) metalnessNode = inputs.metalness; - - // - - let specularIntensityNode = null; - - if ( inputs.specular ) specularIntensityNode = inputs.specular; - - // - - let specularColorNode = null; - - if ( inputs.specular_color ) specularColorNode = inputs.specular_color; - - // - - let iorNode = null; - - if ( inputs.ior ) iorNode = inputs.ior; - - // - - let anisotropyNode = null; - let anisotropyRotationNode = null; - - if ( inputs.specular_anisotropy ) anisotropyNode = inputs.specular_anisotropy; - if ( inputs.specular_rotation ) anisotropyRotationNode = inputs.specular_rotation; - - // - - let transmissionNode = null; - let transmissionColorNode = null; - - if ( inputs.transmission ) transmissionNode = inputs.transmission; - if ( inputs.transmission_color ) transmissionColorNode = inputs.transmission_color; - - // - - let thinFilmThicknessNode = null; - let thinFilmIorNode = null; - - if ( inputs.thin_film_thickness ) thinFilmThicknessNode = inputs.thin_film_thickness; - - if ( inputs.thin_film_ior ) { - - // Clamp IOR to valid range for Three.js (1.0 to 2.333) - thinFilmIorNode = clamp( inputs.thin_film_ior, float( 1.0 ), float( 2.333 ) ); - - } - - // - - let sheenNode = null; - let sheenColorNode = null; - let sheenRoughnessNode = null; - - if ( inputs.sheen ) sheenNode = inputs.sheen; - if ( inputs.sheen_color ) sheenColorNode = inputs.sheen_color; - if ( inputs.sheen_roughness ) sheenRoughnessNode = inputs.sheen_roughness; - - // - - let clearcoatNode = null; - let clearcoatRoughnessNode = null; - - if ( inputs.coat ) clearcoatNode = inputs.coat; - if ( inputs.coat_roughness ) clearcoatRoughnessNode = inputs.coat_roughness; - - if ( inputs.coat_color ) { - - colorNode = colorNode ? mul( colorNode, inputs.coat_color ) : colorNode; - - } - - // - - let normalNode = null; - - if ( inputs.normal ) normalNode = inputs.normal; - - // - - let emissiveNode = null; - - if ( inputs.emission ) emissiveNode = inputs.emission; - if ( inputs.emissionColor ) { - - emissiveNode = emissiveNode ? mul( emissiveNode, inputs.emissionColor ) : emissiveNode; - - } - - // - - material.colorNode = colorNode || color( 0.8, 0.8, 0.8 ); - material.opacityNode = opacityNode || float( 1.0 ); - material.roughnessNode = roughnessNode || float( 0.2 ); - material.metalnessNode = metalnessNode || float( 0 ); - material.specularIntensityNode = specularIntensityNode || float( 0.5 ); - material.specularColorNode = specularColorNode || color( 1.0, 1.0, 1.0 ); - material.iorNode = iorNode || float( 1.5 ); - - if ( anisotropyNode !== null ) { - - material.anisotropyNode = anisotropyNode; - material.anisotropyRotationNode = anisotropyRotationNode || float( 0 ); - - } - - if ( transmissionNode !== null ) { - - material.transmissionNode = transmissionNode; - material.transmissionColorNode = transmissionColorNode || color( 1.0, 1.0, 1.0 ); - - } - - material.thinFilmThicknessNode = thinFilmThicknessNode || float( 0 ); - material.thinFilmIorNode = thinFilmIorNode || float( 1.5 ); - - if ( sheenNode !== null ) { - - material.sheenNode = sheenNode; - material.sheenColorNode = sheenColorNode || color( 1.0, 1.0, 1.0 ); - material.sheenRoughnessNode = sheenRoughnessNode || float( 0.5 ); - - } - - if ( clearcoatNode !== null ) { - - material.clearcoatNode = clearcoatNode; - material.clearcoatRoughnessNode = clearcoatRoughnessNode || float( 0 ); - - } - - if ( normalNode ) material.normalNode = normalNode; - if ( emissiveNode ) material.emissiveNode = emissiveNode; - - // Auto-enable iridescence when thin film parameters are present - if ( thinFilmThicknessNode && thinFilmThicknessNode.value !== undefined && thinFilmThicknessNode.value > 0 ) { - - material.iridescence = 1.0; - - } - - if ( opacityNode !== null ) { - - material.transparent = true; - - } - - if ( transmissionNode !== null ) { - - material.side = DoubleSide; - material.transparent = true; - - } - - } - - /*setGltfPBR( material ) { - - const inputs = this.getNodes(); - - console.log( inputs ); - - }*/ - - setMaterial( material ) { - - const element = this.element; - - if ( element === 'gltf_pbr' ) { - - //this.setGltfPBR( material ); - - } else if ( element === 'standard_surface' ) { - - this.setStandardSurfaceToGltfPBR( material ); - - } - - } - - toBasicMaterial() { - - const material = new MeshBasicNodeMaterial(); - material.name = this.name; - - for ( const nodeX of this.children.toReversed() ) { - - if ( nodeX.name === 'out' ) { - - material.colorNode = nodeX.getNode(); - - break; - - } - - } - - return material; - - } - - toPhysicalMaterial() { - - const material = new MeshPhysicalNodeMaterial(); - material.name = this.name; - - for ( const nodeX of this.children ) { - - const shaderProperties = this.materialX.getMaterialXNode( nodeX.nodeName ); - shaderProperties.setMaterial( material ); - - } - - return material; - - } - - toMaterials() { - - const materials = {}; - - let isUnlit = true; - - for ( const nodeX of this.children ) { - - if ( nodeX.element === 'surfacematerial' ) { - - const material = nodeX.toPhysicalMaterial(); - - materials[ material.name ] = material; - - isUnlit = false; - - } - - } - - if ( isUnlit ) { - - for ( const nodeX of this.children ) { - - if ( nodeX.element === 'nodegraph' ) { - - const material = nodeX.toBasicMaterial(); - - materials[ material.name ] = material; - - } - - } - - } - - return materials; - - } - - add( materialXNode ) { - - materialXNode.parent = this; - - this.children.push( materialXNode ); - - } - -} - -class MaterialX { - - constructor( manager, path ) { - - this.manager = manager; - this.path = path; - this.resourcePath = ''; - - this.nodesXLib = new Map(); - //this.nodesXRefLib = new WeakMap(); - - this.textureLoader = new ImageBitmapLoader( manager ); - this.textureLoader.setOptions( { imageOrientation: 'flipY' } ); - - this.textureCache = new Map(); - - } - - addMaterialXNode( materialXNode ) { - - this.nodesXLib.set( materialXNode.nodePath, materialXNode ); + return this.parse( text, { + ...options, + archiveResolver, + path: options.path || getResourcePath( this.path, url ) + } ); } - /*getMaterialXNodeFromXML( xmlNode ) { - - return this.nodesXRefLib.get( xmlNode ); + parse( text, options = {} ) { - }*/ + const log = new MaterialXLog(); - getMaterialXNode( ...names ) { - - return this.nodesXLib.get( names.join( '/' ) ); - - } - - parseNode( nodeXML, nodePath = '' ) { - - const materialXNode = new MaterialXNode( this, nodeXML, nodePath ); - if ( materialXNode.nodePath ) this.addMaterialXNode( materialXNode ); + const document = new MaterialXDocument( this.manager, options.path || this.path, log, options.archiveResolver || null, options.uvSpace ); + const result = document.parse( text, options.materialName || null, { + interfaceValidator: options.interfaceValidator, + } ); - for ( const childNodeXML of nodeXML.children ) { + if ( options.throwOnErrors !== false && log.errors.length > 0 ) { - const childMXNode = this.parseNode( childNodeXML, materialXNode.nodePath ); - materialXNode.add( childMXNode ); + const details = log.errors.map( ( error ) => error.message ).join( ' ' ); + throw new Error( `THREE.MaterialXLoader: MaterialX translation failed with ${log.errors.length} error(s). ${details}` ); } - return materialXNode; - - } - - parse( text ) { - - const rootXML = new DOMParser().parseFromString( text, 'application/xml' ).documentElement; - - this.textureLoader.setPath( this.path ); - - // - - const materials = this.parseNode( rootXML ).toMaterials(); - - return { materials }; + return result; } diff --git a/examples/jsm/loaders/materialx/MaterialXArchive.js b/examples/jsm/loaders/materialx/MaterialXArchive.js new file mode 100644 index 00000000000000..da98c6108c2570 --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXArchive.js @@ -0,0 +1,108 @@ +import { unzipSync } from '../../libs/fflate.module.js'; + +const _textDecoder = new TextDecoder(); + +function normalizePath( path ) { + + return path + .split( '\\' ).join( '/' ) + .replace( /^\.?\//, '' ) + .replace( /^\/+/, '' ); + +} + +function isZipBuffer( buffer ) { + + const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer ); + return bytes.length >= 4 && bytes[ 0 ] === 0x50 && bytes[ 1 ] === 0x4b; + +} + +function readMtlxArchive( buffer ) { + + const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array( buffer ); + const archive = unzipSync( bytes ); + + const fileMap = new Map(); + let mtlxPath = null; + + for ( const path in archive ) { + + const normalizedPath = normalizePath( path ); + fileMap.set( normalizedPath, archive[ path ] ); + + if ( normalizedPath.toLowerCase().endsWith( '.mtlx' ) ) { + + if ( mtlxPath !== null ) { + + throw new Error( 'THREE.MaterialXLoader: Invalid .mtlx.zip package. Exactly one .mtlx file is required.' ); + + } + + mtlxPath = normalizedPath; + + } + + } + + if ( mtlxPath === null ) { + + throw new Error( 'THREE.MaterialXLoader: Invalid .mtlx.zip package. Missing .mtlx file.' ); + + } + + const text = _textDecoder.decode( fileMap.get( mtlxPath ) ); + return { text, mtlxPath, files: fileMap }; + +} + +function createArchiveResolver( files ) { + + const objectUrlCache = new Map(); + + const getFile = ( uri ) => { + + const normalized = normalizePath( decodeURI( uri ) ); + if ( files.has( normalized ) ) return files.get( normalized ); + + for ( const [ path, bytes ] of files ) { + + if ( path.endsWith( normalized ) ) return bytes; + + } + + return null; + + }; + + const resolve = ( uri ) => { + + if ( objectUrlCache.has( uri ) ) return objectUrlCache.get( uri ); + + const bytes = getFile( uri ); + if ( ! bytes ) return null; + + const blob = new Blob( [ bytes ], { type: 'application/octet-stream' } ); + const objectUrl = URL.createObjectURL( blob ); + objectUrlCache.set( uri, objectUrl ); + return objectUrl; + + }; + + const dispose = () => { + + for ( const objectUrl of objectUrlCache.values() ) { + + URL.revokeObjectURL( objectUrl ); + + } + + objectUrlCache.clear(); + + }; + + return { resolve, dispose }; + +} + +export { isZipBuffer, readMtlxArchive, createArchiveResolver }; diff --git a/examples/jsm/loaders/materialx/MaterialXDocument.js b/examples/jsm/loaders/materialx/MaterialXDocument.js new file mode 100644 index 00000000000000..a97c7e4636cf52 --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXDocument.js @@ -0,0 +1,878 @@ +import { + Texture, + RepeatWrapping, + ClampToEdgeWrapping, + MirroredRepeatWrapping, + ImageLoader, + ImageBitmapLoader, + Matrix3, + Matrix4, + MeshBasicNodeMaterial, + MeshPhysicalNodeMaterial, +} from 'three/webgpu'; + +import { + float, + int, + bool, + sub, + vec2, + vec3, + vec4, + color, + uv, + mat3, + mat4, + element, + mx_transform_uv, + mx_srgb_texture_to_lin_rec709, +} from 'three/tsl'; + +import { MaterialXLogCodes } from './MaterialXLog.js'; +import { createMaterialXCompileRegistry, compileNodeFromRegistry } from './compile/MaterialXCompileRegistry.js'; +import { parseMaterialXNodeTree, parseMaterialXText } from './parse/MaterialXParser.js'; +import { getSurfaceMapper } from './MaterialXSurfaceMappings.js'; +import { MtlXLibrary } from './MaterialXNodeLibrary.js'; +import { mxHextileCoord, mxHextileComputeBlendWeights } from './MaterialXHextile.js'; +import { toBooleanNode } from './MaterialXUtils.js'; + +const colorSpaceLib = { + mx_srgb_texture_to_lin_rec709, +}; + +const DEFAULT_DOCUMENT_COLOR_SPACE = 'lin_rec709'; +const IDENTITY_MAT3_VALUES = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; +const IDENTITY_MAT4_VALUES = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]; +const MATRIX_INVERSE_EPSILON = 1e-8; +const COMPILE_REGISTRY = createMaterialXCompileRegistry(); +const TEXTURE_ADDRESS_MODE_WRAPPING = { + constant: ClampToEdgeWrapping, + clamp: ClampToEdgeWrapping, + periodic: RepeatWrapping, + mirror: MirroredRepeatWrapping, +}; +const NODE_CLASS_BY_TYPE = { + integer: int, + float, + vector2: vec2, + vector3: vec3, + vector4: vec4, + color4: vec4, + color3: color, + boolean: null, + matrix33: mat3, + matrix44: mat4, +}; +const OUTPUT_CHANNELS = { + outx: 0, + outr: 0, + outy: 1, + outg: 1, + outz: 2, + outb: 2, + outw: 3, + outa: 3, +}; + +function mxFlipUvY( uvNode ) { + + return vec2( element( uvNode, 0 ), sub( 1, element( uvNode, 1 ) ) ); + +} + +function mxIdentityUv( uvNode ) { + + return uvNode; + +} + +function getBottomLeftUvSpaceHelpers( uvSpace ) { + + const helper = uvSpace === 'top-left' ? mxFlipUvY : mxIdentityUv; + return { + mxToBottomLeftUvSpace: helper, + mxFromBottomLeftUvSpace: helper, + }; + +} + +function normalizeUvSpace( uvSpace ) { + + if ( uvSpace === undefined || uvSpace === null ) return 'bottom-left'; + if ( uvSpace === 'bottom-left' || uvSpace === 'top-left' ) return uvSpace; + throw new Error( `Unsupported MaterialX uvSpace "${uvSpace}". Expected "bottom-left" or "top-left".` ); + +} + +function isSvgUri( uri ) { + + if ( typeof uri !== 'string' ) return false; + return /\.svg(?:$|[?#])/i.test( uri ); + +} + +function normalizeTextureAddressMode( value ) { + + if ( value === null || value === undefined || value === '' ) return 'periodic'; + + const mode = value.trim().toLowerCase(); + return mode in TEXTURE_ADDRESS_MODE_WRAPPING ? mode : null; + +} + +function invertConstantMatrixValues( values, size ) { + + if ( ! Array.isArray( values ) || values.length !== size * size ) return null; + + if ( size === 3 ) { + + const matrix = new Matrix3().setFromArray( values ); + if ( Math.abs( matrix.determinant() ) < MATRIX_INVERSE_EPSILON ) return null; + matrix.invert(); + // Convert Three.js internal column-major storage back to row-major literal order. + return matrix.transpose().elements; + + } + + if ( size === 4 ) { + + const matrix = new Matrix4().setFromArray( values ); + if ( Math.abs( matrix.determinant() ) < MATRIX_INVERSE_EPSILON ) return null; + matrix.invert(); + // Convert Three.js internal column-major storage back to row-major literal order. + return matrix.transpose().elements; + + } + + return null; + +} + +function getOutputChannel( outputName ) { + + return OUTPUT_CHANNELS[ outputName ] || 0; + +} + +function isChannelOutput( outputName ) { + + return outputName in OUTPUT_CHANNELS; + +} + +class MaterialXNode { + + constructor( materialX, nodeXML, nodePath = '' ) { + + this.materialX = materialX; + this.nodeXML = nodeXML; + this.nodePath = nodePath ? nodePath + '/' + this.name : this.name; + this.parent = null; + this.node = null; + this.children = []; + + } + + get element() { + + return this.nodeXML.nodeName; + + } + get nodeGraph() { + + return this.getAttribute( 'nodegraph' ); + + } + get nodeName() { + + return this.getAttribute( 'nodename' ); + + } + get interfaceName() { + + return this.getAttribute( 'interfacename' ); + + } + get output() { + + return this.getAttribute( 'output' ); + + } + get name() { + + return this.getAttribute( 'name' ); + + } + get type() { + + return this.getAttribute( 'type' ); + + } + get value() { + + return this.getAttribute( 'value' ); + + } + + getNodeGraph() { + + let nodeX = this; + while ( nodeX !== null ) { + + if ( nodeX.element === 'nodegraph' ) break; + nodeX = nodeX.parent; + + } + + return nodeX; + + } + + getRoot() { + + let nodeX = this; + while ( nodeX.parent !== null ) { + + nodeX = nodeX.parent; + + } + + return nodeX; + + } + + get referencePath() { + + let referencePath = null; + if ( this.nodeGraph !== null && this.output !== null ) { + + referencePath = this.nodeGraph + '/' + this.output; + + } else if ( this.nodeName !== null || this.interfaceName !== null ) { + + const graphNode = this.getNodeGraph(); + const scopedReference = this.nodeName || this.interfaceName; + if ( graphNode && scopedReference ) { + + referencePath = graphNode.nodePath + '/' + scopedReference; + + } else if ( this.nodeName !== null ) { + + // Surface-level nodename links can legitimately target top-level siblings. + referencePath = this.nodeName; + + } + + } + + return referencePath; + + } + + get hasReference() { + + return this.referencePath !== null; + + } + get isConst() { + + return this.element === 'input' && this.value !== null && this.type !== 'filename'; + + } + + getColorSpaceNode() { + + const csSource = this.getAttribute( 'colorspace' ); + const csTarget = this.getRoot().getAttribute( 'colorspace' ); + if ( ! csSource || ! csTarget ) return null; + const nodeName = `mx_${csSource}_to_${csTarget}`; + return colorSpaceLib[ nodeName ] || null; + + } + + getTextureAddressMode( inputName ) { + + const rawMode = this.getInputValueByName( inputName ); + const mode = normalizeTextureAddressMode( rawMode ); + if ( mode ) return mode; + + this.materialX.log.add( + MaterialXLogCodes.INVALID_VALUE, + `Unsupported texture address mode "${rawMode}" on input "${inputName}". Expected constant, clamp, periodic, or mirror.`, + this.name, + ); + return 'periodic'; + + } + + getTextureAddressModes() { + + return { + u: this.getTextureAddressMode( 'uaddressmode' ), + v: this.getTextureAddressMode( 'vaddressmode' ), + }; + + } + + getTexture() { + + const filePrefix = this.getRecursiveAttribute( 'fileprefix' ) || ''; + const sourceURI = filePrefix + this.value; + const resolvedURI = this.materialX.resolveTextureURI( sourceURI ); + const svgTexture = isSvgUri( resolvedURI ); + const textureSourceNode = this.parent && typeof this.parent.getTextureAddressModes === 'function' ? this.parent : this; + const addressModes = textureSourceNode.getTextureAddressModes(); + const textureCacheKey = `${resolvedURI}|${addressModes.u}|${addressModes.v}`; + + if ( this.materialX.textureCache.has( textureCacheKey ) ) { + + return this.materialX.textureCache.get( textureCacheKey ); + + } + + let loader = svgTexture ? this.materialX.imageLoader : this.materialX.textureLoader; + if ( resolvedURI && ! svgTexture ) { + + const handler = this.materialX.manager.getHandler( resolvedURI ); + if ( handler !== null ) loader = handler; + + } + + const textureNode = new Texture(); + textureNode.wrapS = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.u ]; + textureNode.wrapT = TEXTURE_ADDRESS_MODE_WRAPPING[ addressModes.v ]; + textureNode.flipY = false; + this.materialX.textureCache.set( textureCacheKey, textureNode ); + + loader.load( resolvedURI, ( imageData ) => { + + textureNode.image = imageData; + textureNode.needsUpdate = true; + + }, undefined, () => { + + throw new Error( `Failed to load texture "${resolvedURI}".` ); + + } ); + + return textureNode; + + } + + getClassFromType( type ) { + + return NODE_CLASS_BY_TYPE[ type ] || null; + + } + + toBooleanNode( node ) { + + return toBooleanNode( node ); + + } + + getNode( out = null ) { + + if ( this.node !== null && out === null ) return this.node; + + let node; + + + if ( ( this.element === 'separate2' || this.element === 'separate3' || this.element === 'separate4' ) && out ) { + + const inNode = this.getNodeByName( 'in' ); + return element( inNode, getOutputChannel( out ) ); + + } + + const type = this.type; + const channelRequested = this.element !== 'input' && this.element !== 'gltf_colorimage' && isChannelOutput( out ); + + if ( this.isConst ) { + + if ( type === 'boolean' ) { + + const normalized = this.getValue().trim().toLowerCase(); + node = bool( normalized === 'true' || normalized === '1' ); + + } else if ( type === 'matrix33' ) { + + node = this.getMatrix( 3 ) || mat3( 1, 0, 0, 0, 1, 0, 0, 0, 1 ); + + } else if ( type === 'matrix44' ) { + + node = this.getMatrix( 4 ) || mat4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ); + + } else if ( type === 'string' ) { + + node = this.getValue(); + + } else { + + const nodeClass = this.getClassFromType( type ); + node = nodeClass ? nodeClass( ...this.getVector() ) : float( 0 ); + + } + + } else if ( this.hasReference ) { + + if ( this.element === 'output' && this.output && out === null ) out = this.output; + let requestedOutput = out; + // For nodegraph references, this input's `output` attribute selects the graph output + // itself and should not be forwarded as an output selector on the resolved node. + if ( this.element === 'input' && this.nodeGraph !== null && this.output !== null ) { + + requestedOutput = null; + + } + + const referenceNode = this.materialX.getMaterialXNode( this.referencePath ); + + if ( referenceNode ) { + + node = referenceNode.getNode( requestedOutput ); + + } else { + + this.materialX.log.add( + MaterialXLogCodes.MISSING_REFERENCE, + `Missing MaterialX reference "${this.referencePath}" from "${this.name}".`, + this.name, + ); + node = float( 0 ); + + } + + } else if ( this.element === 'input' && this.name === 'texcoord' && this.type === 'vector2' ) { + + let index = 0; + const defaultGeomProp = this.getAttribute( 'defaultgeomprop' ); + if ( defaultGeomProp && /^UV(\d+)$/.test( defaultGeomProp ) ) { + + index = parseInt( defaultGeomProp.match( /^UV(\d+)$/ )[ 1 ], 10 ); + + } + + node = this.materialX.compileContext.mxToBottomLeftUvSpace( uv( index ) ); + + } else { + + node = compileNodeFromRegistry( this, out, this.materialX.compileContext ); + + } + + if ( node === null || node === undefined ) { + + this.materialX.log.add( + MaterialXLogCodes.UNSUPPORTED_NODE, + `Unsupported MaterialX node category "${this.element}" on "${this.name}".`, + this.name, + ); + node = float( 0 ); + + } + + if ( channelRequested ) { + + node = element( node, getOutputChannel( out ) ); + + } + + const resolvedType = channelRequested ? 'float' : type; + if ( resolvedType === 'boolean' ) { + + node = this.toBooleanNode( node ); + + } else if ( resolvedType === 'string' ) { + + // String-typed inputs (for example transform* fromspace/tospace) are + // valid scalar parameters and should pass through without numeric casting. + node = typeof node === 'string' ? node : this.getValue(); + + } else { + + const nodeToTypeClass = this.getClassFromType( resolvedType ); + if ( nodeToTypeClass !== null ) { + + node = nodeToTypeClass( node ); + + } else if ( resolvedType !== null && resolvedType !== undefined && resolvedType !== 'multioutput' ) { + + this.materialX.log.add( + MaterialXLogCodes.INVALID_VALUE, + `Unexpected type "${resolvedType}" on node "${this.name}".`, + this.name, + ); + node = float( 0 ); + + } + + } + + if ( node && typeof node === 'object' ) { + + node.name = this.name; + + } + + this.node = node; + return node; + + } + + getChildByName( name ) { + + for ( const input of this.children ) { + + if ( input.name === name ) return input; + + } + + } + + getNodes() { + + const nodes = {}; + for ( const input of this.children ) { + + const value = input.getNode( input.output ); + nodes[ input.name ] = value; + + } + + return nodes; + + } + + getNodeByName( name ) { + + const child = this.getChildByName( name ); + return child ? child.getNode( child.output ) : undefined; + + } + + getInputValueByName( name ) { + + const child = this.getChildByName( name ); + return child ? child.value : null; + + } + + getNodesByNames( ...names ) { + + const nodes = []; + for ( const name of names ) { + + const nodeValue = this.getNodeByName( name ); + nodes.push( nodeValue ); + + } + + return nodes; + + } + + getValue() { + + return this.value ? this.value.trim() : ''; + + } + + getVector() { + + const vector = []; + for ( const val of this.getValue().split( /[,|\s]/ ) ) { + + if ( val !== '' ) vector.push( Number( val.trim() ) ); + + } + + return vector; + + } + + getMatrix( size ) { + + const vector = this.getVector(); + const expectedLength = size * size; + if ( vector.length !== expectedLength ) return null; + // MaterialX matrix values are serialized in column-major order. + // Reorder to row-major before constructing TSL matrix nodes so + // transformmatrix semantics match MaterialXJS and MaterialXView. + const reordered = []; + for ( let row = 0; row < size; row += 1 ) { + + for ( let column = 0; column < size; column += 1 ) { + + reordered.push( vector[ column * size + row ] ); + + } + + } + + return size === 3 ? mat3( ...reordered ) : mat4( ...reordered ); + + } + + getAttribute( name ) { + + const value = this.nodeXML.getAttribute( name ); + if ( value === null && this.element === 'materialx' && name === 'colorspace' ) { + + return DEFAULT_DOCUMENT_COLOR_SPACE; + + } + + return value; + + } + + getRecursiveAttribute( name ) { + + let attribute = this.nodeXML.getAttribute( name ); + if ( attribute === null && this.parent !== null ) { + + attribute = this.parent.getRecursiveAttribute( name ); + + } + + return attribute; + + } + + setMaterial( material ) { + + const mapper = getSurfaceMapper( this.element ); + if ( mapper ) { + + mapper.apply( material, this.getNodes(), this.materialX.log, this.name ); + + } else { + + this.materialX.log.add( + MaterialXLogCodes.UNSUPPORTED_NODE, + `Unsupported MaterialX node category "${this.element}" on "${this.name}".`, + this.name, + ); + + } + + } + + toBasicMaterial() { + + const material = new MeshBasicNodeMaterial(); + material.name = this.name; + + for ( const nodeX of this.children.toReversed() ) { + + if ( nodeX.name === 'out' ) { + + material.colorNode = nodeX.getNode(); + break; + + } + + } + + return material; + + } + + resolveSurfaceShaderNode( nodeX ) { + + if ( nodeX.hasReference ) { + + return this.materialX.getMaterialXNode( nodeX.referencePath ) || null; + + } + + if ( nodeX.nodeName ) { + + return this.materialX.getMaterialXNode( nodeX.nodeName ) || null; + + } + + return null; + + } + + toPhysicalMaterial() { + + const material = new MeshPhysicalNodeMaterial(); + material.name = this.name; + + for ( const nodeX of this.children ) { + + const shaderProperties = this.resolveSurfaceShaderNode( nodeX ); + if ( shaderProperties === null ) { + + this.materialX.log.add( + MaterialXLogCodes.MISSING_REFERENCE, + `Missing MaterialX reference "${nodeX.referencePath || nodeX.nodeName || '(unknown)'}" from "${nodeX.name}".`, + nodeX.name, + ); + continue; + + } + + shaderProperties.setMaterial( material ); + + } + + return material; + + } + + toMaterials( materialName = null ) { + + const materials = {}; + const surfaceMaterials = this.children.filter( ( nodeX ) => nodeX.element === 'surfacematerial' ); + + let selectedSurfaceMaterials = surfaceMaterials; + if ( materialName ) { + + selectedSurfaceMaterials = surfaceMaterials.filter( ( nodeX ) => nodeX.name === materialName ); + + if ( selectedSurfaceMaterials.length === 0 ) { + + this.materialX.log.add( + MaterialXLogCodes.MISSING_MATERIAL, + `Could not find surfacematerial named "${materialName}".`, + ); + + } + + } + + for ( const nodeX of selectedSurfaceMaterials ) { + + const material = nodeX.toPhysicalMaterial(); + materials[ material.name ] = material; + + } + + if ( Object.keys( materials ).length === 0 ) { + + for ( const nodeX of this.children ) { + + if ( nodeX.element === 'nodegraph' ) { + + const material = nodeX.toBasicMaterial(); + materials[ material.name ] = material; + + } + + } + + } + + return materials; + + } + + add( materialXNode ) { + + materialXNode.parent = this; + this.children.push( materialXNode ); + + } + +} + +class MaterialXDocument { + + constructor( manager, path, log, archiveResolver = null, uvSpace = 'bottom-left' ) { + + this.manager = manager; + this.path = path; + this.log = log; + this.archiveResolver = archiveResolver; + this.uvSpace = normalizeUvSpace( uvSpace ); + + this.nodesXLib = new Map(); + this.imageLoader = new ImageLoader( manager ); + this.imageLoader.setPath( path ); + this.textureLoader = new ImageBitmapLoader( manager ); + this.textureLoader.setOptions( { imageOrientation: 'none' } ); + this.textureLoader.setPath( path ); + this.textureCache = new Map(); + const bottomLeftUvSpaceHelpers = getBottomLeftUvSpaceHelpers( this.uvSpace ); + + this.compileContext = { + compileRegistry: COMPILE_REGISTRY, + nodeLibrary: MtlXLibrary, + ...bottomLeftUvSpaceHelpers, + mxTransformUv: mx_transform_uv, + mxHextileCoord, + mxHextileComputeBlendWeights, + invertConstantMatrixValues, + IDENTITY_MAT3_VALUES, + IDENTITY_MAT4_VALUES, + }; + + } + + resolveTextureURI( uri ) { + + if ( this.archiveResolver ) { + + const archiveURI = this.archiveResolver( uri ); + if ( archiveURI ) return archiveURI; + + } + + return uri; + + } + + addMaterialXNode( materialXNode ) { + + this.nodesXLib.set( materialXNode.nodePath, materialXNode ); + + } + + getMaterialXNode( ...names ) { + + return this.nodesXLib.get( names.join( '/' ) ); + + } + + parseNode( nodeXML, nodePath = '' ) { + + return parseMaterialXNodeTree( + nodeXML, + ( childNodeXML, childNodePath ) => new MaterialXNode( this, childNodeXML, childNodePath ), + ( materialXNode ) => this.addMaterialXNode( materialXNode ), + nodePath, + ); + + } + + parse( text, materialName = null, options = {} ) { + + const rootNode = parseMaterialXText( + text, + ( childNodeXML, childNodePath ) => new MaterialXNode( this, childNodeXML, childNodePath ), + ( materialXNode ) => this.addMaterialXNode( materialXNode ), + ); + + if ( options.interfaceValidator ) { + + options.interfaceValidator( rootNode, this.log ); + + } + + const materials = rootNode.toMaterials( materialName ); + return { + materials, + log: this.log.entries, + errors: this.log.errors, + warnings: this.log.warnings, + }; + + } + +} + +export { MaterialXDocument }; diff --git a/examples/jsm/loaders/materialx/MaterialXHextile.js b/examples/jsm/loaders/materialx/MaterialXHextile.js new file mode 100644 index 00000000000000..97a880c7f17e38 --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXHextile.js @@ -0,0 +1,183 @@ +import { + abs, + add, + clamp, + cos, + dFdx, + dFdy, + div, + dot, + element, + floor, + fract, + max, + mix, + mul, + pow, + sin, + step, + sub, + vec2, + vec3, +} from 'three/tsl'; + +const HEXTILE_SQRT3_2 = Math.sqrt( 3 ) * 2; +const HEXTILE_EPSILON = 1e-6; +const HEXTILE_PI_OVER_180 = Math.PI / 180; + +function toRadians( degrees ) { + + return mul( degrees, HEXTILE_PI_OVER_180 ); + +} + +function mxHextileHash( point ) { + + const x = element( point, 0 ); + const y = element( point, 1 ); + const p3Base = vec3( x, y, x ); + const p3Scaled = mul( p3Base, vec3( 0.1031, 0.103, 0.0973 ) ); + const p3Fract = fract( p3Scaled ); + const p3YZX = vec3( element( p3Fract, 1 ), element( p3Fract, 2 ), element( p3Fract, 0 ) ); + const p3Offset = add( p3YZX, 33.33 ); + const p3 = add( p3Fract, dot( p3Fract, p3Offset ) ); + const lhs = add( vec2( element( p3, 0 ), element( p3, 0 ) ), vec2( element( p3, 1 ), element( p3, 2 ) ) ); + const rhs = vec2( element( p3, 2 ), element( p3, 1 ) ); + return fract( mul( lhs, rhs ) ); + +} + +function mxSchlickGain( x, r ) { + + const rr = clamp( r, 0.001, 0.999 ); + const a = mul( sub( div( 1, rr ), 2 ), sub( 1, mul( 2, x ) ) ); + const low = div( x, add( a, 1 ) ); + const high = div( sub( a, x ), sub( a, 1 ) ); + return mix( low, high, step( 0.5, x ) ); + +} + +function normalizeBlendWeights( weights ) { + + const wx = element( weights, 0 ); + const wy = element( weights, 1 ); + const wz = element( weights, 2 ); + const sum = add( add( wx, wy ), wz ); + return div( weights, sum ); + +} + +function mxRotate2d( point, sine, cosine ) { + + return vec2( sub( mul( cosine, element( point, 0 ) ), mul( sine, element( point, 1 ) ) ), add( mul( sine, element( point, 0 ) ), mul( cosine, element( point, 1 ) ) ) ); + +} + +function toTileCenter( tileId ) { + + const scaled = div( tileId, HEXTILE_SQRT3_2 ); + const sx = element( scaled, 0 ); + const sy = element( scaled, 1 ); + return vec2( add( sx, mul( 0.5, sy ) ), mul( 0.8660254, sy ) ); + +} + +export function mxHextileComputeBlendWeights( luminanceWeights, tileWeights, falloff ) { + + const weighted = mul( luminanceWeights, pow( tileWeights, vec3( 7, 7, 7 ) ) ); + const normalized = normalizeBlendWeights( weighted ); + const gained = vec3( + mxSchlickGain( element( normalized, 0 ), falloff ), + mxSchlickGain( element( normalized, 1 ), falloff ), + mxSchlickGain( element( normalized, 2 ), falloff ), + ); + const gainedNormalized = normalizeBlendWeights( gained ); + const applyFalloff = step( HEXTILE_EPSILON, abs( sub( falloff, 0.5 ) ) ); + return mix( normalized, gainedNormalized, applyFalloff ); + +} + +export function mxHextileCoord( coord, rotation, rotationRange, scale, scaleRange, offset, offsetRange ) { + + const st = mul( coord, HEXTILE_SQRT3_2 ); + const stSkewed = vec2( add( element( st, 0 ), mul( - 0.57735027, element( st, 1 ) ) ), mul( 1.15470054, element( st, 1 ) ) ); + const stFrac = fract( stSkewed ); + const tx = element( stFrac, 0 ); + const ty = element( stFrac, 1 ); + const tz = sub( sub( 1, tx ), ty ); + const s = step( 0, sub( 0, tz ) ); + const s2 = sub( mul( 2, s ), 1 ); + const w1 = mul( sub( 0, tz ), s2 ); + const w2 = sub( s, mul( ty, s2 ) ); + const w3 = sub( s, mul( tx, s2 ) ); + const baseId = floor( stSkewed ); + const oneMinusS = sub( 1, s ); + const id1 = add( baseId, vec2( s, s ) ); + const id2 = add( baseId, vec2( s, oneMinusS ) ); + const id3 = add( baseId, vec2( oneMinusS, s ) ); + + const ctr1 = toTileCenter( id1 ); + const ctr2 = toTileCenter( id2 ); + const ctr3 = toTileCenter( id3 ); + + const seedOffset = vec2( 0.12345, 0.12345 ); + const rand1 = mxHextileHash( add( id1, seedOffset ) ); + const rand2 = mxHextileHash( add( id2, seedOffset ) ); + const rand3 = mxHextileHash( add( id3, seedOffset ) ); + + const rr = vec2( toRadians( element( rotationRange, 0 ) ), toRadians( element( rotationRange, 1 ) ) ); + const rrMin = element( rr, 0 ); + const rrMax = element( rr, 1 ); + const randX = vec3( element( rand1, 0 ), element( rand2, 0 ), element( rand3, 0 ) ); + const rotations = mix( vec3( rrMin, rrMin, rrMin ), vec3( rrMax, rrMax, rrMax ), mul( randX, rotation ) ); + const randY = vec3( element( rand1, 1 ), element( rand2, 1 ), element( rand3, 1 ) ); + const scaleMin = element( scaleRange, 0 ); + const scaleMax = element( scaleRange, 1 ); + const randomScale = mix( vec3( scaleMin, scaleMin, scaleMin ), vec3( scaleMax, scaleMax, scaleMax ), randY ); + const scales = mix( vec3( 1, 1, 1 ), randomScale, scale ); + const offsetMin = element( offsetRange, 0 ); + const offsetMax = element( offsetRange, 1 ); + const offset1 = mix( vec2( offsetMin, offsetMin ), vec2( offsetMax, offsetMax ), mul( rand1, offset ) ); + const offset2 = mix( vec2( offsetMin, offsetMin ), vec2( offsetMax, offsetMax ), mul( rand2, offset ) ); + const offset3 = mix( vec2( offsetMin, offsetMin ), vec2( offsetMax, offsetMax ), mul( rand3, offset ) ); + + const sampleCoord = ( center, randomOffset, rotationValue, sampleScale ) => { + + const delta = sub( coord, center ); + const rotated = mxRotate2d( delta, sin( rotationValue ), cos( rotationValue ) ); + const safeScale = max( sampleScale, HEXTILE_EPSILON ); + return add( add( div( rotated, vec2( safeScale, safeScale ) ), center ), randomOffset ); + + }; + + const sampleDerivative = ( derivative, rotationValue, sampleScale ) => { + + const rotated = mxRotate2d( derivative, sin( rotationValue ), cos( rotationValue ) ); + const safeScale = max( sampleScale, HEXTILE_EPSILON ); + return div( rotated, vec2( safeScale, safeScale ) ); + + }; + + const ddx = dFdx( coord ); + const ddy = dFdy( coord ); + + return { + coords: [ + sampleCoord( ctr1, offset1, element( rotations, 0 ), element( scales, 0 ) ), + sampleCoord( ctr2, offset2, element( rotations, 1 ), element( scales, 1 ) ), + sampleCoord( ctr3, offset3, element( rotations, 2 ), element( scales, 2 ) ), + ], + ddx: [ + sampleDerivative( ddx, element( rotations, 0 ), element( scales, 0 ) ), + sampleDerivative( ddx, element( rotations, 1 ), element( scales, 1 ) ), + sampleDerivative( ddx, element( rotations, 2 ), element( scales, 2 ) ), + ], + ddy: [ + sampleDerivative( ddy, element( rotations, 0 ), element( scales, 0 ) ), + sampleDerivative( ddy, element( rotations, 1 ), element( scales, 1 ) ), + sampleDerivative( ddy, element( rotations, 2 ), element( scales, 2 ) ), + ], + weights: vec3( w1, w2, w3 ), + }; + +} diff --git a/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js b/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js new file mode 100644 index 00000000000000..4a75e62cdd338b --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXInterfaceValidation.js @@ -0,0 +1,376 @@ +import { MtlXLibrary } from './MaterialXNodeLibrary.js'; +import { MaterialXLogCodes } from './MaterialXLog.js'; +import registryData from './MaterialXNodeInterfaceRegistry.js'; + +const SKIP_ELEMENTS = new Set( [ 'materialx', 'input', 'output' ] ); +const CONTAINER_ELEMENTS = new Set( [ 'nodegraph' ] ); + +const LIBRARY_FALLBACK_OUTPUT = 'out'; + +function formatInputElement( inputNodeX ) { + + const attrs = []; + for ( const name of [ 'name', 'type', 'nodename', 'nodegraph', 'interfacename', 'output', 'value' ] ) { + + const value = inputNodeX.getAttribute( name ); + if ( value !== null && value !== '' ) { + + attrs.push( `${name}="${value}"` ); + + } + + } + + return ``; + +} + +function formatNodeElement( nodeX ) { + + const attrs = []; + for ( const name of [ 'name', 'type', 'nodedef' ] ) { + + const value = nodeX.getAttribute( name ); + if ( value !== null && value !== '' ) { + + attrs.push( `${name}="${value}"` ); + + } + + } + + return `<${nodeX.element} ${attrs.join( ' ' )}>`; + +} + +function scoreNodedefCandidate( candidateName, nodeX ) { + + const candidate = registryData.resolved[ candidateName ]; + if ( ! candidate ) return - 1; + + let score = 0; + const nodeType = nodeX.type; + const outputType = candidate.outputs.out || Object.values( candidate.outputs )[ 0 ]; + if ( nodeType && outputType === nodeType ) { + + score += 4; + + } + + for ( const child of nodeX.children ) { + + if ( child.element !== 'input' ) continue; + const expectedType = candidate.inputs[ child.name ]; + if ( ! expectedType || ! child.type ) continue; + if ( expectedType === child.type ) { + + score += 3; + + } else if ( typesCompatible( expectedType, child.type ) ) { + + score += 1; + + } else { + + score -= 2; + + } + + } + + return score; + +} + +function resolveInterface( nodeX ) { + + const nodedefName = nodeX.getAttribute( 'nodedef' ); + if ( nodedefName && registryData.resolved[ nodedefName ] ) { + + return { source: 'nodedef', name: nodedefName, ...registryData.resolved[ nodedefName ] }; + + } + + const candidates = registryData.byNode[ nodeX.element ] || []; + if ( candidates.length > 0 ) { + + let selected = candidates[ 0 ]; + let bestScore = - Infinity; + + for ( const candidateName of candidates ) { + + const score = scoreNodedefCandidate( candidateName, nodeX ); + if ( score > bestScore ) { + + bestScore = score; + selected = candidateName; + + } + + } + + const resolved = registryData.resolved[ selected ]; + if ( resolved ) { + + return { source: 'nodedef', name: selected, ...resolved }; + + } + + } + + const libraryEntry = MtlXLibrary[ nodeX.element ]; + if ( libraryEntry ) { + + const inputs = Object.fromEntries( libraryEntry.params.map( ( param ) => [ param, null ] ) ); + const outputs = nodeX.type ? { [ LIBRARY_FALLBACK_OUTPUT ]: nodeX.type } : {}; + return { source: 'library', name: nodeX.element, node: nodeX.element, inputs, outputs }; + + } + + return null; + +} + +function resolveReferencedNode( inputNodeX ) { + + const materialX = inputNodeX.materialX; + const referencePath = inputNodeX.referencePath; + if ( ! referencePath ) return null; + + return materialX.getMaterialXNode( referencePath ) || null; + +} + +function resolveSourceOutputType( sourceNodeX, outputName ) { + + if ( sourceNodeX.element === 'output' ) { + + return { + interface: null, + outputType: sourceNodeX.type, + outputName: sourceNodeX.name || 'out', + }; + + } + + const sourceInterface = resolveInterface( sourceNodeX ); + if ( ! sourceInterface ) return { interface: null, outputType: null, outputName }; + + if ( outputName ) { + + if ( sourceInterface.outputs[ outputName ] ) { + + return { + interface: sourceInterface, + outputType: sourceInterface.outputs[ outputName ], + outputName, + }; + + } + + return { + interface: sourceInterface, + outputType: null, + outputName, + }; + + } + + if ( sourceNodeX.type && sourceNodeX.type !== 'multioutput' ) { + + return { + interface: sourceInterface, + outputType: sourceNodeX.type, + outputName: 'out', + }; + + } + + if ( sourceInterface.outputs.out ) { + + return { + interface: sourceInterface, + outputType: sourceInterface.outputs.out, + outputName: 'out', + }; + + } + + const declaredOutputs = Object.entries( sourceInterface.outputs ); + if ( declaredOutputs.length === 1 ) { + + const [ singleName, singleType ] = declaredOutputs[ 0 ]; + return { + interface: sourceInterface, + outputType: singleType, + outputName: singleName, + }; + + } + + if ( sourceNodeX.type ) { + + return { + interface: sourceInterface, + outputType: sourceNodeX.type, + outputName: null, + }; + + } + + return { interface: sourceInterface, outputType: null, outputName: null }; + +} + +function typesCompatible( expectedType, actualType ) { + + if ( ! expectedType || ! actualType ) return true; + if ( expectedType === actualType ) return true; + if ( ( expectedType === 'float' && actualType === 'integer' ) || ( expectedType === 'integer' && actualType === 'float' ) ) { + + return true; + + } + + return false; + +} + +function validatePortConnection( inputNodeX, parentNodeX, log ) { + + const sourceNodeX = resolveReferencedNode( inputNodeX ); + if ( ! sourceNodeX ) return; + + const { outputType } = resolveSourceOutputType( sourceNodeX, inputNodeX.output ); + const inputSnippet = formatInputElement( inputNodeX ); + + if ( inputNodeX.output && outputType === null ) { + + log.add( + MaterialXLogCodes.INVALID_OUTPUT_CONNECTION, + `No output found for port connection: ${inputSnippet}`, + parentNodeX.name, + ); + return; + + } + + const inputType = inputNodeX.type; + if ( inputType && outputType && typesCompatible( inputType, outputType ) === false ) { + + log.add( + MaterialXLogCodes.TYPE_MISMATCH, + `Mismatched types in port connection: ${inputSnippet}`, + parentNodeX.name, + ); + + } + +} + +function validateNodeInputs( nodeX, log ) { + + if ( nodeX.element === 'materialx' ) { + + for ( const child of nodeX.children ) { + + validateNodeInputs( child, log ); + + } + + return; + + } + + if ( SKIP_ELEMENTS.has( nodeX.element ) ) return; + if ( CONTAINER_ELEMENTS.has( nodeX.element ) ) { + + for ( const child of nodeX.children ) { + + validateNodeInputs( child, log ); + + } + + return; + + } + + const nodeInterface = resolveInterface( nodeX ); + if ( nodeInterface ) { + + for ( const child of nodeX.children ) { + + if ( child.element !== 'input' ) continue; + + const inputName = child.name; + if ( ! inputName ) continue; + + if ( nodeInterface.inputs[ inputName ] === undefined ) { + + log.add( + MaterialXLogCodes.UNKNOWN_INPUT, + `Node interface error: Input '${inputName}' doesn't match declaration: ${formatNodeElement( nodeX )}`, + nodeX.name, + ); + + } else if ( + child.type && + nodeInterface.inputs[ inputName ] && + child.hasReference === false && + typesCompatible( nodeInterface.inputs[ inputName ], child.type ) === false + ) { + + log.add( + MaterialXLogCodes.TYPE_MISMATCH, + `Input '${inputName}' type '${child.type}' doesn't match nodedef type '${nodeInterface.inputs[ inputName ]}' on ${formatNodeElement( nodeX )}`, + nodeX.name, + ); + + } + + if ( child.hasReference ) { + + validatePortConnection( child, nodeX, log ); + + } + + } + + } else if ( MtlXLibrary[ nodeX.element ] === undefined && nodeX.element !== 'surfacematerial' ) { + + // Defer unsupported-node warnings to compile-time behavior. + for ( const child of nodeX.children ) { + + if ( child.element === 'input' && child.hasReference ) { + + validatePortConnection( child, nodeX, log ); + + } + + } + + } + + for ( const child of nodeX.children ) { + + if ( child.element !== 'input' && child.element !== 'output' ) { + + validateNodeInputs( child, log ); + + } + + } + +} + +function createStrictInterfaceValidator() { + + return function validateMaterialXInterfaces( rootNode, log ) { + + validateNodeInputs( rootNode, log ); + + }; + +} + +export { createStrictInterfaceValidator }; diff --git a/examples/jsm/loaders/materialx/MaterialXLog.js b/examples/jsm/loaders/materialx/MaterialXLog.js new file mode 100644 index 00000000000000..db21324ab584ac --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXLog.js @@ -0,0 +1,75 @@ +const MaterialXLogCodes = { + UNSUPPORTED_NODE: { + label: 'unsupported-node', + severity: 'error', + }, + IGNORED_SURFACE_INPUT: { + label: 'ignored-surface-input', + severity: 'warning', + }, + MISSING_REFERENCE: { + label: 'missing-reference', + severity: 'error', + }, + MISSING_MATERIAL: { + label: 'missing-material', + severity: 'error', + }, + INVALID_VALUE: { + label: 'invalid-value', + severity: 'error', + }, + UNKNOWN_INPUT: { + label: 'unknown-input', + severity: 'error', + }, + INVALID_OUTPUT_CONNECTION: { + label: 'invalid-output-connection', + severity: 'error', + }, + TYPE_MISMATCH: { + label: 'type-mismatch', + severity: 'error', + }, +}; + +class MaterialXLog { + + constructor() { + + this.entries = []; + + } + + get errors() { + + return this.entries.filter( ( entry ) => entry.severity === 'error' ); + + } + + get warnings() { + + return this.entries.filter( ( entry ) => entry.severity === 'warning' ); + + } + + add( code, message, nodeName ) { + + const entry = { + code: code.label, + severity: code.severity, + message, + }; + if ( nodeName !== undefined && nodeName !== null ) { + + entry.nodeName = nodeName; + + } + + this.entries.push( entry ); + + } + +} + +export { MaterialXLogCodes, MaterialXLog }; diff --git a/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js b/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js new file mode 100644 index 00000000000000..431ebe93dd5afb --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXNodeInterfaceRegistry.js @@ -0,0 +1,4 @@ +/* eslint-disable */ +const registryData = {"nodedefs":{"ND_oren_nayar_diffuse_bsdf":{"node":"oren_nayar_diffuse_bsdf","inherit":null,"inputs":{"weight":"float","color":"color3","roughness":"float","normal":"vector3","energy_compensation":"boolean"},"outputs":{"out":"BSDF"}},"ND_burley_diffuse_bsdf":{"node":"burley_diffuse_bsdf","inherit":null,"inputs":{"weight":"float","color":"color3","roughness":"float","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_translucent_bsdf":{"node":"translucent_bsdf","inherit":null,"inputs":{"weight":"float","color":"color3","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_dielectric_bsdf":{"node":"dielectric_bsdf","inherit":null,"inputs":{"weight":"float","tint":"color3","ior":"float","roughness":"vector2","retroreflective":"boolean","thinfilm_thickness":"float","thinfilm_ior":"float","normal":"vector3","tangent":"vector3","distribution":"string","scatter_mode":"string"},"outputs":{"out":"BSDF"}},"ND_conductor_bsdf":{"node":"conductor_bsdf","inherit":null,"inputs":{"weight":"float","ior":"color3","extinction":"color3","roughness":"vector2","retroreflective":"boolean","thinfilm_thickness":"float","thinfilm_ior":"float","normal":"vector3","tangent":"vector3","distribution":"string"},"outputs":{"out":"BSDF"}},"ND_generalized_schlick_bsdf":{"node":"generalized_schlick_bsdf","inherit":null,"inputs":{"weight":"float","color0":"color3","color82":"color3","color90":"color3","exponent":"float","roughness":"vector2","retroreflective":"boolean","thinfilm_thickness":"float","thinfilm_ior":"float","normal":"vector3","tangent":"vector3","distribution":"string","scatter_mode":"string"},"outputs":{"out":"BSDF"}},"ND_subsurface_bsdf":{"node":"subsurface_bsdf","inherit":null,"inputs":{"weight":"float","color":"color3","radius":"color3","anisotropy":"float","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_sheen_bsdf":{"node":"sheen_bsdf","inherit":null,"inputs":{"weight":"float","color":"color3","roughness":"float","normal":"vector3","mode":"string"},"outputs":{"out":"BSDF"}},"ND_chiang_hair_bsdf":{"node":"chiang_hair_bsdf","inherit":null,"inputs":{"tint_R":"color3","tint_TT":"color3","tint_TRT":"color3","ior":"float","roughness_R":"vector2","roughness_TT":"vector2","roughness_TRT":"vector2","cuticle_angle":"float","absorption_coefficient":"vector3","normal":"vector3","curve_direction":"vector3"},"outputs":{"out":"BSDF"}},"ND_uniform_edf":{"node":"uniform_edf","inherit":null,"inputs":{"color":"color3"},"outputs":{"out":"EDF"}},"ND_conical_edf":{"node":"conical_edf","inherit":null,"inputs":{"color":"color3","normal":"vector3","inner_angle":"float","outer_angle":"float"},"outputs":{"out":"EDF"}},"ND_measured_edf":{"node":"measured_edf","inherit":null,"inputs":{"color":"color3","normal":"vector3","file":"filename"},"outputs":{"out":"EDF"}},"ND_generalized_schlick_edf":{"node":"generalized_schlick_edf","inherit":null,"inputs":{"color0":"color3","color90":"color3","exponent":"float","base":"EDF"},"outputs":{"out":"EDF"}},"ND_absorption_vdf":{"node":"absorption_vdf","inherit":null,"inputs":{"absorption":"vector3"},"outputs":{"out":"VDF"}},"ND_anisotropic_vdf":{"node":"anisotropic_vdf","inherit":null,"inputs":{"absorption":"vector3","scattering":"vector3","anisotropy":"float"},"outputs":{"out":"VDF"}},"ND_surface":{"node":"surface","inherit":null,"inputs":{"bsdf":"BSDF","edf":"EDF","opacity":"float","thin_walled":"boolean"},"outputs":{"out":"surfaceshader"}},"ND_volume":{"node":"volume","inherit":null,"inputs":{"vdf":"VDF","edf":"EDF"},"outputs":{"out":"volumeshader"}},"ND_light":{"node":"light","inherit":null,"inputs":{"edf":"EDF","intensity":"float","exposure":"float"},"outputs":{"out":"lightshader"}},"ND_displacement_float":{"node":"displacement","inherit":null,"inputs":{"displacement":"float","scale":"float"},"outputs":{"out":"displacementshader"}},"ND_displacement_vector3":{"node":"displacement","inherit":null,"inputs":{"displacement":"vector3","scale":"float"},"outputs":{"out":"displacementshader"}},"ND_layer_bsdf":{"node":"layer","inherit":null,"inputs":{"top":"BSDF","base":"BSDF"},"outputs":{"out":"BSDF"}},"ND_layer_vdf":{"node":"layer","inherit":null,"inputs":{"top":"BSDF","base":"VDF"},"outputs":{"out":"BSDF"}},"ND_mix_bsdf":{"node":"mix","inherit":null,"inputs":{"fg":"BSDF","bg":"BSDF","mix":"float"},"outputs":{"out":"BSDF"}},"ND_mix_edf":{"node":"mix","inherit":null,"inputs":{"fg":"EDF","bg":"EDF","mix":"float"},"outputs":{"out":"EDF"}},"ND_mix_vdf":{"node":"mix","inherit":null,"inputs":{"fg":"VDF","bg":"VDF","mix":"float"},"outputs":{"out":"VDF"}},"ND_add_bsdf":{"node":"add","inherit":null,"inputs":{"in1":"BSDF","in2":"BSDF"},"outputs":{"out":"BSDF"}},"ND_add_edf":{"node":"add","inherit":null,"inputs":{"in1":"EDF","in2":"EDF"},"outputs":{"out":"EDF"}},"ND_add_vdf":{"node":"add","inherit":null,"inputs":{"in1":"VDF","in2":"VDF"},"outputs":{"out":"VDF"}},"ND_multiply_bsdfC":{"node":"multiply","inherit":null,"inputs":{"in1":"BSDF","in2":"color3"},"outputs":{"out":"BSDF"}},"ND_multiply_bsdfF":{"node":"multiply","inherit":null,"inputs":{"in1":"BSDF","in2":"float"},"outputs":{"out":"BSDF"}},"ND_multiply_edfC":{"node":"multiply","inherit":null,"inputs":{"in1":"EDF","in2":"color3"},"outputs":{"out":"EDF"}},"ND_multiply_edfF":{"node":"multiply","inherit":null,"inputs":{"in1":"EDF","in2":"float"},"outputs":{"out":"EDF"}},"ND_multiply_vdfC":{"node":"multiply","inherit":null,"inputs":{"in1":"VDF","in2":"color3"},"outputs":{"out":"VDF"}},"ND_multiply_vdfF":{"node":"multiply","inherit":null,"inputs":{"in1":"VDF","in2":"float"},"outputs":{"out":"VDF"}},"ND_roughness_anisotropy":{"node":"roughness_anisotropy","inherit":null,"inputs":{"roughness":"float","anisotropy":"float"},"outputs":{"out":"vector2"}},"ND_roughness_dual":{"node":"roughness_dual","inherit":null,"inputs":{"roughness":"vector2"},"outputs":{"out":"vector2"}},"ND_glossiness_anisotropy":{"node":"glossiness_anisotropy","inherit":null,"inputs":{"glossiness":"float","anisotropy":"float"},"outputs":{"out":"vector2"}},"ND_blackbody":{"node":"blackbody","inherit":null,"inputs":{"temperature":"float"},"outputs":{"out":"color3"}},"ND_artistic_ior":{"node":"artistic_ior","inherit":null,"inputs":{"reflectivity":"color3","edge_color":"color3"},"outputs":{"ior":"color3","extinction":"color3"}},"ND_deon_hair_absorption_from_melanin":{"node":"deon_hair_absorption_from_melanin","inherit":null,"inputs":{"melanin_concentration":"float","melanin_redness":"float","eumelanin_color":"color3","pheomelanin_color":"color3"},"outputs":{"absorption":"vector3"}},"ND_chiang_hair_absorption_from_color":{"node":"chiang_hair_absorption_from_color","inherit":null,"inputs":{"color":"color3","azimuthal_roughness":"float"},"outputs":{"absorption":"vector3"}},"ND_chiang_hair_roughness":{"node":"chiang_hair_roughness","inherit":null,"inputs":{"longitudinal":"float","azimuthal":"float","scale_TT":"float","scale_TRT":"float"},"outputs":{"roughness_R":"vector2","roughness_TT":"vector2","roughness_TRT":"vector2"}},"ND_disney_principled":{"node":"disney_principled","inherit":null,"inputs":{"baseColor":"color3","metallic":"float","roughness":"float","anisotropic":"float","specular":"float","specularTint":"float","sheen":"float","sheenTint":"float","clearcoat":"float","clearcoatGloss":"float","specTrans":"float","ior":"float","subsurface":"float","subsurfaceDistance":"color3"},"outputs":{"out":"surfaceshader"}},"ND_open_pbr_surface_surfaceshader":{"node":"open_pbr_surface","inherit":null,"inputs":{"base_weight":"float","base_color":"color3","base_diffuse_roughness":"float","base_metalness":"float","specular_weight":"float","specular_color":"color3","specular_roughness":"float","specular_ior":"float","specular_roughness_anisotropy":"float","transmission_weight":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion_scale":"float","transmission_dispersion_abbe_number":"float","subsurface_weight":"float","subsurface_color":"color3","subsurface_radius":"float","subsurface_radius_scale":"color3","subsurface_scatter_anisotropy":"float","fuzz_weight":"float","fuzz_color":"color3","fuzz_roughness":"float","coat_weight":"float","coat_color":"color3","coat_roughness":"float","coat_roughness_anisotropy":"float","coat_ior":"float","coat_darkening":"float","thin_film_weight":"float","thin_film_thickness":"float","thin_film_ior":"float","emission_luminance":"float","emission_color":"color3","geometry_opacity":"float","geometry_thin_walled":"boolean","geometry_normal":"vector3","geometry_coat_normal":"vector3","geometry_tangent":"vector3","geometry_coat_tangent":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_open_pbr_anisotropy":{"node":"open_pbr_anisotropy","inherit":null,"inputs":{"roughness":"float","anisotropy":"float"},"outputs":{"out":"vector2"}},"ND_UsdPreviewSurface_surfaceshader":{"node":"UsdPreviewSurface","inherit":null,"inputs":{"diffuseColor":"color3","emissiveColor":"color3","useSpecularWorkflow":"integer","specularColor":"color3","metallic":"float","roughness":"float","clearcoat":"float","clearcoatRoughness":"float","opacity":"float","opacityMode":"integer","opacityThreshold":"float","ior":"float","normal":"vector3","displacement":"float","occlusion":"float"},"outputs":{"out":"surfaceshader"}},"ND_UsdUVTexture":{"node":"UsdUVTexture","inherit":"ND_UsdUVTexture_23","inputs":{},"outputs":{"r":"float","g":"float","b":"float","a":"float","rgb":"color3","rgba":"color4"}},"ND_UsdUVTexture_23":{"node":"UsdUVTexture","inherit":null,"inputs":{"file":"filename","st":"vector2","wrapS":"string","wrapT":"string","fallback":"color4","scale":"color4","bias":"color4"},"outputs":{"r":"float","g":"float","b":"float","a":"float","rgb":"color3"}},"ND_UsdPrimvarReader_integer":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"integer"},"outputs":{"out":"integer"}},"ND_UsdPrimvarReader_boolean":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"boolean"},"outputs":{"out":"boolean"}},"ND_UsdPrimvarReader_string":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"string"},"outputs":{"out":"string"}},"ND_UsdPrimvarReader_filename":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"filename"},"outputs":{"out":"filename"}},"ND_UsdPrimvarReader_float":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"float"},"outputs":{"out":"float"}},"ND_UsdPrimvarReader_vector2":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"vector2"},"outputs":{"out":"vector2"}},"ND_UsdPrimvarReader_vector3":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"vector3"},"outputs":{"out":"vector3"}},"ND_UsdPrimvarReader_vector4":{"node":"UsdPrimvarReader","inherit":null,"inputs":{"varname":"string","fallback":"vector4"},"outputs":{"out":"vector4"}},"ND_UsdTransform2d":{"node":"UsdTransform2d","inherit":null,"inputs":{"in":"vector2","rotation":"float","scale":"vector2","translation":"vector2"},"outputs":{"out":"vector2"}},"ND_standard_surface_surfaceshader":{"node":"standard_surface","inherit":"ND_standard_surface_surfaceshader_100","inputs":{"base":"float","base_color":"color3"},"outputs":{}},"ND_standard_surface_surfaceshader_100":{"node":"standard_surface","inherit":null,"inputs":{"base":"float","base_color":"color3","diffuse_roughness":"float","metalness":"float","specular":"float","specular_color":"color3","specular_roughness":"float","specular_IOR":"float","specular_anisotropy":"float","specular_rotation":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion":"float","transmission_extra_roughness":"float","subsurface":"float","subsurface_color":"color3","subsurface_radius":"color3","subsurface_scale":"float","subsurface_anisotropy":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","coat_anisotropy":"float","coat_rotation":"float","coat_IOR":"float","coat_normal":"vector3","coat_affect_color":"float","coat_affect_roughness":"float","thin_film_thickness":"float","thin_film_IOR":"float","emission":"float","emission_color":"color3","opacity":"color3","thin_walled":"boolean","normal":"vector3","tangent":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_gltf_pbr_surfaceshader":{"node":"gltf_pbr","inherit":null,"inputs":{"base_color":"color3","metallic":"float","roughness":"float","normal":"vector3","tangent":"vector3","occlusion":"float","transmission":"float","specular":"float","specular_color":"color3","ior":"float","alpha":"float","alpha_mode":"integer","alpha_cutoff":"float","iridescence":"float","iridescence_ior":"float","iridescence_thickness":"float","sheen_color":"color3","sheen_roughness":"float","clearcoat":"float","clearcoat_roughness":"float","clearcoat_normal":"vector3","emissive":"color3","emissive_strength":"float","thickness":"float","attenuation_distance":"float","attenuation_color":"color3","anisotropy_strength":"float","anisotropy_rotation":"float","dispersion":"float"},"outputs":{"out":"surfaceshader"}},"ND_gltf_colorimage":{"node":"gltf_colorimage","inherit":null,"inputs":{"file":"filename","default":"color4","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string","color":"color4","geomcolor":"color4"},"outputs":{"outcolor":"color3","outa":"float"}},"ND_gltf_image_color3_color3_1_0":{"node":"gltf_image","inherit":null,"inputs":{"file":"filename","factor":"color3","default":"color3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"color3"}},"ND_gltf_image_color4_color4_1_0":{"node":"gltf_image","inherit":null,"inputs":{"file":"filename","factor":"color4","default":"color4","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"color4"}},"ND_gltf_image_float_float_1_0":{"node":"gltf_image","inherit":null,"inputs":{"file":"filename","factor":"float","default":"float","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"float"}},"ND_gltf_image_vector3_vector3_1_0":{"node":"gltf_image","inherit":null,"inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"vector3"}},"ND_gltf_normalmap_vector3_1_0":{"node":"gltf_normalmap","inherit":null,"inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"vector3"}},"ND_gltf_iridescence_thickness_float_1_0":{"node":"gltf_iridescence_thickness","inherit":null,"inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","thicknessMin":"float","thicknessMax":"float"},"outputs":{"out":"float"}},"ND_gltf_anisotropy_image":{"node":"gltf_anisotropy_image","inherit":null,"inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string","anisotropy_strength":"float","anisotropy_rotation":"float"},"outputs":{"anisotropy_strength_out":"float","anisotropy_rotation_out":"float"}},"ND_viewdirection_vector3":{"node":"viewdirection","inherit":null,"inputs":{"space":"string"},"outputs":{"out":"vector3"}},"ND_facingratio_float":{"node":"facingratio","inherit":null,"inputs":{"viewdirection":"vector3","normal":"vector3","faceforward":"boolean","invert":"boolean"},"outputs":{"out":"float"}},"ND_gooch_shade":{"node":"gooch_shade","inherit":null,"inputs":{"warm_color":"color3","cool_color":"color3","specular_intensity":"float","shininess":"float","light_direction":"vector3"},"outputs":{"out":"color3"}},"ND_g18_rec709_to_lin_rec709_color3":{"node":"g18_rec709_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_g18_rec709_to_lin_rec709_color4":{"node":"g18_rec709_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_g22_rec709_to_lin_rec709_color3":{"node":"g22_rec709_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_g22_rec709_to_lin_rec709_color4":{"node":"g22_rec709_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_rec709_display_to_lin_rec709_color3":{"node":"rec709_display_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_rec709_display_to_lin_rec709_color4":{"node":"rec709_display_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_acescg_to_lin_rec709_color3":{"node":"acescg_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_acescg_to_lin_rec709_color4":{"node":"acescg_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_g22_ap1_to_lin_rec709_color3":{"node":"g22_ap1_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_g22_ap1_to_lin_rec709_color4":{"node":"g22_ap1_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_srgb_texture_to_lin_rec709_color3":{"node":"srgb_texture_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_srgb_texture_to_lin_rec709_color4":{"node":"srgb_texture_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_lin_adobergb_to_lin_rec709_color3":{"node":"lin_adobergb_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_lin_adobergb_to_lin_rec709_color4":{"node":"lin_adobergb_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_adobergb_to_lin_rec709_color3":{"node":"adobergb_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_adobergb_to_lin_rec709_color4":{"node":"adobergb_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_srgb_displayp3_to_lin_rec709_color3":{"node":"srgb_displayp3_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_srgb_displayp3_to_lin_rec709_color4":{"node":"srgb_displayp3_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_lin_displayp3_to_lin_rec709_color3":{"node":"lin_displayp3_to_lin_rec709","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_lin_displayp3_to_lin_rec709_color4":{"node":"lin_displayp3_to_lin_rec709","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_surfacematerial":{"node":"surfacematerial","inherit":null,"inputs":{"surfaceshader":"surfaceshader","backsurfaceshader":"surfaceshader","displacementshader":"displacementshader"},"outputs":{"out":"material"}},"ND_volumematerial":{"node":"volumematerial","inherit":null,"inputs":{"volumeshader":"volumeshader"},"outputs":{"out":"material"}},"ND_surface_unlit":{"node":"surface_unlit","inherit":null,"inputs":{"emission":"float","emission_color":"color3","transmission":"float","transmission_color":"color3","opacity":"float"},"outputs":{"out":"surfaceshader"}},"ND_image_float":{"node":"image","inherit":null,"inputs":{"file":"filename","layer":"string","default":"float","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"float"}},"ND_image_color3":{"node":"image","inherit":null,"inputs":{"file":"filename","layer":"string","default":"color3","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color3"}},"ND_image_color4":{"node":"image","inherit":null,"inputs":{"file":"filename","layer":"string","default":"color4","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color4"}},"ND_image_vector2":{"node":"image","inherit":null,"inputs":{"file":"filename","layer":"string","default":"vector2","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector2"}},"ND_image_vector3":{"node":"image","inherit":null,"inputs":{"file":"filename","layer":"string","default":"vector3","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector3"}},"ND_image_vector4":{"node":"image","inherit":null,"inputs":{"file":"filename","layer":"string","default":"vector4","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector4"}},"ND_tiledimage_float":{"node":"tiledimage","inherit":null,"inputs":{"file":"filename","default":"float","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"float"}},"ND_tiledimage_color3":{"node":"tiledimage","inherit":null,"inputs":{"file":"filename","default":"color3","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color3"}},"ND_tiledimage_color4":{"node":"tiledimage","inherit":null,"inputs":{"file":"filename","default":"color4","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color4"}},"ND_tiledimage_vector2":{"node":"tiledimage","inherit":null,"inputs":{"file":"filename","default":"vector2","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector2"}},"ND_tiledimage_vector3":{"node":"tiledimage","inherit":null,"inputs":{"file":"filename","default":"vector3","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector3"}},"ND_tiledimage_vector4":{"node":"tiledimage","inherit":null,"inputs":{"file":"filename","default":"vector4","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector4"}},"ND_latlongimage":{"node":"latlongimage","inherit":null,"inputs":{"file":"filename","default":"color3","viewdir":"vector3","rotation":"float"},"outputs":{"out":"color3"}},"ND_hextiledimage_color3":{"node":"hextiledimage","inherit":null,"inputs":{"file":"filename","default":"color3","texcoord":"vector2","tiling":"vector2","rotation":"float","rotationrange":"vector2","scale":"float","scalerange":"vector2","offset":"float","offsetrange":"vector2","falloff":"float","falloffcontrast":"float","lumacoeffs":"color3"},"outputs":{"out":"color3"}},"ND_hextiledimage_color4":{"node":"hextiledimage","inherit":null,"inputs":{"file":"filename","default":"color4","texcoord":"vector2","tiling":"vector2","rotation":"float","rotationrange":"vector2","scale":"float","scalerange":"vector2","offset":"float","offsetrange":"vector2","falloff":"float","falloffcontrast":"float","lumacoeffs":"color3"},"outputs":{"out":"color4"}},"ND_triplanarprojection_float":{"node":"triplanarprojection","inherit":null,"inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"float","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"float"}},"ND_triplanarprojection_color3":{"node":"triplanarprojection","inherit":null,"inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"color3","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color3"}},"ND_triplanarprojection_color4":{"node":"triplanarprojection","inherit":null,"inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"color4","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color4"}},"ND_triplanarprojection_vector2":{"node":"triplanarprojection","inherit":null,"inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"vector2","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector2"}},"ND_triplanarprojection_vector3":{"node":"triplanarprojection","inherit":null,"inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"vector3","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector3"}},"ND_triplanarprojection_vector4":{"node":"triplanarprojection","inherit":null,"inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"vector4","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector4"}},"ND_constant_float":{"node":"constant","inherit":null,"inputs":{"value":"float"},"outputs":{"out":"float"}},"ND_constant_color3":{"node":"constant","inherit":null,"inputs":{"value":"color3"},"outputs":{"out":"color3"}},"ND_constant_color4":{"node":"constant","inherit":null,"inputs":{"value":"color4"},"outputs":{"out":"color4"}},"ND_constant_vector2":{"node":"constant","inherit":null,"inputs":{"value":"vector2"},"outputs":{"out":"vector2"}},"ND_constant_vector3":{"node":"constant","inherit":null,"inputs":{"value":"vector3"},"outputs":{"out":"vector3"}},"ND_constant_vector4":{"node":"constant","inherit":null,"inputs":{"value":"vector4"},"outputs":{"out":"vector4"}},"ND_constant_boolean":{"node":"constant","inherit":null,"inputs":{"value":"boolean"},"outputs":{"out":"boolean"}},"ND_constant_integer":{"node":"constant","inherit":null,"inputs":{"value":"integer"},"outputs":{"out":"integer"}},"ND_constant_matrix33":{"node":"constant","inherit":null,"inputs":{"value":"matrix33"},"outputs":{"out":"matrix33"}},"ND_constant_matrix44":{"node":"constant","inherit":null,"inputs":{"value":"matrix44"},"outputs":{"out":"matrix44"}},"ND_constant_string":{"node":"constant","inherit":null,"inputs":{"value":"string"},"outputs":{"out":"string"}},"ND_constant_filename":{"node":"constant","inherit":null,"inputs":{"value":"filename"},"outputs":{"out":"filename"}},"ND_ramp":{"node":"ramp","inherit":null,"inputs":{"texcoord":"vector2","type":"integer","interpolation":"integer","num_intervals":"integer","interval1":"float","color1":"color4","interval2":"float","color2":"color4","interval3":"float","color3":"color4","interval4":"float","color4":"color4","interval5":"float","color5":"color4","interval6":"float","color6":"color4","interval7":"float","color7":"color4","interval8":"float","color8":"color4","interval9":"float","color9":"color4","interval10":"float","color10":"color4"},"outputs":{"out":"color4"}},"ND_ramp_gradient":{"node":"ramp_gradient","inherit":null,"inputs":{"x":"float","interval1":"float","interval2":"float","color1":"color4","color2":"color4","interpolation":"integer","prev_color":"color4","interval_num":"integer","num_intervals":"integer"},"outputs":{"out":"color4"}},"ND_ramplr_float":{"node":"ramplr","inherit":null,"inputs":{"valuel":"float","valuer":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_ramplr_color3":{"node":"ramplr","inherit":null,"inputs":{"valuel":"color3","valuer":"color3","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_ramplr_color4":{"node":"ramplr","inherit":null,"inputs":{"valuel":"color4","valuer":"color4","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_ramplr_vector2":{"node":"ramplr","inherit":null,"inputs":{"valuel":"vector2","valuer":"vector2","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_ramplr_vector3":{"node":"ramplr","inherit":null,"inputs":{"valuel":"vector3","valuer":"vector3","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_ramplr_vector4":{"node":"ramplr","inherit":null,"inputs":{"valuel":"vector4","valuer":"vector4","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_ramptb_float":{"node":"ramptb","inherit":null,"inputs":{"valuet":"float","valueb":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_ramptb_color3":{"node":"ramptb","inherit":null,"inputs":{"valuet":"color3","valueb":"color3","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_ramptb_color4":{"node":"ramptb","inherit":null,"inputs":{"valuet":"color4","valueb":"color4","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_ramptb_vector2":{"node":"ramptb","inherit":null,"inputs":{"valuet":"vector2","valueb":"vector2","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_ramptb_vector3":{"node":"ramptb","inherit":null,"inputs":{"valuet":"vector3","valueb":"vector3","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_ramptb_vector4":{"node":"ramptb","inherit":null,"inputs":{"valuet":"vector4","valueb":"vector4","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_ramp4_float":{"node":"ramp4","inherit":null,"inputs":{"valuetl":"float","valuetr":"float","valuebl":"float","valuebr":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_ramp4_color3":{"node":"ramp4","inherit":null,"inputs":{"valuetl":"color3","valuetr":"color3","valuebl":"color3","valuebr":"color3","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_ramp4_color4":{"node":"ramp4","inherit":null,"inputs":{"valuetl":"color4","valuetr":"color4","valuebl":"color4","valuebr":"color4","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_ramp4_vector2":{"node":"ramp4","inherit":null,"inputs":{"valuetl":"vector2","valuetr":"vector2","valuebl":"vector2","valuebr":"vector2","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_ramp4_vector3":{"node":"ramp4","inherit":null,"inputs":{"valuetl":"vector3","valuetr":"vector3","valuebl":"vector3","valuebr":"vector3","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_ramp4_vector4":{"node":"ramp4","inherit":null,"inputs":{"valuetl":"vector4","valuetr":"vector4","valuebl":"vector4","valuebr":"vector4","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_splitlr_float":{"node":"splitlr","inherit":null,"inputs":{"valuel":"float","valuer":"float","center":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_splitlr_color3":{"node":"splitlr","inherit":null,"inputs":{"valuel":"color3","valuer":"color3","center":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_splitlr_color4":{"node":"splitlr","inherit":null,"inputs":{"valuel":"color4","valuer":"color4","center":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_splitlr_vector2":{"node":"splitlr","inherit":null,"inputs":{"valuel":"vector2","valuer":"vector2","center":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_splitlr_vector3":{"node":"splitlr","inherit":null,"inputs":{"valuel":"vector3","valuer":"vector3","center":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_splitlr_vector4":{"node":"splitlr","inherit":null,"inputs":{"valuel":"vector4","valuer":"vector4","center":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_splittb_float":{"node":"splittb","inherit":null,"inputs":{"valuet":"float","valueb":"float","center":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_splittb_color3":{"node":"splittb","inherit":null,"inputs":{"valuet":"color3","valueb":"color3","center":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_splittb_color4":{"node":"splittb","inherit":null,"inputs":{"valuet":"color4","valueb":"color4","center":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_splittb_vector2":{"node":"splittb","inherit":null,"inputs":{"valuet":"vector2","valueb":"vector2","center":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_splittb_vector3":{"node":"splittb","inherit":null,"inputs":{"valuet":"vector3","valueb":"vector3","center":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_splittb_vector4":{"node":"splittb","inherit":null,"inputs":{"valuet":"vector4","valueb":"vector4","center":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_noise2d_float":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_noise2d_color3":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"vector3","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_noise2d_color4":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"vector4","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_noise2d_vector2":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"vector2","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_noise2d_vector3":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"vector3","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_noise2d_vector4":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"vector4","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_noise2d_color3FA":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_noise2d_color4FA":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_noise2d_vector2FA":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_noise2d_vector3FA":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_noise2d_vector4FA":{"node":"noise2d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_noise3d_float":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"float"}},"ND_noise3d_color3":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"vector3","pivot":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_noise3d_color4":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"vector4","pivot":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_noise3d_vector2":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"vector2","pivot":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_noise3d_vector3":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"vector3","pivot":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_noise3d_vector4":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"vector4","pivot":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_noise3d_color3FA":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_noise3d_color4FA":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_noise3d_vector2FA":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_noise3d_vector3FA":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_noise3d_vector4FA":{"node":"noise3d","inherit":null,"inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_fractal2d_float":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_fractal2d_color3":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_fractal2d_color4":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_fractal2d_vector2":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"vector2","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_fractal2d_vector3":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_fractal2d_vector4":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_fractal2d_color3FA":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_fractal2d_color4FA":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_fractal2d_vector2FA":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_fractal2d_vector3FA":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_fractal2d_vector4FA":{"node":"fractal2d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_fractal3d_float":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"float"}},"ND_fractal3d_color3":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_fractal3d_color4":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_fractal3d_vector2":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"vector2","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_fractal3d_vector3":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_fractal3d_vector4":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_fractal3d_color3FA":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_fractal3d_color4FA":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_fractal3d_vector2FA":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_fractal3d_vector3FA":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_fractal3d_vector4FA":{"node":"fractal3d","inherit":null,"inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_cellnoise2d_float":{"node":"cellnoise2d","inherit":null,"inputs":{"texcoord":"vector2"},"outputs":{"out":"float"}},"ND_cellnoise3d_float":{"node":"cellnoise3d","inherit":null,"inputs":{"position":"vector3"},"outputs":{"out":"float"}},"ND_worleynoise2d_float":{"node":"worleynoise2d","inherit":null,"inputs":{"texcoord":"vector2","jitter":"float","style":"integer"},"outputs":{"out":"float"}},"ND_worleynoise2d_vector2":{"node":"worleynoise2d","inherit":null,"inputs":{"texcoord":"vector2","jitter":"float","style":"integer"},"outputs":{"out":"vector2"}},"ND_worleynoise2d_vector3":{"node":"worleynoise2d","inherit":null,"inputs":{"texcoord":"vector2","jitter":"float","style":"integer"},"outputs":{"out":"vector3"}},"ND_worleynoise3d_float":{"node":"worleynoise3d","inherit":null,"inputs":{"position":"vector3","jitter":"float","style":"integer"},"outputs":{"out":"float"}},"ND_worleynoise3d_vector2":{"node":"worleynoise3d","inherit":null,"inputs":{"position":"vector3","jitter":"float","style":"integer"},"outputs":{"out":"vector2"}},"ND_worleynoise3d_vector3":{"node":"worleynoise3d","inherit":null,"inputs":{"position":"vector3","jitter":"float","style":"integer"},"outputs":{"out":"vector3"}},"ND_unifiednoise2d_float":{"node":"unifiednoise2d","inherit":null,"inputs":{"texcoord":"vector2","freq":"vector2","offset":"vector2","jitter":"float","outmin":"float","outmax":"float","clampoutput":"boolean","octaves":"integer","lacunarity":"float","diminish":"float","type":"integer","style":"integer"},"outputs":{"out":"float"}},"ND_unifiednoise3d_float":{"node":"unifiednoise3d","inherit":null,"inputs":{"position":"vector3","freq":"vector3","offset":"vector3","jitter":"float","outmin":"float","outmax":"float","clampoutput":"boolean","octaves":"integer","lacunarity":"float","diminish":"float","type":"integer","style":"integer"},"outputs":{"out":"float"}},"ND_flake2d":{"node":"flake2d","inherit":null,"inputs":{"size":"float","roughness":"float","coverage":"float","texcoord":"vector2","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"id":"integer","rand":"float","presence":"float","flakenormal":"vector3"}},"ND_flake3d":{"node":"flake3d","inherit":null,"inputs":{"size":"float","roughness":"float","coverage":"float","position":"vector3","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"id":"integer","rand":"float","presence":"float","flakenormal":"vector3"}},"ND_randomfloat_float":{"node":"randomfloat","inherit":null,"inputs":{"in":"float","min":"float","max":"float","seed":"integer"},"outputs":{"out":"float"}},"ND_randomfloat_integer":{"node":"randomfloat","inherit":null,"inputs":{"in":"integer","min":"float","max":"float","seed":"integer"},"outputs":{"out":"float"}},"ND_randomcolor_float":{"node":"randomcolor","inherit":null,"inputs":{"in":"float","huelow":"float","huehigh":"float","saturationlow":"float","saturationhigh":"float","brightnesslow":"float","brightnesshigh":"float","seed":"integer"},"outputs":{"out":"color3"}},"ND_randomcolor_integer":{"node":"randomcolor","inherit":null,"inputs":{"in":"integer","huelow":"float","huehigh":"float","saturationlow":"float","saturationhigh":"float","brightnesslow":"float","brightnesshigh":"float","seed":"integer"},"outputs":{"out":"color3"}},"ND_checkerboard_color3":{"node":"checkerboard","inherit":null,"inputs":{"color1":"color3","color2":"color3","uvtiling":"vector2","uvoffset":"vector2","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_line_float":{"node":"line","inherit":null,"inputs":{"texcoord":"vector2","center":"vector2","radius":"float","point1":"vector2","point2":"vector2"},"outputs":{"out":"float"}},"ND_circle_float":{"node":"circle","inherit":null,"inputs":{"texcoord":"vector2","center":"vector2","radius":"float"},"outputs":{"out":"float"}},"ND_cloverleaf_float":{"node":"cloverleaf","inherit":null,"inputs":{"texcoord":"vector2","center":"vector2","radius":"float"},"outputs":{"out":"float"}},"ND_hexagon_float":{"node":"hexagon","inherit":null,"inputs":{"texcoord":"vector2","center":"vector2","radius":"float"},"outputs":{"out":"float"}},"ND_grid_color3":{"node":"grid","inherit":null,"inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","thickness":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_crosshatch_color3":{"node":"crosshatch","inherit":null,"inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","thickness":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_tiledcircles_color3":{"node":"tiledcircles","inherit":null,"inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","size":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_tiledcloverleafs_color3":{"node":"tiledcloverleafs","inherit":null,"inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","size":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_tiledhexagons_color3":{"node":"tiledhexagons","inherit":null,"inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","size":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_position_vector3":{"node":"position","inherit":null,"inputs":{"space":"string"},"outputs":{"out":"vector3"}},"ND_normal_vector3":{"node":"normal","inherit":null,"inputs":{"space":"string"},"outputs":{"out":"vector3"}},"ND_tangent_vector3":{"node":"tangent","inherit":null,"inputs":{"space":"string","index":"integer"},"outputs":{"out":"vector3"}},"ND_bitangent_vector3":{"node":"bitangent","inherit":null,"inputs":{"space":"string","index":"integer"},"outputs":{"out":"vector3"}},"ND_texcoord_vector2":{"node":"texcoord","inherit":null,"inputs":{"index":"integer"},"outputs":{"out":"vector2"}},"ND_texcoord_vector3":{"node":"texcoord","inherit":null,"inputs":{"index":"integer"},"outputs":{"out":"vector3"}},"ND_geomcolor_float":{"node":"geomcolor","inherit":null,"inputs":{"index":"integer"},"outputs":{"out":"float"}},"ND_geomcolor_color3":{"node":"geomcolor","inherit":null,"inputs":{"index":"integer"},"outputs":{"out":"color3"}},"ND_geomcolor_color4":{"node":"geomcolor","inherit":null,"inputs":{"index":"integer"},"outputs":{"out":"color4"}},"ND_geompropvalue_integer":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"integer"},"outputs":{"out":"integer"}},"ND_geompropvalue_boolean":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"boolean"},"outputs":{"out":"boolean"}},"ND_geompropvalue_float":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"float"},"outputs":{"out":"float"}},"ND_geompropvalue_color3":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"color3"},"outputs":{"out":"color3"}},"ND_geompropvalue_color4":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"color4"},"outputs":{"out":"color4"}},"ND_geompropvalue_vector2":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"vector2"},"outputs":{"out":"vector2"}},"ND_geompropvalue_vector3":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"vector3"},"outputs":{"out":"vector3"}},"ND_geompropvalue_vector4":{"node":"geompropvalue","inherit":null,"inputs":{"geomprop":"string","default":"vector4"},"outputs":{"out":"vector4"}},"ND_geompropvalueuniform_string":{"node":"geompropvalueuniform","inherit":null,"inputs":{"geomprop":"string","default":"string"},"outputs":{"out":"string"}},"ND_geompropvalueuniform_filename":{"node":"geompropvalueuniform","inherit":null,"inputs":{"geomprop":"string","default":"filename"},"outputs":{"out":"filename"}},"ND_bump_vector3":{"node":"bump","inherit":null,"inputs":{"height":"float","scale":"float","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_frame_float":{"node":"frame","inherit":null,"inputs":{},"outputs":{"out":"float"}},"ND_time_float":{"node":"time","inherit":null,"inputs":{"fps":"float"},"outputs":{"out":"float"}},"ND_add_float":{"node":"add","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_add_integer":{"node":"add","inherit":null,"inputs":{"in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_add_color3":{"node":"add","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_add_color4":{"node":"add","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_add_vector2":{"node":"add","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_add_vector3":{"node":"add","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_add_vector4":{"node":"add","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_add_matrix33":{"node":"add","inherit":null,"inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_add_matrix44":{"node":"add","inherit":null,"inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_add_color3FA":{"node":"add","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_add_color4FA":{"node":"add","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_add_vector2FA":{"node":"add","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_add_vector3FA":{"node":"add","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_add_vector4FA":{"node":"add","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_add_matrix33FA":{"node":"add","inherit":null,"inputs":{"in1":"matrix33","in2":"float"},"outputs":{"out":"matrix33"}},"ND_add_matrix44FA":{"node":"add","inherit":null,"inputs":{"in1":"matrix44","in2":"float"},"outputs":{"out":"matrix44"}},"ND_subtract_float":{"node":"subtract","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_subtract_integer":{"node":"subtract","inherit":null,"inputs":{"in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_subtract_color3":{"node":"subtract","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_subtract_color4":{"node":"subtract","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_subtract_vector2":{"node":"subtract","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_subtract_vector3":{"node":"subtract","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_subtract_vector4":{"node":"subtract","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_subtract_matrix33":{"node":"subtract","inherit":null,"inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_subtract_matrix44":{"node":"subtract","inherit":null,"inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_subtract_color3FA":{"node":"subtract","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_subtract_color4FA":{"node":"subtract","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_subtract_vector2FA":{"node":"subtract","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_subtract_vector3FA":{"node":"subtract","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_subtract_vector4FA":{"node":"subtract","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_subtract_matrix33FA":{"node":"subtract","inherit":null,"inputs":{"in1":"matrix33","in2":"float"},"outputs":{"out":"matrix33"}},"ND_subtract_matrix44FA":{"node":"subtract","inherit":null,"inputs":{"in1":"matrix44","in2":"float"},"outputs":{"out":"matrix44"}},"ND_multiply_float":{"node":"multiply","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_multiply_color3":{"node":"multiply","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_multiply_color4":{"node":"multiply","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_multiply_vector2":{"node":"multiply","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_multiply_vector3":{"node":"multiply","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_multiply_vector4":{"node":"multiply","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_multiply_matrix33":{"node":"multiply","inherit":null,"inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_multiply_matrix44":{"node":"multiply","inherit":null,"inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_multiply_color3FA":{"node":"multiply","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_multiply_color4FA":{"node":"multiply","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_multiply_vector2FA":{"node":"multiply","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_multiply_vector3FA":{"node":"multiply","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_multiply_vector4FA":{"node":"multiply","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_divide_float":{"node":"divide","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_divide_color3":{"node":"divide","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_divide_color4":{"node":"divide","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_divide_vector2":{"node":"divide","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_divide_vector3":{"node":"divide","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_divide_vector4":{"node":"divide","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_divide_matrix33":{"node":"divide","inherit":null,"inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_divide_matrix44":{"node":"divide","inherit":null,"inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_divide_color3FA":{"node":"divide","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_divide_color4FA":{"node":"divide","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_divide_vector2FA":{"node":"divide","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_divide_vector3FA":{"node":"divide","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_divide_vector4FA":{"node":"divide","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_modulo_float":{"node":"modulo","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_modulo_color3":{"node":"modulo","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_modulo_color4":{"node":"modulo","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_modulo_vector2":{"node":"modulo","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_modulo_vector3":{"node":"modulo","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_modulo_vector4":{"node":"modulo","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_modulo_color3FA":{"node":"modulo","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_modulo_color4FA":{"node":"modulo","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_modulo_vector2FA":{"node":"modulo","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_modulo_vector3FA":{"node":"modulo","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_modulo_vector4FA":{"node":"modulo","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_fract_float":{"node":"fract","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_fract_color3":{"node":"fract","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_fract_color4":{"node":"fract","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_fract_vector2":{"node":"fract","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_fract_vector3":{"node":"fract","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_fract_vector4":{"node":"fract","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_invert_float":{"node":"invert","inherit":null,"inputs":{"in":"float","amount":"float"},"outputs":{"out":"float"}},"ND_invert_color3":{"node":"invert","inherit":null,"inputs":{"in":"color3","amount":"color3"},"outputs":{"out":"color3"}},"ND_invert_color4":{"node":"invert","inherit":null,"inputs":{"in":"color4","amount":"color4"},"outputs":{"out":"color4"}},"ND_invert_vector2":{"node":"invert","inherit":null,"inputs":{"in":"vector2","amount":"vector2"},"outputs":{"out":"vector2"}},"ND_invert_vector3":{"node":"invert","inherit":null,"inputs":{"in":"vector3","amount":"vector3"},"outputs":{"out":"vector3"}},"ND_invert_vector4":{"node":"invert","inherit":null,"inputs":{"in":"vector4","amount":"vector4"},"outputs":{"out":"vector4"}},"ND_invert_color3FA":{"node":"invert","inherit":null,"inputs":{"in":"color3","amount":"float"},"outputs":{"out":"color3"}},"ND_invert_color4FA":{"node":"invert","inherit":null,"inputs":{"in":"color4","amount":"float"},"outputs":{"out":"color4"}},"ND_invert_vector2FA":{"node":"invert","inherit":null,"inputs":{"in":"vector2","amount":"float"},"outputs":{"out":"vector2"}},"ND_invert_vector3FA":{"node":"invert","inherit":null,"inputs":{"in":"vector3","amount":"float"},"outputs":{"out":"vector3"}},"ND_invert_vector4FA":{"node":"invert","inherit":null,"inputs":{"in":"vector4","amount":"float"},"outputs":{"out":"vector4"}},"ND_absval_float":{"node":"absval","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_absval_color3":{"node":"absval","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_absval_color4":{"node":"absval","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_absval_vector2":{"node":"absval","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_absval_vector3":{"node":"absval","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_absval_vector4":{"node":"absval","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_floor_float":{"node":"floor","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_floor_color3":{"node":"floor","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_floor_color4":{"node":"floor","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_floor_vector2":{"node":"floor","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_floor_vector3":{"node":"floor","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_floor_vector4":{"node":"floor","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_floor_integer":{"node":"floor","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"integer"}},"ND_ceil_float":{"node":"ceil","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_ceil_color3":{"node":"ceil","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_ceil_color4":{"node":"ceil","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_ceil_vector2":{"node":"ceil","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_ceil_vector3":{"node":"ceil","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_ceil_vector4":{"node":"ceil","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_ceil_integer":{"node":"ceil","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"integer"}},"ND_round_float":{"node":"round","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_round_color3":{"node":"round","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_round_color4":{"node":"round","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_round_vector2":{"node":"round","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_round_vector3":{"node":"round","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_round_vector4":{"node":"round","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_round_integer":{"node":"round","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"integer"}},"ND_power_float":{"node":"power","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_power_color3":{"node":"power","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_power_color4":{"node":"power","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_power_vector2":{"node":"power","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_power_vector3":{"node":"power","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_power_vector4":{"node":"power","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_power_color3FA":{"node":"power","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_power_color4FA":{"node":"power","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_power_vector2FA":{"node":"power","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_power_vector3FA":{"node":"power","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_power_vector4FA":{"node":"power","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_safepower_float":{"node":"safepower","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_safepower_color3":{"node":"safepower","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_safepower_color4":{"node":"safepower","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_safepower_vector2":{"node":"safepower","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_safepower_vector3":{"node":"safepower","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_safepower_vector4":{"node":"safepower","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_safepower_color3FA":{"node":"safepower","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_safepower_color4FA":{"node":"safepower","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_safepower_vector2FA":{"node":"safepower","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_safepower_vector3FA":{"node":"safepower","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_safepower_vector4FA":{"node":"safepower","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_sin_float":{"node":"sin","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_cos_float":{"node":"cos","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_tan_float":{"node":"tan","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_asin_float":{"node":"asin","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_acos_float":{"node":"acos","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_atan2_float":{"node":"atan2","inherit":null,"inputs":{"iny":"float","inx":"float"},"outputs":{"out":"float"}},"ND_sin_vector2":{"node":"sin","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_cos_vector2":{"node":"cos","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_tan_vector2":{"node":"tan","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_asin_vector2":{"node":"asin","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_acos_vector2":{"node":"acos","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_atan2_vector2":{"node":"atan2","inherit":null,"inputs":{"iny":"vector2","inx":"vector2"},"outputs":{"out":"vector2"}},"ND_sin_vector3":{"node":"sin","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_cos_vector3":{"node":"cos","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_tan_vector3":{"node":"tan","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_asin_vector3":{"node":"asin","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_acos_vector3":{"node":"acos","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_atan2_vector3":{"node":"atan2","inherit":null,"inputs":{"iny":"vector3","inx":"vector3"},"outputs":{"out":"vector3"}},"ND_sin_vector4":{"node":"sin","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_cos_vector4":{"node":"cos","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_tan_vector4":{"node":"tan","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_asin_vector4":{"node":"asin","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_acos_vector4":{"node":"acos","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_atan2_vector4":{"node":"atan2","inherit":null,"inputs":{"iny":"vector4","inx":"vector4"},"outputs":{"out":"vector4"}},"ND_sqrt_float":{"node":"sqrt","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_ln_float":{"node":"ln","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_exp_float":{"node":"exp","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_sqrt_vector2":{"node":"sqrt","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_ln_vector2":{"node":"ln","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_exp_vector2":{"node":"exp","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_sqrt_vector3":{"node":"sqrt","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_ln_vector3":{"node":"ln","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_exp_vector3":{"node":"exp","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_sqrt_vector4":{"node":"sqrt","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_ln_vector4":{"node":"ln","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_exp_vector4":{"node":"exp","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_sign_float":{"node":"sign","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_sign_color3":{"node":"sign","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_sign_color4":{"node":"sign","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_sign_vector2":{"node":"sign","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_sign_vector3":{"node":"sign","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_sign_vector4":{"node":"sign","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_clamp_float":{"node":"clamp","inherit":null,"inputs":{"in":"float","low":"float","high":"float"},"outputs":{"out":"float"}},"ND_clamp_color3":{"node":"clamp","inherit":null,"inputs":{"in":"color3","low":"color3","high":"color3"},"outputs":{"out":"color3"}},"ND_clamp_color4":{"node":"clamp","inherit":null,"inputs":{"in":"color4","low":"color4","high":"color4"},"outputs":{"out":"color4"}},"ND_clamp_vector2":{"node":"clamp","inherit":null,"inputs":{"in":"vector2","low":"vector2","high":"vector2"},"outputs":{"out":"vector2"}},"ND_clamp_vector3":{"node":"clamp","inherit":null,"inputs":{"in":"vector3","low":"vector3","high":"vector3"},"outputs":{"out":"vector3"}},"ND_clamp_vector4":{"node":"clamp","inherit":null,"inputs":{"in":"vector4","low":"vector4","high":"vector4"},"outputs":{"out":"vector4"}},"ND_clamp_color3FA":{"node":"clamp","inherit":null,"inputs":{"in":"color3","low":"float","high":"float"},"outputs":{"out":"color3"}},"ND_clamp_color4FA":{"node":"clamp","inherit":null,"inputs":{"in":"color4","low":"float","high":"float"},"outputs":{"out":"color4"}},"ND_clamp_vector2FA":{"node":"clamp","inherit":null,"inputs":{"in":"vector2","low":"float","high":"float"},"outputs":{"out":"vector2"}},"ND_clamp_vector3FA":{"node":"clamp","inherit":null,"inputs":{"in":"vector3","low":"float","high":"float"},"outputs":{"out":"vector3"}},"ND_clamp_vector4FA":{"node":"clamp","inherit":null,"inputs":{"in":"vector4","low":"float","high":"float"},"outputs":{"out":"vector4"}},"ND_min_float":{"node":"min","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_min_color3":{"node":"min","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_min_color4":{"node":"min","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_min_vector2":{"node":"min","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_min_vector3":{"node":"min","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_min_vector4":{"node":"min","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_min_color3FA":{"node":"min","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_min_color4FA":{"node":"min","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_min_vector2FA":{"node":"min","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_min_vector3FA":{"node":"min","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_min_vector4FA":{"node":"min","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_max_float":{"node":"max","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_max_color3":{"node":"max","inherit":null,"inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_max_color4":{"node":"max","inherit":null,"inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_max_vector2":{"node":"max","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_max_vector3":{"node":"max","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_max_vector4":{"node":"max","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_max_color3FA":{"node":"max","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_max_color4FA":{"node":"max","inherit":null,"inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_max_vector2FA":{"node":"max","inherit":null,"inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_max_vector3FA":{"node":"max","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_max_vector4FA":{"node":"max","inherit":null,"inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_normalize_vector2":{"node":"normalize","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_normalize_vector3":{"node":"normalize","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_normalize_vector4":{"node":"normalize","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_magnitude_vector2":{"node":"magnitude","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"float"}},"ND_magnitude_vector3":{"node":"magnitude","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"float"}},"ND_magnitude_vector4":{"node":"magnitude","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"float"}},"ND_distance_vector2":{"node":"distance","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"float"}},"ND_distance_vector3":{"node":"distance","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"float"}},"ND_distance_vector4":{"node":"distance","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"float"}},"ND_dotproduct_vector2":{"node":"dotproduct","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"float"}},"ND_dotproduct_vector3":{"node":"dotproduct","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"float"}},"ND_dotproduct_vector4":{"node":"dotproduct","inherit":null,"inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"float"}},"ND_crossproduct_vector3":{"node":"crossproduct","inherit":null,"inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_transformpoint_vector3":{"node":"transformpoint","inherit":null,"inputs":{"in":"vector3","fromspace":"string","tospace":"string"},"outputs":{"out":"vector3"}},"ND_transformvector_vector3":{"node":"transformvector","inherit":null,"inputs":{"in":"vector3","fromspace":"string","tospace":"string"},"outputs":{"out":"vector3"}},"ND_transformnormal_vector3":{"node":"transformnormal","inherit":null,"inputs":{"in":"vector3","fromspace":"string","tospace":"string"},"outputs":{"out":"vector3"}},"ND_transformmatrix_vector2M3":{"node":"transformmatrix","inherit":null,"inputs":{"in":"vector2","mat":"matrix33"},"outputs":{"out":"vector2"}},"ND_transformmatrix_vector3":{"node":"transformmatrix","inherit":null,"inputs":{"in":"vector3","mat":"matrix33"},"outputs":{"out":"vector3"}},"ND_transformmatrix_vector3M4":{"node":"transformmatrix","inherit":null,"inputs":{"in":"vector3","mat":"matrix44"},"outputs":{"out":"vector3"}},"ND_transformmatrix_vector4":{"node":"transformmatrix","inherit":null,"inputs":{"in":"vector4","mat":"matrix44"},"outputs":{"out":"vector4"}},"ND_normalmap_float":{"node":"normalmap","inherit":null,"inputs":{"in":"vector3","scale":"float","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_normalmap_vector2":{"node":"normalmap","inherit":null,"inputs":{"in":"vector3","scale":"vector2","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_hextilednormalmap_vector3":{"node":"hextilednormalmap","inherit":null,"inputs":{"file":"filename","default":"vector3","texcoord":"vector2","tiling":"vector2","rotation":"float","rotationrange":"vector2","scale":"float","scalerange":"vector2","offset":"float","offsetrange":"vector2","falloff":"float","strength":"float","flip_g":"boolean","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_transpose_matrix33":{"node":"transpose","inherit":null,"inputs":{"in":"matrix33"},"outputs":{"out":"matrix33"}},"ND_transpose_matrix44":{"node":"transpose","inherit":null,"inputs":{"in":"matrix44"},"outputs":{"out":"matrix44"}},"ND_determinant_matrix33":{"node":"determinant","inherit":null,"inputs":{"in":"matrix33"},"outputs":{"out":"float"}},"ND_determinant_matrix44":{"node":"determinant","inherit":null,"inputs":{"in":"matrix44"},"outputs":{"out":"float"}},"ND_invertmatrix_matrix33":{"node":"invertmatrix","inherit":null,"inputs":{"in":"matrix33"},"outputs":{"out":"matrix33"}},"ND_invertmatrix_matrix44":{"node":"invertmatrix","inherit":null,"inputs":{"in":"matrix44"},"outputs":{"out":"matrix44"}},"ND_rotate2d_vector2":{"node":"rotate2d","inherit":null,"inputs":{"in":"vector2","amount":"float"},"outputs":{"out":"vector2"}},"ND_rotate3d_vector3":{"node":"rotate3d","inherit":null,"inputs":{"in":"vector3","amount":"float","axis":"vector3"},"outputs":{"out":"vector3"}},"ND_place2d_vector2":{"node":"place2d","inherit":null,"inputs":{"texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer"},"outputs":{"out":"vector2"}},"ND_trianglewave_float":{"node":"trianglewave","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_reflect_vector3":{"node":"reflect","inherit":null,"inputs":{"in":"vector3","normal":"vector3"},"outputs":{"out":"vector3"}},"ND_refract_vector3":{"node":"refract","inherit":null,"inputs":{"in":"vector3","normal":"vector3","ior":"float"},"outputs":{"out":"vector3"}},"ND_remap_float":{"node":"remap","inherit":null,"inputs":{"in":"float","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"float"}},"ND_remap_color3":{"node":"remap","inherit":null,"inputs":{"in":"color3","inlow":"color3","inhigh":"color3","outlow":"color3","outhigh":"color3"},"outputs":{"out":"color3"}},"ND_remap_color4":{"node":"remap","inherit":null,"inputs":{"in":"color4","inlow":"color4","inhigh":"color4","outlow":"color4","outhigh":"color4"},"outputs":{"out":"color4"}},"ND_remap_vector2":{"node":"remap","inherit":null,"inputs":{"in":"vector2","inlow":"vector2","inhigh":"vector2","outlow":"vector2","outhigh":"vector2"},"outputs":{"out":"vector2"}},"ND_remap_vector3":{"node":"remap","inherit":null,"inputs":{"in":"vector3","inlow":"vector3","inhigh":"vector3","outlow":"vector3","outhigh":"vector3"},"outputs":{"out":"vector3"}},"ND_remap_vector4":{"node":"remap","inherit":null,"inputs":{"in":"vector4","inlow":"vector4","inhigh":"vector4","outlow":"vector4","outhigh":"vector4"},"outputs":{"out":"vector4"}},"ND_remap_color3FA":{"node":"remap","inherit":null,"inputs":{"in":"color3","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"color3"}},"ND_remap_color4FA":{"node":"remap","inherit":null,"inputs":{"in":"color4","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"color4"}},"ND_remap_vector2FA":{"node":"remap","inherit":null,"inputs":{"in":"vector2","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"vector2"}},"ND_remap_vector3FA":{"node":"remap","inherit":null,"inputs":{"in":"vector3","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"vector3"}},"ND_remap_vector4FA":{"node":"remap","inherit":null,"inputs":{"in":"vector4","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"vector4"}},"ND_smoothstep_float":{"node":"smoothstep","inherit":null,"inputs":{"in":"float","low":"float","high":"float"},"outputs":{"out":"float"}},"ND_smoothstep_color3":{"node":"smoothstep","inherit":null,"inputs":{"in":"color3","low":"color3","high":"color3"},"outputs":{"out":"color3"}},"ND_smoothstep_color4":{"node":"smoothstep","inherit":null,"inputs":{"in":"color4","low":"color4","high":"color4"},"outputs":{"out":"color4"}},"ND_smoothstep_vector2":{"node":"smoothstep","inherit":null,"inputs":{"in":"vector2","low":"vector2","high":"vector2"},"outputs":{"out":"vector2"}},"ND_smoothstep_vector3":{"node":"smoothstep","inherit":null,"inputs":{"in":"vector3","low":"vector3","high":"vector3"},"outputs":{"out":"vector3"}},"ND_smoothstep_vector4":{"node":"smoothstep","inherit":null,"inputs":{"in":"vector4","low":"vector4","high":"vector4"},"outputs":{"out":"vector4"}},"ND_smoothstep_color3FA":{"node":"smoothstep","inherit":null,"inputs":{"in":"color3","low":"float","high":"float"},"outputs":{"out":"color3"}},"ND_smoothstep_color4FA":{"node":"smoothstep","inherit":null,"inputs":{"in":"color4","low":"float","high":"float"},"outputs":{"out":"color4"}},"ND_smoothstep_vector2FA":{"node":"smoothstep","inherit":null,"inputs":{"in":"vector2","low":"float","high":"float"},"outputs":{"out":"vector2"}},"ND_smoothstep_vector3FA":{"node":"smoothstep","inherit":null,"inputs":{"in":"vector3","low":"float","high":"float"},"outputs":{"out":"vector3"}},"ND_smoothstep_vector4FA":{"node":"smoothstep","inherit":null,"inputs":{"in":"vector4","low":"float","high":"float"},"outputs":{"out":"vector4"}},"ND_luminance_color3":{"node":"luminance","inherit":null,"inputs":{"in":"color3","lumacoeffs":"color3"},"outputs":{"out":"color3"}},"ND_luminance_color4":{"node":"luminance","inherit":null,"inputs":{"in":"color4","lumacoeffs":"color3"},"outputs":{"out":"color4"}},"ND_rgbtohsv_color3":{"node":"rgbtohsv","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_rgbtohsv_color4":{"node":"rgbtohsv","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_hsvtorgb_color3":{"node":"hsvtorgb","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_hsvtorgb_color4":{"node":"hsvtorgb","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_contrast_float":{"node":"contrast","inherit":null,"inputs":{"in":"float","amount":"float","pivot":"float"},"outputs":{"out":"float"}},"ND_contrast_color3":{"node":"contrast","inherit":null,"inputs":{"in":"color3","amount":"color3","pivot":"color3"},"outputs":{"out":"color3"}},"ND_contrast_color4":{"node":"contrast","inherit":null,"inputs":{"in":"color4","amount":"color4","pivot":"color4"},"outputs":{"out":"color4"}},"ND_contrast_vector2":{"node":"contrast","inherit":null,"inputs":{"in":"vector2","amount":"vector2","pivot":"vector2"},"outputs":{"out":"vector2"}},"ND_contrast_vector3":{"node":"contrast","inherit":null,"inputs":{"in":"vector3","amount":"vector3","pivot":"vector3"},"outputs":{"out":"vector3"}},"ND_contrast_vector4":{"node":"contrast","inherit":null,"inputs":{"in":"vector4","amount":"vector4","pivot":"vector4"},"outputs":{"out":"vector4"}},"ND_contrast_color3FA":{"node":"contrast","inherit":null,"inputs":{"in":"color3","amount":"float","pivot":"float"},"outputs":{"out":"color3"}},"ND_contrast_color4FA":{"node":"contrast","inherit":null,"inputs":{"in":"color4","amount":"float","pivot":"float"},"outputs":{"out":"color4"}},"ND_contrast_vector2FA":{"node":"contrast","inherit":null,"inputs":{"in":"vector2","amount":"float","pivot":"float"},"outputs":{"out":"vector2"}},"ND_contrast_vector3FA":{"node":"contrast","inherit":null,"inputs":{"in":"vector3","amount":"float","pivot":"float"},"outputs":{"out":"vector3"}},"ND_contrast_vector4FA":{"node":"contrast","inherit":null,"inputs":{"in":"vector4","amount":"float","pivot":"float"},"outputs":{"out":"vector4"}},"ND_range_float":{"node":"range","inherit":null,"inputs":{"in":"float","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"float"}},"ND_range_color3":{"node":"range","inherit":null,"inputs":{"in":"color3","inlow":"color3","inhigh":"color3","gamma":"color3","outlow":"color3","outhigh":"color3","doclamp":"boolean"},"outputs":{"out":"color3"}},"ND_range_color4":{"node":"range","inherit":null,"inputs":{"in":"color4","inlow":"color4","inhigh":"color4","gamma":"color4","outlow":"color4","outhigh":"color4","doclamp":"boolean"},"outputs":{"out":"color4"}},"ND_range_vector2":{"node":"range","inherit":null,"inputs":{"in":"vector2","inlow":"vector2","inhigh":"vector2","gamma":"vector2","outlow":"vector2","outhigh":"vector2","doclamp":"boolean"},"outputs":{"out":"vector2"}},"ND_range_vector3":{"node":"range","inherit":null,"inputs":{"in":"vector3","inlow":"vector3","inhigh":"vector3","gamma":"vector3","outlow":"vector3","outhigh":"vector3","doclamp":"boolean"},"outputs":{"out":"vector3"}},"ND_range_vector4":{"node":"range","inherit":null,"inputs":{"in":"vector4","inlow":"vector4","inhigh":"vector4","gamma":"vector4","outlow":"vector4","outhigh":"vector4","doclamp":"boolean"},"outputs":{"out":"vector4"}},"ND_range_color3FA":{"node":"range","inherit":null,"inputs":{"in":"color3","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"color3"}},"ND_range_color4FA":{"node":"range","inherit":null,"inputs":{"in":"color4","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"color4"}},"ND_range_vector2FA":{"node":"range","inherit":null,"inputs":{"in":"vector2","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"vector2"}},"ND_range_vector3FA":{"node":"range","inherit":null,"inputs":{"in":"vector3","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"vector3"}},"ND_range_vector4FA":{"node":"range","inherit":null,"inputs":{"in":"vector4","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"vector4"}},"ND_hsvadjust_color3":{"node":"hsvadjust","inherit":null,"inputs":{"in":"color3","amount":"vector3"},"outputs":{"out":"color3"}},"ND_hsvadjust_color4":{"node":"hsvadjust","inherit":null,"inputs":{"in":"color4","amount":"vector3"},"outputs":{"out":"color4"}},"ND_saturate_color3":{"node":"saturate","inherit":null,"inputs":{"in":"color3","amount":"float","lumacoeffs":"color3"},"outputs":{"out":"color3"}},"ND_saturate_color4":{"node":"saturate","inherit":null,"inputs":{"in":"color4","amount":"float","lumacoeffs":"color3"},"outputs":{"out":"color4"}},"ND_colorcorrect_color3":{"node":"colorcorrect","inherit":null,"inputs":{"in":"color3","hue":"float","saturation":"float","gamma":"float","lift":"float","gain":"float","contrast":"float","contrastpivot":"float","exposure":"float"},"outputs":{"out":"color3"}},"ND_colorcorrect_color4":{"node":"colorcorrect","inherit":null,"inputs":{"in":"color4","hue":"float","saturation":"float","gamma":"float","lift":"float","gain":"float","contrast":"float","contrastpivot":"float","exposure":"float"},"outputs":{"out":"color4"}},"ND_premult_color4":{"node":"premult","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_unpremult_color4":{"node":"unpremult","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_plus_float":{"node":"plus","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_plus_color3":{"node":"plus","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_plus_color4":{"node":"plus","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_minus_float":{"node":"minus","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_minus_color3":{"node":"minus","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_minus_color4":{"node":"minus","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_difference_float":{"node":"difference","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_difference_color3":{"node":"difference","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_difference_color4":{"node":"difference","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_burn_float":{"node":"burn","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_burn_color3":{"node":"burn","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_burn_color4":{"node":"burn","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_dodge_float":{"node":"dodge","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_dodge_color3":{"node":"dodge","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_dodge_color4":{"node":"dodge","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_screen_float":{"node":"screen","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_screen_color3":{"node":"screen","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_screen_color4":{"node":"screen","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_overlay_float":{"node":"overlay","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_overlay_color3":{"node":"overlay","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_overlay_color4":{"node":"overlay","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_disjointover_color4":{"node":"disjointover","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_in_color4":{"node":"in","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_mask_color4":{"node":"mask","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_matte_color4":{"node":"matte","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_out_color4":{"node":"out","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_over_color4":{"node":"over","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_inside_float":{"node":"inside","inherit":null,"inputs":{"in":"float","mask":"float"},"outputs":{"out":"float"}},"ND_inside_color3":{"node":"inside","inherit":null,"inputs":{"in":"color3","mask":"float"},"outputs":{"out":"color3"}},"ND_inside_color4":{"node":"inside","inherit":null,"inputs":{"in":"color4","mask":"float"},"outputs":{"out":"color4"}},"ND_outside_float":{"node":"outside","inherit":null,"inputs":{"in":"float","mask":"float"},"outputs":{"out":"float"}},"ND_outside_color3":{"node":"outside","inherit":null,"inputs":{"in":"color3","mask":"float"},"outputs":{"out":"color3"}},"ND_outside_color4":{"node":"outside","inherit":null,"inputs":{"in":"color4","mask":"float"},"outputs":{"out":"color4"}},"ND_mix_float":{"node":"mix","inherit":null,"inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_mix_color3":{"node":"mix","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_mix_color3_color3":{"node":"mix","inherit":null,"inputs":{"fg":"color3","bg":"color3","mix":"color3"},"outputs":{"out":"color3"}},"ND_mix_color4":{"node":"mix","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_mix_color4_color4":{"node":"mix","inherit":null,"inputs":{"fg":"color4","bg":"color4","mix":"color4"},"outputs":{"out":"color4"}},"ND_mix_vector2":{"node":"mix","inherit":null,"inputs":{"fg":"vector2","bg":"vector2","mix":"float"},"outputs":{"out":"vector2"}},"ND_mix_vector2_vector2":{"node":"mix","inherit":null,"inputs":{"fg":"vector2","bg":"vector2","mix":"vector2"},"outputs":{"out":"vector2"}},"ND_mix_vector3":{"node":"mix","inherit":null,"inputs":{"fg":"vector3","bg":"vector3","mix":"float"},"outputs":{"out":"vector3"}},"ND_mix_vector3_vector3":{"node":"mix","inherit":null,"inputs":{"fg":"vector3","bg":"vector3","mix":"vector3"},"outputs":{"out":"vector3"}},"ND_mix_vector4":{"node":"mix","inherit":null,"inputs":{"fg":"vector4","bg":"vector4","mix":"float"},"outputs":{"out":"vector4"}},"ND_mix_vector4_vector4":{"node":"mix","inherit":null,"inputs":{"fg":"vector4","bg":"vector4","mix":"vector4"},"outputs":{"out":"vector4"}},"ND_mix_surfaceshader":{"node":"mix","inherit":null,"inputs":{"fg":"surfaceshader","bg":"surfaceshader","mix":"float"},"outputs":{"out":"surfaceshader"}},"ND_mix_displacementshader":{"node":"mix","inherit":null,"inputs":{"fg":"displacementshader","bg":"displacementshader","mix":"float"},"outputs":{"out":"displacementshader"}},"ND_mix_volumeshader":{"node":"mix","inherit":null,"inputs":{"fg":"volumeshader","bg":"volumeshader","mix":"float"},"outputs":{"out":"volumeshader"}},"ND_ifgreater_float":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreater_integer":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreater_color3":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreater_color4":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreater_vector2":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreater_vector3":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreater_vector4":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreater_matrix33":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreater_matrix44":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreater_boolean":{"node":"ifgreater","inherit":null,"inputs":{"value1":"float","value2":"float"},"outputs":{"out":"boolean"}},"ND_ifgreater_floatI":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreater_integerI":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreater_color3I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreater_color4I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreater_vector2I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreater_vector3I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreater_vector4I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreater_matrix33I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreater_matrix44I":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreater_booleanI":{"node":"ifgreater","inherit":null,"inputs":{"value1":"integer","value2":"integer"},"outputs":{"out":"boolean"}},"ND_ifgreatereq_float":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreatereq_integer":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreatereq_color3":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreatereq_color4":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreatereq_vector2":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreatereq_vector3":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreatereq_vector4":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreatereq_matrix33":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreatereq_matrix44":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreatereq_boolean":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"float","value2":"float"},"outputs":{"out":"boolean"}},"ND_ifgreatereq_floatI":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreatereq_integerI":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreatereq_color3I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreatereq_color4I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreatereq_vector2I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreatereq_vector3I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreatereq_vector4I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreatereq_matrix33I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreatereq_matrix44I":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreatereq_booleanI":{"node":"ifgreatereq","inherit":null,"inputs":{"value1":"integer","value2":"integer"},"outputs":{"out":"boolean"}},"ND_ifequal_float":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifequal_integer":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifequal_color3":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifequal_color4":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifequal_vector2":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifequal_vector3":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifequal_vector4":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifequal_matrix33":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifequal_matrix44":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifequal_boolean":{"node":"ifequal","inherit":null,"inputs":{"value1":"float","value2":"float"},"outputs":{"out":"boolean"}},"ND_ifequal_floatI":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifequal_integerI":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifequal_color3I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifequal_color4I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifequal_vector2I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifequal_vector3I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifequal_vector4I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifequal_matrix33I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifequal_matrix44I":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifequal_booleanI":{"node":"ifequal","inherit":null,"inputs":{"value1":"integer","value2":"integer"},"outputs":{"out":"boolean"}},"ND_ifequal_floatB":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifequal_integerB":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifequal_color3B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifequal_color4B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifequal_vector2B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifequal_vector3B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifequal_vector4B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifequal_matrix33B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifequal_matrix44B":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifequal_booleanB":{"node":"ifequal","inherit":null,"inputs":{"value1":"boolean","value2":"boolean"},"outputs":{"out":"boolean"}},"ND_switch_float":{"node":"switch","inherit":null,"inputs":{"in1":"float","in2":"float","in3":"float","in4":"float","in5":"float","in6":"float","in7":"float","in8":"float","in9":"float","in10":"float","which":"float"},"outputs":{"out":"float"}},"ND_switch_color3":{"node":"switch","inherit":null,"inputs":{"in1":"color3","in2":"color3","in3":"color3","in4":"color3","in5":"color3","in6":"color3","in7":"color3","in8":"color3","in9":"color3","in10":"color3","which":"float"},"outputs":{"out":"color3"}},"ND_switch_color4":{"node":"switch","inherit":null,"inputs":{"in1":"color4","in2":"color4","in3":"color4","in4":"color4","in5":"color4","in6":"color4","in7":"color4","in8":"color4","in9":"color4","in10":"color4","which":"float"},"outputs":{"out":"color4"}},"ND_switch_vector2":{"node":"switch","inherit":null,"inputs":{"in1":"vector2","in2":"vector2","in3":"vector2","in4":"vector2","in5":"vector2","in6":"vector2","in7":"vector2","in8":"vector2","in9":"vector2","in10":"vector2","which":"float"},"outputs":{"out":"vector2"}},"ND_switch_vector3":{"node":"switch","inherit":null,"inputs":{"in1":"vector3","in2":"vector3","in3":"vector3","in4":"vector3","in5":"vector3","in6":"vector3","in7":"vector3","in8":"vector3","in9":"vector3","in10":"vector3","which":"float"},"outputs":{"out":"vector3"}},"ND_switch_vector4":{"node":"switch","inherit":null,"inputs":{"in1":"vector4","in2":"vector4","in3":"vector4","in4":"vector4","in5":"vector4","in6":"vector4","in7":"vector4","in8":"vector4","in9":"vector4","in10":"vector4","which":"float"},"outputs":{"out":"vector4"}},"ND_switch_matrix33":{"node":"switch","inherit":null,"inputs":{"in1":"matrix33","in2":"matrix33","in3":"matrix33","in4":"matrix33","in5":"matrix33","in6":"matrix33","in7":"matrix33","in8":"matrix33","in9":"matrix33","in10":"matrix33","which":"float"},"outputs":{"out":"matrix33"}},"ND_switch_matrix44":{"node":"switch","inherit":null,"inputs":{"in1":"matrix44","in2":"matrix44","in3":"matrix44","in4":"matrix44","in5":"matrix44","in6":"matrix44","in7":"matrix44","in8":"matrix44","in9":"matrix44","in10":"matrix44","which":"float"},"outputs":{"out":"matrix44"}},"ND_switch_floatI":{"node":"switch","inherit":null,"inputs":{"in1":"float","in2":"float","in3":"float","in4":"float","in5":"float","in6":"float","in7":"float","in8":"float","in9":"float","in10":"float","which":"integer"},"outputs":{"out":"float"}},"ND_switch_color3I":{"node":"switch","inherit":null,"inputs":{"in1":"color3","in2":"color3","in3":"color3","in4":"color3","in5":"color3","in6":"color3","in7":"color3","in8":"color3","in9":"color3","in10":"color3","which":"integer"},"outputs":{"out":"color3"}},"ND_switch_color4I":{"node":"switch","inherit":null,"inputs":{"in1":"color4","in2":"color4","in3":"color4","in4":"color4","in5":"color4","in6":"color4","in7":"color4","in8":"color4","in9":"color4","in10":"color4","which":"integer"},"outputs":{"out":"color4"}},"ND_switch_vector2I":{"node":"switch","inherit":null,"inputs":{"in1":"vector2","in2":"vector2","in3":"vector2","in4":"vector2","in5":"vector2","in6":"vector2","in7":"vector2","in8":"vector2","in9":"vector2","in10":"vector2","which":"integer"},"outputs":{"out":"vector2"}},"ND_switch_vector3I":{"node":"switch","inherit":null,"inputs":{"in1":"vector3","in2":"vector3","in3":"vector3","in4":"vector3","in5":"vector3","in6":"vector3","in7":"vector3","in8":"vector3","in9":"vector3","in10":"vector3","which":"integer"},"outputs":{"out":"vector3"}},"ND_switch_vector4I":{"node":"switch","inherit":null,"inputs":{"in1":"vector4","in2":"vector4","in3":"vector4","in4":"vector4","in5":"vector4","in6":"vector4","in7":"vector4","in8":"vector4","in9":"vector4","in10":"vector4","which":"integer"},"outputs":{"out":"vector4"}},"ND_switch_matrix33I":{"node":"switch","inherit":null,"inputs":{"in1":"matrix33","in2":"matrix33","in3":"matrix33","in4":"matrix33","in5":"matrix33","in6":"matrix33","in7":"matrix33","in8":"matrix33","in9":"matrix33","in10":"matrix33","which":"integer"},"outputs":{"out":"matrix33"}},"ND_switch_matrix44I":{"node":"switch","inherit":null,"inputs":{"in1":"matrix44","in2":"matrix44","in3":"matrix44","in4":"matrix44","in5":"matrix44","in6":"matrix44","in7":"matrix44","in8":"matrix44","in9":"matrix44","in10":"matrix44","which":"integer"},"outputs":{"out":"matrix44"}},"ND_convert_float_color3":{"node":"convert","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"color3"}},"ND_convert_float_color4":{"node":"convert","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"color4"}},"ND_convert_float_vector2":{"node":"convert","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"vector2"}},"ND_convert_float_vector3":{"node":"convert","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"vector3"}},"ND_convert_float_vector4":{"node":"convert","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"vector4"}},"ND_convert_color3_color4":{"node":"convert","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"color4"}},"ND_convert_color3_vector2":{"node":"convert","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"vector2"}},"ND_convert_color3_vector3":{"node":"convert","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"vector3"}},"ND_convert_color3_vector4":{"node":"convert","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"vector4"}},"ND_convert_color4_color3":{"node":"convert","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"color3"}},"ND_convert_color4_vector2":{"node":"convert","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"vector2"}},"ND_convert_color4_vector3":{"node":"convert","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"vector3"}},"ND_convert_color4_vector4":{"node":"convert","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"vector4"}},"ND_convert_vector2_color3":{"node":"convert","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"color3"}},"ND_convert_vector2_color4":{"node":"convert","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"color4"}},"ND_convert_vector2_vector3":{"node":"convert","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector3"}},"ND_convert_vector2_vector4":{"node":"convert","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"vector4"}},"ND_convert_vector3_color3":{"node":"convert","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"color3"}},"ND_convert_vector3_color4":{"node":"convert","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"color4"}},"ND_convert_vector3_vector2":{"node":"convert","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector2"}},"ND_convert_vector3_vector4":{"node":"convert","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"vector4"}},"ND_convert_vector4_color3":{"node":"convert","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"color3"}},"ND_convert_vector4_color4":{"node":"convert","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"color4"}},"ND_convert_vector4_vector2":{"node":"convert","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector2"}},"ND_convert_vector4_vector3":{"node":"convert","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"vector3"}},"ND_convert_boolean_float":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"float"}},"ND_convert_boolean_color3":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"color3"}},"ND_convert_boolean_color4":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"color4"}},"ND_convert_boolean_vector2":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"vector2"}},"ND_convert_boolean_vector3":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"vector3"}},"ND_convert_boolean_vector4":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"vector4"}},"ND_convert_boolean_integer":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"integer"}},"ND_convert_integer_float":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"float"}},"ND_convert_integer_color3":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"color3"}},"ND_convert_integer_color4":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"color4"}},"ND_convert_integer_vector2":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"vector2"}},"ND_convert_integer_vector3":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"vector3"}},"ND_convert_integer_vector4":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"vector4"}},"ND_convert_integer_boolean":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"boolean"}},"ND_convert_color3_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"color3"},"outputs":{"out":"surfaceshader"}},"ND_convert_color4_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"color4"},"outputs":{"out":"surfaceshader"}},"ND_convert_float_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"float"},"outputs":{"out":"surfaceshader"}},"ND_convert_vector2_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"vector2"},"outputs":{"out":"surfaceshader"}},"ND_convert_vector3_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_convert_vector4_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"vector4"},"outputs":{"out":"surfaceshader"}},"ND_convert_integer_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"integer"},"outputs":{"out":"surfaceshader"}},"ND_convert_boolean_surfaceshader":{"node":"convert","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"surfaceshader"}},"ND_combine2_vector2":{"node":"combine2","inherit":null,"inputs":{"in1":"float","in2":"float"},"outputs":{"out":"vector2"}},"ND_combine2_color4CF":{"node":"combine2","inherit":null,"inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color4"}},"ND_combine2_vector4VF":{"node":"combine2","inherit":null,"inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector4"}},"ND_combine2_vector4VV":{"node":"combine2","inherit":null,"inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector4"}},"ND_combine3_color3":{"node":"combine3","inherit":null,"inputs":{"in1":"float","in2":"float","in3":"float"},"outputs":{"out":"color3"}},"ND_combine3_vector3":{"node":"combine3","inherit":null,"inputs":{"in1":"float","in2":"float","in3":"float"},"outputs":{"out":"vector3"}},"ND_combine4_color4":{"node":"combine4","inherit":null,"inputs":{"in1":"float","in2":"float","in3":"float","in4":"float"},"outputs":{"out":"color4"}},"ND_combine4_vector4":{"node":"combine4","inherit":null,"inputs":{"in1":"float","in2":"float","in3":"float","in4":"float"},"outputs":{"out":"vector4"}},"ND_creatematrix_vector3_matrix33":{"node":"creatematrix","inherit":null,"inputs":{"in1":"vector3","in2":"vector3","in3":"vector3"},"outputs":{"out":"matrix33"}},"ND_creatematrix_vector3_matrix44":{"node":"creatematrix","inherit":null,"inputs":{"in1":"vector3","in2":"vector3","in3":"vector3","in4":"vector3"},"outputs":{"out":"matrix44"}},"ND_creatematrix_vector4_matrix44":{"node":"creatematrix","inherit":null,"inputs":{"in1":"vector4","in2":"vector4","in3":"vector4","in4":"vector4"},"outputs":{"out":"matrix44"}},"ND_extract_color3":{"node":"extract","inherit":null,"inputs":{"in":"color3","index":"integer"},"outputs":{"out":"float"}},"ND_extract_color4":{"node":"extract","inherit":null,"inputs":{"in":"color4","index":"integer"},"outputs":{"out":"float"}},"ND_extract_vector2":{"node":"extract","inherit":null,"inputs":{"in":"vector2","index":"integer"},"outputs":{"out":"float"}},"ND_extract_vector3":{"node":"extract","inherit":null,"inputs":{"in":"vector3","index":"integer"},"outputs":{"out":"float"}},"ND_extract_vector4":{"node":"extract","inherit":null,"inputs":{"in":"vector4","index":"integer"},"outputs":{"out":"float"}},"ND_extract_matrix33":{"node":"extract","inherit":null,"inputs":{"in":"matrix33","index":"integer"},"outputs":{"out":"vector3"}},"ND_extract_matrix44":{"node":"extract","inherit":null,"inputs":{"in":"matrix44","index":"integer"},"outputs":{"out":"vector4"}},"ND_separate2_vector2":{"node":"separate2","inherit":null,"inputs":{"in":"vector2"},"outputs":{"outx":"float","outy":"float"}},"ND_separate3_color3":{"node":"separate3","inherit":null,"inputs":{"in":"color3"},"outputs":{"outr":"float","outg":"float","outb":"float"}},"ND_separate3_vector3":{"node":"separate3","inherit":null,"inputs":{"in":"vector3"},"outputs":{"outx":"float","outy":"float","outz":"float"}},"ND_separate4_color4":{"node":"separate4","inherit":null,"inputs":{"in":"color4"},"outputs":{"outr":"float","outg":"float","outb":"float","outa":"float"}},"ND_separate4_vector4":{"node":"separate4","inherit":null,"inputs":{"in":"vector4"},"outputs":{"outx":"float","outy":"float","outz":"float","outw":"float"}},"ND_blur_float":{"node":"blur","inherit":null,"inputs":{"in":"float","size":"float","filtertype":"string"},"outputs":{"out":"float"}},"ND_blur_color3":{"node":"blur","inherit":null,"inputs":{"in":"color3","size":"float","filtertype":"string"},"outputs":{"out":"color3"}},"ND_blur_color4":{"node":"blur","inherit":null,"inputs":{"in":"color4","size":"float","filtertype":"string"},"outputs":{"out":"color4"}},"ND_blur_vector2":{"node":"blur","inherit":null,"inputs":{"in":"vector2","size":"float","filtertype":"string"},"outputs":{"out":"vector2"}},"ND_blur_vector3":{"node":"blur","inherit":null,"inputs":{"in":"vector3","size":"float","filtertype":"string"},"outputs":{"out":"vector3"}},"ND_blur_vector4":{"node":"blur","inherit":null,"inputs":{"in":"vector4","size":"float","filtertype":"string"},"outputs":{"out":"vector4"}},"ND_heighttonormal_vector3":{"node":"heighttonormal","inherit":null,"inputs":{"in":"float","scale":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_logical_and":{"node":"and","inherit":null,"inputs":{"in1":"boolean","in2":"boolean"},"outputs":{"out":"boolean"}},"ND_logical_or":{"node":"or","inherit":null,"inputs":{"in1":"boolean","in2":"boolean"},"outputs":{"out":"boolean"}},"ND_logical_xor":{"node":"xor","inherit":null,"inputs":{"in1":"boolean","in2":"boolean"},"outputs":{"out":"boolean"}},"ND_logical_not":{"node":"not","inherit":null,"inputs":{"in":"boolean"},"outputs":{"out":"boolean"}},"ND_dot_float":{"node":"dot","inherit":null,"inputs":{"in":"float","note":"string"},"outputs":{"out":"float"}},"ND_dot_color3":{"node":"dot","inherit":null,"inputs":{"in":"color3","note":"string"},"outputs":{"out":"color3"}},"ND_dot_color4":{"node":"dot","inherit":null,"inputs":{"in":"color4","note":"string"},"outputs":{"out":"color4"}},"ND_dot_vector2":{"node":"dot","inherit":null,"inputs":{"in":"vector2","note":"string"},"outputs":{"out":"vector2"}},"ND_dot_vector3":{"node":"dot","inherit":null,"inputs":{"in":"vector3","note":"string"},"outputs":{"out":"vector3"}},"ND_dot_vector4":{"node":"dot","inherit":null,"inputs":{"in":"vector4","note":"string"},"outputs":{"out":"vector4"}},"ND_dot_boolean":{"node":"dot","inherit":null,"inputs":{"in":"boolean","note":"string"},"outputs":{"out":"boolean"}},"ND_dot_integer":{"node":"dot","inherit":null,"inputs":{"in":"integer","note":"string"},"outputs":{"out":"integer"}},"ND_dot_matrix33":{"node":"dot","inherit":null,"inputs":{"in":"matrix33","note":"string"},"outputs":{"out":"matrix33"}},"ND_dot_matrix44":{"node":"dot","inherit":null,"inputs":{"in":"matrix44","note":"string"},"outputs":{"out":"matrix44"}},"ND_dot_string":{"node":"dot","inherit":null,"inputs":{"in":"string","note":"string"},"outputs":{"out":"string"}},"ND_dot_filename":{"node":"dot","inherit":null,"inputs":{"in":"filename","note":"string"},"outputs":{"out":"filename"}},"ND_dot_surfaceshader":{"node":"dot","inherit":null,"inputs":{"in":"surfaceshader","note":"string"},"outputs":{"out":"surfaceshader"}},"ND_dot_displacementshader":{"node":"dot","inherit":null,"inputs":{"in":"displacementshader","note":"string"},"outputs":{"out":"displacementshader"}},"ND_dot_volumeshader":{"node":"dot","inherit":null,"inputs":{"in":"volumeshader","note":"string"},"outputs":{"out":"volumeshader"}},"ND_dot_lightshader":{"node":"dot","inherit":null,"inputs":{"in":"lightshader","note":"string"},"outputs":{"out":"lightshader"}},"ND_point_light":{"node":"point_light","inherit":null,"inputs":{"position":"vector3","color":"color3","intensity":"float","decay_rate":"float"},"outputs":{"out":"lightshader"}},"ND_directional_light":{"node":"directional_light","inherit":null,"inputs":{"direction":"vector3","color":"color3","intensity":"float"},"outputs":{"out":"lightshader"}},"ND_spot_light":{"node":"spot_light","inherit":null,"inputs":{"position":"vector3","direction":"vector3","color":"color3","intensity":"float","decay_rate":"float","inner_angle":"float","outer_angle":"float"},"outputs":{"out":"lightshader"}},"ND_open_pbr_surface_to_standard_surface":{"node":"open_pbr_surface_to_standard_surface","inherit":null,"inputs":{"base_weight":"float","base_color":"color3","base_diffuse_roughness":"float","base_metalness":"float","specular_weight":"float","specular_color":"color3","specular_roughness":"float","specular_ior":"float","specular_roughness_anisotropy":"float","transmission_weight":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion_scale":"float","subsurface_weight":"float","subsurface_color":"color3","subsurface_radius":"float","subsurface_radius_scale":"color3","subsurface_scatter_anisotropy":"float","fuzz_weight":"float","fuzz_color":"color3","fuzz_roughness":"float","coat_weight":"float","coat_color":"color3","coat_roughness":"float","coat_roughness_anisotropy":"float","coat_ior":"float","coat_darkening":"float","thin_film_weight":"float","thin_film_thickness":"float","thin_film_ior":"float","emission_luminance":"float","emission_color":"color3","geometry_opacity":"float","geometry_thin_walled":"boolean"},"outputs":{"base_out":"float","base_color_out":"color3","diffuse_roughness_out":"float","metalness_out":"float","specular_out":"float","specular_color_out":"color3","specular_roughness_out":"float","specular_IOR_out":"float","specular_anisotropy_out":"float","transmission_out":"float","transmission_color_out":"color3","transmission_depth_out":"float","transmission_scatter_out":"color3","transmission_scatter_anisotropy_out":"float","transmission_dispersion_out":"float","subsurface_out":"float","subsurface_color_out":"color3","subsurface_radius_out":"color3","subsurface_scale_out":"float","subsurface_anisotropy_out":"float","sheen_out":"float","sheen_color_out":"color3","sheen_roughness_out":"float","coat_out":"float","coat_color_out":"color3","coat_roughness_out":"float","coat_anisotropy_out":"float","coat_IOR_out":"float","coat_affect_roughness_out":"float","thin_film_thickness_out":"float","thin_film_IOR_out":"float","emission_out":"float","emission_color_out":"color3","opacity_out":"color3","thin_walled_out":"boolean"}},"ND_standard_surface_to_open_pbr_surface":{"node":"standard_surface_to_open_pbr_surface","inherit":null,"inputs":{"base":"float","base_color":"color3","diffuse_roughness":"float","metalness":"float","specular":"float","specular_color":"color3","specular_roughness":"float","specular_IOR":"float","specular_anisotropy":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion":"float","subsurface":"float","subsurface_color":"color3","subsurface_radius":"color3","subsurface_scale":"float","subsurface_anisotropy":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","coat_anisotropy":"float","coat_IOR":"float","coat_affect_roughness":"float","thin_film_thickness":"float","thin_film_IOR":"float","emission":"float","emission_color":"color3","opacity":"color3","thin_walled":"boolean"},"outputs":{"base_weight_out":"float","base_color_out":"color3","base_diffuse_roughness_out":"float","base_metalness_out":"float","specular_weight_out":"float","specular_color_out":"color3","specular_roughness_out":"float","specular_ior_out":"float","specular_roughness_anisotropy_out":"float","transmission_weight_out":"float","transmission_color_out":"color3","transmission_depth_out":"float","transmission_scatter_out":"color3","transmission_scatter_anisotropy_out":"float","transmission_dispersion_scale_out":"float","subsurface_weight_out":"float","subsurface_color_out":"color3","subsurface_radius_out":"float","subsurface_radius_scale_out":"color3","subsurface_scatter_anisotropy_out":"float","fuzz_weight_out":"float","fuzz_color_out":"color3","fuzz_roughness_out":"float","coat_weight_out":"float","coat_color_out":"color3","coat_roughness_out":"float","coat_roughness_anisotropy_out":"float","coat_ior_out":"float","coat_darkening_out":"float","thin_film_weight_out":"float","thin_film_thickness_out":"float","thin_film_ior_out":"float","emission_luminance_out":"float","emission_color_out":"color3","geometry_opacity_out":"float","geometry_thin_walled_out":"boolean"}},"ND_standard_surface_to_UsdPreviewSurface":{"node":"standard_surface_to_UsdPreviewSurface","inherit":null,"inputs":{"metalness":"float","base":"float","base_color":"color3","specular":"float","specular_color":"color3","specular_IOR":"float","specular_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","subsurface":"float","subsurface_color":"color3","emission":"float","emission_color":"color3","opacity":"color3","normal":"vector3"},"outputs":{"diffuseColor_out":"color3","emissiveColor_out":"color3","metallic_out":"float","roughness_out":"float","clearcoat_out":"float","clearcoatRoughness_out":"float","opacity_out":"float","ior_out":"float","normal_out":"vector3"}},"ND_standard_surface_to_gltf_pbr":{"node":"standard_surface_to_gltf_pbr","inherit":null,"inputs":{"base":"float","base_color":"color3","metalness":"float","specular":"float","specular_color":"color3","specular_anisotropy":"float","specular_rotation":"float","specular_roughness":"float","specular_IOR":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_dispersion":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","emission":"float","emission_color":"color3","normal":"vector3","tangent":"vector3","opacity":"color3","thin_walled":"boolean"},"outputs":{"base_color_out":"color3","metallic_out":"float","roughness_out":"float","specular_out":"float","specular_color_out":"color3","ior_out":"float","anisotropy_strength_out":"float","anisotropy_rotation_out":"float","transmission_out":"float","thickness_out":"float","attenuation_color_out":"color3","attenuation_distance_out":"float","sheen_color_out":"color3","sheen_roughness_out":"float","clearcoat_out":"float","clearcoat_roughness_out":"float","dispersion_out":"float","emissive_out":"color3","emissive_strength_out":"float","normal_out":"vector3","tangent_out":"vector3","alpha_out":"float","alpha_mode_out":"integer"}},"ND_lama_sheen":{"node":"LamaSheen","inherit":null,"inputs":{"color":"color3","roughness":"float","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_lama_sss":{"node":"LamaSSS","inherit":null,"inputs":{"color":"color3","normal":"vector3","sssRadius":"color3","sssScale":"float","sssMode":"integer","sssIOR":"float","sssAnisotropy":"float","sssBleed":"float","sssFollowTopology":"float","sssSubset":"string","sssContinuationRays":"integer","sssUnitLength":"float","mode":"integer","albedoInversionMethod":"integer"},"outputs":{"out":"BSDF"}},"ND_lama_dielectric":{"node":"LamaDielectric","inherit":null,"inputs":{"reflectionTint":"color3","transmissionTint":"color3","fresnelMode":"integer","IOR":"float","reflectivity":"float","roughness":"float","normal":"vector3","anisotropy":"float","direction":"vector3","rotation":"float","absorptionColor":"color3","absorptionRadius":"float","scatterColor":"color3","scatterAnisotropy":"float"},"outputs":{"out":"BSDF"}},"ND_lama_iridescence":{"node":"LamaIridescence","inherit":null,"inputs":{"roughness":"float","anisotropy":"float","anisotropyDirection":"vector3","anisotropyRotation":"float","relativeFilmThickness":"float","minFilmThickness":"float","maxFilmThickness":"float","filmIOR":"float"},"outputs":{"out":"BSDF"}},"ND_lama_diffuse":{"node":"LamaDiffuse","inherit":null,"inputs":{"color":"color3","roughness":"float","normal":"vector3","energyCompensation":"float"},"outputs":{"out":"BSDF"}},"ND_lama_mix_bsdf":{"node":"LamaMix","inherit":null,"inputs":{"material1":"BSDF","material2":"BSDF","mix":"float"},"outputs":{"out":"BSDF"}},"ND_lama_mix_edf":{"node":"LamaMix","inherit":null,"inputs":{"material1":"EDF","material2":"EDF","mix":"float"},"outputs":{"out":"EDF"}},"ND_lama_add_bsdf":{"node":"LamaAdd","inherit":null,"inputs":{"material1":"BSDF","material2":"BSDF","weight1":"float","weight2":"float"},"outputs":{"out":"BSDF"}},"ND_lama_add_edf":{"node":"LamaAdd","inherit":null,"inputs":{"material1":"EDF","material2":"EDF","weight1":"float","weight2":"float"},"outputs":{"out":"EDF"}},"ND_lama_conductor":{"node":"LamaConductor","inherit":null,"inputs":{"tint":"color3","fresnelMode":"integer","IOR":"vector3","extinction":"vector3","reflectivity":"color3","edgeColor":"color3","roughness":"float","normal":"vector3","anisotropy":"float","anisotropyDirection":"vector3","anisotropyRotation":"float"},"outputs":{"out":"BSDF"}},"ND_lama_emission":{"node":"LamaEmission","inherit":null,"inputs":{"color":"color3"},"outputs":{"out":"EDF"}},"ND_lama_surface":{"node":"LamaSurface","inherit":null,"inputs":{"materialFront":"BSDF","materialBack":"BSDF","presence":"float"},"outputs":{"out":"material"}},"ND_lama_generalized_schlick":{"node":"LamaGeneralizedSchlick","inherit":null,"inputs":{"reflectionTint":"color3","transmissionTint":"color3","fresnelMode":"integer","IOR":"vector3","reflectivity":"color3","reflectivity90":"color3","reflectivityProfile":"float","roughness":"float","normal":"vector3","anisotropy":"float","anisotropyDirection":"vector3","anisotropyRotation":"float","absorptionColor":"color3","absorptionRadius":"float","scatterColor":"color3","scatterAnisotropy":"float"},"outputs":{"out":"BSDF"}},"ND_lama_translucent":{"node":"LamaTranslucent","inherit":null,"inputs":{"color":"color3","roughness":"float","normal":"vector3","energyCompensation":"float"},"outputs":{"out":"BSDF"}},"ND_lama_layer_bsdf":{"node":"LamaLayer","inherit":null,"inputs":{"materialTop":"BSDF","materialBase":"BSDF","topMix":"float","topThickness":"float"},"outputs":{"out":"BSDF"}}},"resolved":{"ND_oren_nayar_diffuse_bsdf":{"node":"oren_nayar_diffuse_bsdf","inputs":{"weight":"float","color":"color3","roughness":"float","normal":"vector3","energy_compensation":"boolean"},"outputs":{"out":"BSDF"}},"ND_burley_diffuse_bsdf":{"node":"burley_diffuse_bsdf","inputs":{"weight":"float","color":"color3","roughness":"float","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_translucent_bsdf":{"node":"translucent_bsdf","inputs":{"weight":"float","color":"color3","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_dielectric_bsdf":{"node":"dielectric_bsdf","inputs":{"weight":"float","tint":"color3","ior":"float","roughness":"vector2","retroreflective":"boolean","thinfilm_thickness":"float","thinfilm_ior":"float","normal":"vector3","tangent":"vector3","distribution":"string","scatter_mode":"string"},"outputs":{"out":"BSDF"}},"ND_conductor_bsdf":{"node":"conductor_bsdf","inputs":{"weight":"float","ior":"color3","extinction":"color3","roughness":"vector2","retroreflective":"boolean","thinfilm_thickness":"float","thinfilm_ior":"float","normal":"vector3","tangent":"vector3","distribution":"string"},"outputs":{"out":"BSDF"}},"ND_generalized_schlick_bsdf":{"node":"generalized_schlick_bsdf","inputs":{"weight":"float","color0":"color3","color82":"color3","color90":"color3","exponent":"float","roughness":"vector2","retroreflective":"boolean","thinfilm_thickness":"float","thinfilm_ior":"float","normal":"vector3","tangent":"vector3","distribution":"string","scatter_mode":"string"},"outputs":{"out":"BSDF"}},"ND_subsurface_bsdf":{"node":"subsurface_bsdf","inputs":{"weight":"float","color":"color3","radius":"color3","anisotropy":"float","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_sheen_bsdf":{"node":"sheen_bsdf","inputs":{"weight":"float","color":"color3","roughness":"float","normal":"vector3","mode":"string"},"outputs":{"out":"BSDF"}},"ND_chiang_hair_bsdf":{"node":"chiang_hair_bsdf","inputs":{"tint_R":"color3","tint_TT":"color3","tint_TRT":"color3","ior":"float","roughness_R":"vector2","roughness_TT":"vector2","roughness_TRT":"vector2","cuticle_angle":"float","absorption_coefficient":"vector3","normal":"vector3","curve_direction":"vector3"},"outputs":{"out":"BSDF"}},"ND_uniform_edf":{"node":"uniform_edf","inputs":{"color":"color3"},"outputs":{"out":"EDF"}},"ND_conical_edf":{"node":"conical_edf","inputs":{"color":"color3","normal":"vector3","inner_angle":"float","outer_angle":"float"},"outputs":{"out":"EDF"}},"ND_measured_edf":{"node":"measured_edf","inputs":{"color":"color3","normal":"vector3","file":"filename"},"outputs":{"out":"EDF"}},"ND_generalized_schlick_edf":{"node":"generalized_schlick_edf","inputs":{"color0":"color3","color90":"color3","exponent":"float","base":"EDF"},"outputs":{"out":"EDF"}},"ND_absorption_vdf":{"node":"absorption_vdf","inputs":{"absorption":"vector3"},"outputs":{"out":"VDF"}},"ND_anisotropic_vdf":{"node":"anisotropic_vdf","inputs":{"absorption":"vector3","scattering":"vector3","anisotropy":"float"},"outputs":{"out":"VDF"}},"ND_surface":{"node":"surface","inputs":{"bsdf":"BSDF","edf":"EDF","opacity":"float","thin_walled":"boolean"},"outputs":{"out":"surfaceshader"}},"ND_volume":{"node":"volume","inputs":{"vdf":"VDF","edf":"EDF"},"outputs":{"out":"volumeshader"}},"ND_light":{"node":"light","inputs":{"edf":"EDF","intensity":"float","exposure":"float"},"outputs":{"out":"lightshader"}},"ND_displacement_float":{"node":"displacement","inputs":{"displacement":"float","scale":"float"},"outputs":{"out":"displacementshader"}},"ND_displacement_vector3":{"node":"displacement","inputs":{"displacement":"vector3","scale":"float"},"outputs":{"out":"displacementshader"}},"ND_layer_bsdf":{"node":"layer","inputs":{"top":"BSDF","base":"BSDF"},"outputs":{"out":"BSDF"}},"ND_layer_vdf":{"node":"layer","inputs":{"top":"BSDF","base":"VDF"},"outputs":{"out":"BSDF"}},"ND_mix_bsdf":{"node":"mix","inputs":{"fg":"BSDF","bg":"BSDF","mix":"float"},"outputs":{"out":"BSDF"}},"ND_mix_edf":{"node":"mix","inputs":{"fg":"EDF","bg":"EDF","mix":"float"},"outputs":{"out":"EDF"}},"ND_mix_vdf":{"node":"mix","inputs":{"fg":"VDF","bg":"VDF","mix":"float"},"outputs":{"out":"VDF"}},"ND_add_bsdf":{"node":"add","inputs":{"in1":"BSDF","in2":"BSDF"},"outputs":{"out":"BSDF"}},"ND_add_edf":{"node":"add","inputs":{"in1":"EDF","in2":"EDF"},"outputs":{"out":"EDF"}},"ND_add_vdf":{"node":"add","inputs":{"in1":"VDF","in2":"VDF"},"outputs":{"out":"VDF"}},"ND_multiply_bsdfC":{"node":"multiply","inputs":{"in1":"BSDF","in2":"color3"},"outputs":{"out":"BSDF"}},"ND_multiply_bsdfF":{"node":"multiply","inputs":{"in1":"BSDF","in2":"float"},"outputs":{"out":"BSDF"}},"ND_multiply_edfC":{"node":"multiply","inputs":{"in1":"EDF","in2":"color3"},"outputs":{"out":"EDF"}},"ND_multiply_edfF":{"node":"multiply","inputs":{"in1":"EDF","in2":"float"},"outputs":{"out":"EDF"}},"ND_multiply_vdfC":{"node":"multiply","inputs":{"in1":"VDF","in2":"color3"},"outputs":{"out":"VDF"}},"ND_multiply_vdfF":{"node":"multiply","inputs":{"in1":"VDF","in2":"float"},"outputs":{"out":"VDF"}},"ND_roughness_anisotropy":{"node":"roughness_anisotropy","inputs":{"roughness":"float","anisotropy":"float"},"outputs":{"out":"vector2"}},"ND_roughness_dual":{"node":"roughness_dual","inputs":{"roughness":"vector2"},"outputs":{"out":"vector2"}},"ND_glossiness_anisotropy":{"node":"glossiness_anisotropy","inputs":{"glossiness":"float","anisotropy":"float"},"outputs":{"out":"vector2"}},"ND_blackbody":{"node":"blackbody","inputs":{"temperature":"float"},"outputs":{"out":"color3"}},"ND_artistic_ior":{"node":"artistic_ior","inputs":{"reflectivity":"color3","edge_color":"color3"},"outputs":{"ior":"color3","extinction":"color3"}},"ND_deon_hair_absorption_from_melanin":{"node":"deon_hair_absorption_from_melanin","inputs":{"melanin_concentration":"float","melanin_redness":"float","eumelanin_color":"color3","pheomelanin_color":"color3"},"outputs":{"absorption":"vector3"}},"ND_chiang_hair_absorption_from_color":{"node":"chiang_hair_absorption_from_color","inputs":{"color":"color3","azimuthal_roughness":"float"},"outputs":{"absorption":"vector3"}},"ND_chiang_hair_roughness":{"node":"chiang_hair_roughness","inputs":{"longitudinal":"float","azimuthal":"float","scale_TT":"float","scale_TRT":"float"},"outputs":{"roughness_R":"vector2","roughness_TT":"vector2","roughness_TRT":"vector2"}},"ND_disney_principled":{"node":"disney_principled","inputs":{"baseColor":"color3","metallic":"float","roughness":"float","anisotropic":"float","specular":"float","specularTint":"float","sheen":"float","sheenTint":"float","clearcoat":"float","clearcoatGloss":"float","specTrans":"float","ior":"float","subsurface":"float","subsurfaceDistance":"color3"},"outputs":{"out":"surfaceshader"}},"ND_open_pbr_surface_surfaceshader":{"node":"open_pbr_surface","inputs":{"base_weight":"float","base_color":"color3","base_diffuse_roughness":"float","base_metalness":"float","specular_weight":"float","specular_color":"color3","specular_roughness":"float","specular_ior":"float","specular_roughness_anisotropy":"float","transmission_weight":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion_scale":"float","transmission_dispersion_abbe_number":"float","subsurface_weight":"float","subsurface_color":"color3","subsurface_radius":"float","subsurface_radius_scale":"color3","subsurface_scatter_anisotropy":"float","fuzz_weight":"float","fuzz_color":"color3","fuzz_roughness":"float","coat_weight":"float","coat_color":"color3","coat_roughness":"float","coat_roughness_anisotropy":"float","coat_ior":"float","coat_darkening":"float","thin_film_weight":"float","thin_film_thickness":"float","thin_film_ior":"float","emission_luminance":"float","emission_color":"color3","geometry_opacity":"float","geometry_thin_walled":"boolean","geometry_normal":"vector3","geometry_coat_normal":"vector3","geometry_tangent":"vector3","geometry_coat_tangent":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_open_pbr_anisotropy":{"node":"open_pbr_anisotropy","inputs":{"roughness":"float","anisotropy":"float"},"outputs":{"out":"vector2"}},"ND_UsdPreviewSurface_surfaceshader":{"node":"UsdPreviewSurface","inputs":{"diffuseColor":"color3","emissiveColor":"color3","useSpecularWorkflow":"integer","specularColor":"color3","metallic":"float","roughness":"float","clearcoat":"float","clearcoatRoughness":"float","opacity":"float","opacityMode":"integer","opacityThreshold":"float","ior":"float","normal":"vector3","displacement":"float","occlusion":"float"},"outputs":{"out":"surfaceshader"}},"ND_UsdUVTexture_23":{"node":"UsdUVTexture","inputs":{"file":"filename","st":"vector2","wrapS":"string","wrapT":"string","fallback":"color4","scale":"color4","bias":"color4"},"outputs":{"r":"float","g":"float","b":"float","a":"float","rgb":"color3"}},"ND_UsdUVTexture":{"node":"UsdUVTexture","inputs":{"file":"filename","st":"vector2","wrapS":"string","wrapT":"string","fallback":"color4","scale":"color4","bias":"color4"},"outputs":{"r":"float","g":"float","b":"float","a":"float","rgb":"color3","rgba":"color4"}},"ND_UsdPrimvarReader_integer":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"integer"},"outputs":{"out":"integer"}},"ND_UsdPrimvarReader_boolean":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"boolean"},"outputs":{"out":"boolean"}},"ND_UsdPrimvarReader_string":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"string"},"outputs":{"out":"string"}},"ND_UsdPrimvarReader_filename":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"filename"},"outputs":{"out":"filename"}},"ND_UsdPrimvarReader_float":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"float"},"outputs":{"out":"float"}},"ND_UsdPrimvarReader_vector2":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"vector2"},"outputs":{"out":"vector2"}},"ND_UsdPrimvarReader_vector3":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"vector3"},"outputs":{"out":"vector3"}},"ND_UsdPrimvarReader_vector4":{"node":"UsdPrimvarReader","inputs":{"varname":"string","fallback":"vector4"},"outputs":{"out":"vector4"}},"ND_UsdTransform2d":{"node":"UsdTransform2d","inputs":{"in":"vector2","rotation":"float","scale":"vector2","translation":"vector2"},"outputs":{"out":"vector2"}},"ND_standard_surface_surfaceshader_100":{"node":"standard_surface","inputs":{"base":"float","base_color":"color3","diffuse_roughness":"float","metalness":"float","specular":"float","specular_color":"color3","specular_roughness":"float","specular_IOR":"float","specular_anisotropy":"float","specular_rotation":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion":"float","transmission_extra_roughness":"float","subsurface":"float","subsurface_color":"color3","subsurface_radius":"color3","subsurface_scale":"float","subsurface_anisotropy":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","coat_anisotropy":"float","coat_rotation":"float","coat_IOR":"float","coat_normal":"vector3","coat_affect_color":"float","coat_affect_roughness":"float","thin_film_thickness":"float","thin_film_IOR":"float","emission":"float","emission_color":"color3","opacity":"color3","thin_walled":"boolean","normal":"vector3","tangent":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_standard_surface_surfaceshader":{"node":"standard_surface","inputs":{"base":"float","base_color":"color3","diffuse_roughness":"float","metalness":"float","specular":"float","specular_color":"color3","specular_roughness":"float","specular_IOR":"float","specular_anisotropy":"float","specular_rotation":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion":"float","transmission_extra_roughness":"float","subsurface":"float","subsurface_color":"color3","subsurface_radius":"color3","subsurface_scale":"float","subsurface_anisotropy":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","coat_anisotropy":"float","coat_rotation":"float","coat_IOR":"float","coat_normal":"vector3","coat_affect_color":"float","coat_affect_roughness":"float","thin_film_thickness":"float","thin_film_IOR":"float","emission":"float","emission_color":"color3","opacity":"color3","thin_walled":"boolean","normal":"vector3","tangent":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_gltf_pbr_surfaceshader":{"node":"gltf_pbr","inputs":{"base_color":"color3","metallic":"float","roughness":"float","normal":"vector3","tangent":"vector3","occlusion":"float","transmission":"float","specular":"float","specular_color":"color3","ior":"float","alpha":"float","alpha_mode":"integer","alpha_cutoff":"float","iridescence":"float","iridescence_ior":"float","iridescence_thickness":"float","sheen_color":"color3","sheen_roughness":"float","clearcoat":"float","clearcoat_roughness":"float","clearcoat_normal":"vector3","emissive":"color3","emissive_strength":"float","thickness":"float","attenuation_distance":"float","attenuation_color":"color3","anisotropy_strength":"float","anisotropy_rotation":"float","dispersion":"float"},"outputs":{"out":"surfaceshader"}},"ND_gltf_colorimage":{"node":"gltf_colorimage","inputs":{"file":"filename","default":"color4","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string","color":"color4","geomcolor":"color4"},"outputs":{"outcolor":"color3","outa":"float"}},"ND_gltf_image_color3_color3_1_0":{"node":"gltf_image","inputs":{"file":"filename","factor":"color3","default":"color3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"color3"}},"ND_gltf_image_color4_color4_1_0":{"node":"gltf_image","inputs":{"file":"filename","factor":"color4","default":"color4","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"color4"}},"ND_gltf_image_float_float_1_0":{"node":"gltf_image","inputs":{"file":"filename","factor":"float","default":"float","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"float"}},"ND_gltf_image_vector3_vector3_1_0":{"node":"gltf_image","inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"vector3"}},"ND_gltf_normalmap_vector3_1_0":{"node":"gltf_normalmap","inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string"},"outputs":{"out":"vector3"}},"ND_gltf_iridescence_thickness_float_1_0":{"node":"gltf_iridescence_thickness","inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","thicknessMin":"float","thicknessMax":"float"},"outputs":{"out":"float"}},"ND_gltf_anisotropy_image":{"node":"gltf_anisotropy_image","inputs":{"file":"filename","default":"vector3","texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer","uaddressmode":"string","vaddressmode":"string","filtertype":"string","anisotropy_strength":"float","anisotropy_rotation":"float"},"outputs":{"anisotropy_strength_out":"float","anisotropy_rotation_out":"float"}},"ND_viewdirection_vector3":{"node":"viewdirection","inputs":{"space":"string"},"outputs":{"out":"vector3"}},"ND_facingratio_float":{"node":"facingratio","inputs":{"viewdirection":"vector3","normal":"vector3","faceforward":"boolean","invert":"boolean"},"outputs":{"out":"float"}},"ND_gooch_shade":{"node":"gooch_shade","inputs":{"warm_color":"color3","cool_color":"color3","specular_intensity":"float","shininess":"float","light_direction":"vector3"},"outputs":{"out":"color3"}},"ND_g18_rec709_to_lin_rec709_color3":{"node":"g18_rec709_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_g18_rec709_to_lin_rec709_color4":{"node":"g18_rec709_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_g22_rec709_to_lin_rec709_color3":{"node":"g22_rec709_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_g22_rec709_to_lin_rec709_color4":{"node":"g22_rec709_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_rec709_display_to_lin_rec709_color3":{"node":"rec709_display_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_rec709_display_to_lin_rec709_color4":{"node":"rec709_display_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_acescg_to_lin_rec709_color3":{"node":"acescg_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_acescg_to_lin_rec709_color4":{"node":"acescg_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_g22_ap1_to_lin_rec709_color3":{"node":"g22_ap1_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_g22_ap1_to_lin_rec709_color4":{"node":"g22_ap1_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_srgb_texture_to_lin_rec709_color3":{"node":"srgb_texture_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_srgb_texture_to_lin_rec709_color4":{"node":"srgb_texture_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_lin_adobergb_to_lin_rec709_color3":{"node":"lin_adobergb_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_lin_adobergb_to_lin_rec709_color4":{"node":"lin_adobergb_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_adobergb_to_lin_rec709_color3":{"node":"adobergb_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_adobergb_to_lin_rec709_color4":{"node":"adobergb_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_srgb_displayp3_to_lin_rec709_color3":{"node":"srgb_displayp3_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_srgb_displayp3_to_lin_rec709_color4":{"node":"srgb_displayp3_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_lin_displayp3_to_lin_rec709_color3":{"node":"lin_displayp3_to_lin_rec709","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_lin_displayp3_to_lin_rec709_color4":{"node":"lin_displayp3_to_lin_rec709","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_surfacematerial":{"node":"surfacematerial","inputs":{"surfaceshader":"surfaceshader","backsurfaceshader":"surfaceshader","displacementshader":"displacementshader"},"outputs":{"out":"material"}},"ND_volumematerial":{"node":"volumematerial","inputs":{"volumeshader":"volumeshader"},"outputs":{"out":"material"}},"ND_surface_unlit":{"node":"surface_unlit","inputs":{"emission":"float","emission_color":"color3","transmission":"float","transmission_color":"color3","opacity":"float"},"outputs":{"out":"surfaceshader"}},"ND_image_float":{"node":"image","inputs":{"file":"filename","layer":"string","default":"float","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"float"}},"ND_image_color3":{"node":"image","inputs":{"file":"filename","layer":"string","default":"color3","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color3"}},"ND_image_color4":{"node":"image","inputs":{"file":"filename","layer":"string","default":"color4","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color4"}},"ND_image_vector2":{"node":"image","inputs":{"file":"filename","layer":"string","default":"vector2","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector2"}},"ND_image_vector3":{"node":"image","inputs":{"file":"filename","layer":"string","default":"vector3","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector3"}},"ND_image_vector4":{"node":"image","inputs":{"file":"filename","layer":"string","default":"vector4","texcoord":"vector2","uaddressmode":"string","vaddressmode":"string","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector4"}},"ND_tiledimage_float":{"node":"tiledimage","inputs":{"file":"filename","default":"float","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"float"}},"ND_tiledimage_color3":{"node":"tiledimage","inputs":{"file":"filename","default":"color3","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color3"}},"ND_tiledimage_color4":{"node":"tiledimage","inputs":{"file":"filename","default":"color4","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color4"}},"ND_tiledimage_vector2":{"node":"tiledimage","inputs":{"file":"filename","default":"vector2","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector2"}},"ND_tiledimage_vector3":{"node":"tiledimage","inputs":{"file":"filename","default":"vector3","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector3"}},"ND_tiledimage_vector4":{"node":"tiledimage","inputs":{"file":"filename","default":"vector4","texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","realworldimagesize":"vector2","realworldtilesize":"vector2","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector4"}},"ND_latlongimage":{"node":"latlongimage","inputs":{"file":"filename","default":"color3","viewdir":"vector3","rotation":"float"},"outputs":{"out":"color3"}},"ND_hextiledimage_color3":{"node":"hextiledimage","inputs":{"file":"filename","default":"color3","texcoord":"vector2","tiling":"vector2","rotation":"float","rotationrange":"vector2","scale":"float","scalerange":"vector2","offset":"float","offsetrange":"vector2","falloff":"float","falloffcontrast":"float","lumacoeffs":"color3"},"outputs":{"out":"color3"}},"ND_hextiledimage_color4":{"node":"hextiledimage","inputs":{"file":"filename","default":"color4","texcoord":"vector2","tiling":"vector2","rotation":"float","rotationrange":"vector2","scale":"float","scalerange":"vector2","offset":"float","offsetrange":"vector2","falloff":"float","falloffcontrast":"float","lumacoeffs":"color3"},"outputs":{"out":"color4"}},"ND_triplanarprojection_float":{"node":"triplanarprojection","inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"float","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"float"}},"ND_triplanarprojection_color3":{"node":"triplanarprojection","inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"color3","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color3"}},"ND_triplanarprojection_color4":{"node":"triplanarprojection","inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"color4","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"color4"}},"ND_triplanarprojection_vector2":{"node":"triplanarprojection","inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"vector2","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector2"}},"ND_triplanarprojection_vector3":{"node":"triplanarprojection","inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"vector3","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector3"}},"ND_triplanarprojection_vector4":{"node":"triplanarprojection","inputs":{"filex":"filename","filey":"filename","filez":"filename","layerx":"string","layery":"string","layerz":"string","default":"vector4","position":"vector3","normal":"vector3","upaxis":"integer","blend":"float","filtertype":"string","framerange":"string","frameoffset":"integer","frameendaction":"string"},"outputs":{"out":"vector4"}},"ND_constant_float":{"node":"constant","inputs":{"value":"float"},"outputs":{"out":"float"}},"ND_constant_color3":{"node":"constant","inputs":{"value":"color3"},"outputs":{"out":"color3"}},"ND_constant_color4":{"node":"constant","inputs":{"value":"color4"},"outputs":{"out":"color4"}},"ND_constant_vector2":{"node":"constant","inputs":{"value":"vector2"},"outputs":{"out":"vector2"}},"ND_constant_vector3":{"node":"constant","inputs":{"value":"vector3"},"outputs":{"out":"vector3"}},"ND_constant_vector4":{"node":"constant","inputs":{"value":"vector4"},"outputs":{"out":"vector4"}},"ND_constant_boolean":{"node":"constant","inputs":{"value":"boolean"},"outputs":{"out":"boolean"}},"ND_constant_integer":{"node":"constant","inputs":{"value":"integer"},"outputs":{"out":"integer"}},"ND_constant_matrix33":{"node":"constant","inputs":{"value":"matrix33"},"outputs":{"out":"matrix33"}},"ND_constant_matrix44":{"node":"constant","inputs":{"value":"matrix44"},"outputs":{"out":"matrix44"}},"ND_constant_string":{"node":"constant","inputs":{"value":"string"},"outputs":{"out":"string"}},"ND_constant_filename":{"node":"constant","inputs":{"value":"filename"},"outputs":{"out":"filename"}},"ND_ramp":{"node":"ramp","inputs":{"texcoord":"vector2","type":"integer","interpolation":"integer","num_intervals":"integer","interval1":"float","color1":"color4","interval2":"float","color2":"color4","interval3":"float","color3":"color4","interval4":"float","color4":"color4","interval5":"float","color5":"color4","interval6":"float","color6":"color4","interval7":"float","color7":"color4","interval8":"float","color8":"color4","interval9":"float","color9":"color4","interval10":"float","color10":"color4"},"outputs":{"out":"color4"}},"ND_ramp_gradient":{"node":"ramp_gradient","inputs":{"x":"float","interval1":"float","interval2":"float","color1":"color4","color2":"color4","interpolation":"integer","prev_color":"color4","interval_num":"integer","num_intervals":"integer"},"outputs":{"out":"color4"}},"ND_ramplr_float":{"node":"ramplr","inputs":{"valuel":"float","valuer":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_ramplr_color3":{"node":"ramplr","inputs":{"valuel":"color3","valuer":"color3","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_ramplr_color4":{"node":"ramplr","inputs":{"valuel":"color4","valuer":"color4","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_ramplr_vector2":{"node":"ramplr","inputs":{"valuel":"vector2","valuer":"vector2","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_ramplr_vector3":{"node":"ramplr","inputs":{"valuel":"vector3","valuer":"vector3","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_ramplr_vector4":{"node":"ramplr","inputs":{"valuel":"vector4","valuer":"vector4","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_ramptb_float":{"node":"ramptb","inputs":{"valuet":"float","valueb":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_ramptb_color3":{"node":"ramptb","inputs":{"valuet":"color3","valueb":"color3","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_ramptb_color4":{"node":"ramptb","inputs":{"valuet":"color4","valueb":"color4","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_ramptb_vector2":{"node":"ramptb","inputs":{"valuet":"vector2","valueb":"vector2","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_ramptb_vector3":{"node":"ramptb","inputs":{"valuet":"vector3","valueb":"vector3","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_ramptb_vector4":{"node":"ramptb","inputs":{"valuet":"vector4","valueb":"vector4","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_ramp4_float":{"node":"ramp4","inputs":{"valuetl":"float","valuetr":"float","valuebl":"float","valuebr":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_ramp4_color3":{"node":"ramp4","inputs":{"valuetl":"color3","valuetr":"color3","valuebl":"color3","valuebr":"color3","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_ramp4_color4":{"node":"ramp4","inputs":{"valuetl":"color4","valuetr":"color4","valuebl":"color4","valuebr":"color4","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_ramp4_vector2":{"node":"ramp4","inputs":{"valuetl":"vector2","valuetr":"vector2","valuebl":"vector2","valuebr":"vector2","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_ramp4_vector3":{"node":"ramp4","inputs":{"valuetl":"vector3","valuetr":"vector3","valuebl":"vector3","valuebr":"vector3","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_ramp4_vector4":{"node":"ramp4","inputs":{"valuetl":"vector4","valuetr":"vector4","valuebl":"vector4","valuebr":"vector4","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_splitlr_float":{"node":"splitlr","inputs":{"valuel":"float","valuer":"float","center":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_splitlr_color3":{"node":"splitlr","inputs":{"valuel":"color3","valuer":"color3","center":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_splitlr_color4":{"node":"splitlr","inputs":{"valuel":"color4","valuer":"color4","center":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_splitlr_vector2":{"node":"splitlr","inputs":{"valuel":"vector2","valuer":"vector2","center":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_splitlr_vector3":{"node":"splitlr","inputs":{"valuel":"vector3","valuer":"vector3","center":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_splitlr_vector4":{"node":"splitlr","inputs":{"valuel":"vector4","valuer":"vector4","center":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_splittb_float":{"node":"splittb","inputs":{"valuet":"float","valueb":"float","center":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_splittb_color3":{"node":"splittb","inputs":{"valuet":"color3","valueb":"color3","center":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_splittb_color4":{"node":"splittb","inputs":{"valuet":"color4","valueb":"color4","center":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_splittb_vector2":{"node":"splittb","inputs":{"valuet":"vector2","valueb":"vector2","center":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_splittb_vector3":{"node":"splittb","inputs":{"valuet":"vector3","valueb":"vector3","center":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_splittb_vector4":{"node":"splittb","inputs":{"valuet":"vector4","valueb":"vector4","center":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_noise2d_float":{"node":"noise2d","inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_noise2d_color3":{"node":"noise2d","inputs":{"amplitude":"vector3","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_noise2d_color4":{"node":"noise2d","inputs":{"amplitude":"vector4","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_noise2d_vector2":{"node":"noise2d","inputs":{"amplitude":"vector2","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_noise2d_vector3":{"node":"noise2d","inputs":{"amplitude":"vector3","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_noise2d_vector4":{"node":"noise2d","inputs":{"amplitude":"vector4","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_noise2d_color3FA":{"node":"noise2d","inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_noise2d_color4FA":{"node":"noise2d","inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_noise2d_vector2FA":{"node":"noise2d","inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_noise2d_vector3FA":{"node":"noise2d","inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_noise2d_vector4FA":{"node":"noise2d","inputs":{"amplitude":"float","pivot":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_noise3d_float":{"node":"noise3d","inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"float"}},"ND_noise3d_color3":{"node":"noise3d","inputs":{"amplitude":"vector3","pivot":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_noise3d_color4":{"node":"noise3d","inputs":{"amplitude":"vector4","pivot":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_noise3d_vector2":{"node":"noise3d","inputs":{"amplitude":"vector2","pivot":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_noise3d_vector3":{"node":"noise3d","inputs":{"amplitude":"vector3","pivot":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_noise3d_vector4":{"node":"noise3d","inputs":{"amplitude":"vector4","pivot":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_noise3d_color3FA":{"node":"noise3d","inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_noise3d_color4FA":{"node":"noise3d","inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_noise3d_vector2FA":{"node":"noise3d","inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_noise3d_vector3FA":{"node":"noise3d","inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_noise3d_vector4FA":{"node":"noise3d","inputs":{"amplitude":"float","pivot":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_fractal2d_float":{"node":"fractal2d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"float"}},"ND_fractal2d_color3":{"node":"fractal2d","inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_fractal2d_color4":{"node":"fractal2d","inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_fractal2d_vector2":{"node":"fractal2d","inputs":{"amplitude":"vector2","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_fractal2d_vector3":{"node":"fractal2d","inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_fractal2d_vector4":{"node":"fractal2d","inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_fractal2d_color3FA":{"node":"fractal2d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_fractal2d_color4FA":{"node":"fractal2d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"color4"}},"ND_fractal2d_vector2FA":{"node":"fractal2d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector2"}},"ND_fractal2d_vector3FA":{"node":"fractal2d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_fractal2d_vector4FA":{"node":"fractal2d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","texcoord":"vector2"},"outputs":{"out":"vector4"}},"ND_fractal3d_float":{"node":"fractal3d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"float"}},"ND_fractal3d_color3":{"node":"fractal3d","inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_fractal3d_color4":{"node":"fractal3d","inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_fractal3d_vector2":{"node":"fractal3d","inputs":{"amplitude":"vector2","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_fractal3d_vector3":{"node":"fractal3d","inputs":{"amplitude":"vector3","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_fractal3d_vector4":{"node":"fractal3d","inputs":{"amplitude":"vector4","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_fractal3d_color3FA":{"node":"fractal3d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color3"}},"ND_fractal3d_color4FA":{"node":"fractal3d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"color4"}},"ND_fractal3d_vector2FA":{"node":"fractal3d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector2"}},"ND_fractal3d_vector3FA":{"node":"fractal3d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector3"}},"ND_fractal3d_vector4FA":{"node":"fractal3d","inputs":{"amplitude":"float","octaves":"integer","lacunarity":"float","diminish":"float","position":"vector3"},"outputs":{"out":"vector4"}},"ND_cellnoise2d_float":{"node":"cellnoise2d","inputs":{"texcoord":"vector2"},"outputs":{"out":"float"}},"ND_cellnoise3d_float":{"node":"cellnoise3d","inputs":{"position":"vector3"},"outputs":{"out":"float"}},"ND_worleynoise2d_float":{"node":"worleynoise2d","inputs":{"texcoord":"vector2","jitter":"float","style":"integer"},"outputs":{"out":"float"}},"ND_worleynoise2d_vector2":{"node":"worleynoise2d","inputs":{"texcoord":"vector2","jitter":"float","style":"integer"},"outputs":{"out":"vector2"}},"ND_worleynoise2d_vector3":{"node":"worleynoise2d","inputs":{"texcoord":"vector2","jitter":"float","style":"integer"},"outputs":{"out":"vector3"}},"ND_worleynoise3d_float":{"node":"worleynoise3d","inputs":{"position":"vector3","jitter":"float","style":"integer"},"outputs":{"out":"float"}},"ND_worleynoise3d_vector2":{"node":"worleynoise3d","inputs":{"position":"vector3","jitter":"float","style":"integer"},"outputs":{"out":"vector2"}},"ND_worleynoise3d_vector3":{"node":"worleynoise3d","inputs":{"position":"vector3","jitter":"float","style":"integer"},"outputs":{"out":"vector3"}},"ND_unifiednoise2d_float":{"node":"unifiednoise2d","inputs":{"texcoord":"vector2","freq":"vector2","offset":"vector2","jitter":"float","outmin":"float","outmax":"float","clampoutput":"boolean","octaves":"integer","lacunarity":"float","diminish":"float","type":"integer","style":"integer"},"outputs":{"out":"float"}},"ND_unifiednoise3d_float":{"node":"unifiednoise3d","inputs":{"position":"vector3","freq":"vector3","offset":"vector3","jitter":"float","outmin":"float","outmax":"float","clampoutput":"boolean","octaves":"integer","lacunarity":"float","diminish":"float","type":"integer","style":"integer"},"outputs":{"out":"float"}},"ND_flake2d":{"node":"flake2d","inputs":{"size":"float","roughness":"float","coverage":"float","texcoord":"vector2","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"id":"integer","rand":"float","presence":"float","flakenormal":"vector3"}},"ND_flake3d":{"node":"flake3d","inputs":{"size":"float","roughness":"float","coverage":"float","position":"vector3","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"id":"integer","rand":"float","presence":"float","flakenormal":"vector3"}},"ND_randomfloat_float":{"node":"randomfloat","inputs":{"in":"float","min":"float","max":"float","seed":"integer"},"outputs":{"out":"float"}},"ND_randomfloat_integer":{"node":"randomfloat","inputs":{"in":"integer","min":"float","max":"float","seed":"integer"},"outputs":{"out":"float"}},"ND_randomcolor_float":{"node":"randomcolor","inputs":{"in":"float","huelow":"float","huehigh":"float","saturationlow":"float","saturationhigh":"float","brightnesslow":"float","brightnesshigh":"float","seed":"integer"},"outputs":{"out":"color3"}},"ND_randomcolor_integer":{"node":"randomcolor","inputs":{"in":"integer","huelow":"float","huehigh":"float","saturationlow":"float","saturationhigh":"float","brightnesslow":"float","brightnesshigh":"float","seed":"integer"},"outputs":{"out":"color3"}},"ND_checkerboard_color3":{"node":"checkerboard","inputs":{"color1":"color3","color2":"color3","uvtiling":"vector2","uvoffset":"vector2","texcoord":"vector2"},"outputs":{"out":"color3"}},"ND_line_float":{"node":"line","inputs":{"texcoord":"vector2","center":"vector2","radius":"float","point1":"vector2","point2":"vector2"},"outputs":{"out":"float"}},"ND_circle_float":{"node":"circle","inputs":{"texcoord":"vector2","center":"vector2","radius":"float"},"outputs":{"out":"float"}},"ND_cloverleaf_float":{"node":"cloverleaf","inputs":{"texcoord":"vector2","center":"vector2","radius":"float"},"outputs":{"out":"float"}},"ND_hexagon_float":{"node":"hexagon","inputs":{"texcoord":"vector2","center":"vector2","radius":"float"},"outputs":{"out":"float"}},"ND_grid_color3":{"node":"grid","inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","thickness":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_crosshatch_color3":{"node":"crosshatch","inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","thickness":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_tiledcircles_color3":{"node":"tiledcircles","inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","size":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_tiledcloverleafs_color3":{"node":"tiledcloverleafs","inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","size":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_tiledhexagons_color3":{"node":"tiledhexagons","inputs":{"texcoord":"vector2","uvtiling":"vector2","uvoffset":"vector2","size":"float","staggered":"boolean"},"outputs":{"out":"color3"}},"ND_position_vector3":{"node":"position","inputs":{"space":"string"},"outputs":{"out":"vector3"}},"ND_normal_vector3":{"node":"normal","inputs":{"space":"string"},"outputs":{"out":"vector3"}},"ND_tangent_vector3":{"node":"tangent","inputs":{"space":"string","index":"integer"},"outputs":{"out":"vector3"}},"ND_bitangent_vector3":{"node":"bitangent","inputs":{"space":"string","index":"integer"},"outputs":{"out":"vector3"}},"ND_texcoord_vector2":{"node":"texcoord","inputs":{"index":"integer"},"outputs":{"out":"vector2"}},"ND_texcoord_vector3":{"node":"texcoord","inputs":{"index":"integer"},"outputs":{"out":"vector3"}},"ND_geomcolor_float":{"node":"geomcolor","inputs":{"index":"integer"},"outputs":{"out":"float"}},"ND_geomcolor_color3":{"node":"geomcolor","inputs":{"index":"integer"},"outputs":{"out":"color3"}},"ND_geomcolor_color4":{"node":"geomcolor","inputs":{"index":"integer"},"outputs":{"out":"color4"}},"ND_geompropvalue_integer":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"integer"},"outputs":{"out":"integer"}},"ND_geompropvalue_boolean":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"boolean"},"outputs":{"out":"boolean"}},"ND_geompropvalue_float":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"float"},"outputs":{"out":"float"}},"ND_geompropvalue_color3":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"color3"},"outputs":{"out":"color3"}},"ND_geompropvalue_color4":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"color4"},"outputs":{"out":"color4"}},"ND_geompropvalue_vector2":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"vector2"},"outputs":{"out":"vector2"}},"ND_geompropvalue_vector3":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"vector3"},"outputs":{"out":"vector3"}},"ND_geompropvalue_vector4":{"node":"geompropvalue","inputs":{"geomprop":"string","default":"vector4"},"outputs":{"out":"vector4"}},"ND_geompropvalueuniform_string":{"node":"geompropvalueuniform","inputs":{"geomprop":"string","default":"string"},"outputs":{"out":"string"}},"ND_geompropvalueuniform_filename":{"node":"geompropvalueuniform","inputs":{"geomprop":"string","default":"filename"},"outputs":{"out":"filename"}},"ND_bump_vector3":{"node":"bump","inputs":{"height":"float","scale":"float","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_frame_float":{"node":"frame","inputs":{},"outputs":{"out":"float"}},"ND_time_float":{"node":"time","inputs":{"fps":"float"},"outputs":{"out":"float"}},"ND_add_float":{"node":"add","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_add_integer":{"node":"add","inputs":{"in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_add_color3":{"node":"add","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_add_color4":{"node":"add","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_add_vector2":{"node":"add","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_add_vector3":{"node":"add","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_add_vector4":{"node":"add","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_add_matrix33":{"node":"add","inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_add_matrix44":{"node":"add","inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_add_color3FA":{"node":"add","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_add_color4FA":{"node":"add","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_add_vector2FA":{"node":"add","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_add_vector3FA":{"node":"add","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_add_vector4FA":{"node":"add","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_add_matrix33FA":{"node":"add","inputs":{"in1":"matrix33","in2":"float"},"outputs":{"out":"matrix33"}},"ND_add_matrix44FA":{"node":"add","inputs":{"in1":"matrix44","in2":"float"},"outputs":{"out":"matrix44"}},"ND_subtract_float":{"node":"subtract","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_subtract_integer":{"node":"subtract","inputs":{"in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_subtract_color3":{"node":"subtract","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_subtract_color4":{"node":"subtract","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_subtract_vector2":{"node":"subtract","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_subtract_vector3":{"node":"subtract","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_subtract_vector4":{"node":"subtract","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_subtract_matrix33":{"node":"subtract","inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_subtract_matrix44":{"node":"subtract","inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_subtract_color3FA":{"node":"subtract","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_subtract_color4FA":{"node":"subtract","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_subtract_vector2FA":{"node":"subtract","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_subtract_vector3FA":{"node":"subtract","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_subtract_vector4FA":{"node":"subtract","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_subtract_matrix33FA":{"node":"subtract","inputs":{"in1":"matrix33","in2":"float"},"outputs":{"out":"matrix33"}},"ND_subtract_matrix44FA":{"node":"subtract","inputs":{"in1":"matrix44","in2":"float"},"outputs":{"out":"matrix44"}},"ND_multiply_float":{"node":"multiply","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_multiply_color3":{"node":"multiply","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_multiply_color4":{"node":"multiply","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_multiply_vector2":{"node":"multiply","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_multiply_vector3":{"node":"multiply","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_multiply_vector4":{"node":"multiply","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_multiply_matrix33":{"node":"multiply","inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_multiply_matrix44":{"node":"multiply","inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_multiply_color3FA":{"node":"multiply","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_multiply_color4FA":{"node":"multiply","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_multiply_vector2FA":{"node":"multiply","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_multiply_vector3FA":{"node":"multiply","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_multiply_vector4FA":{"node":"multiply","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_divide_float":{"node":"divide","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_divide_color3":{"node":"divide","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_divide_color4":{"node":"divide","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_divide_vector2":{"node":"divide","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_divide_vector3":{"node":"divide","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_divide_vector4":{"node":"divide","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_divide_matrix33":{"node":"divide","inputs":{"in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_divide_matrix44":{"node":"divide","inputs":{"in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_divide_color3FA":{"node":"divide","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_divide_color4FA":{"node":"divide","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_divide_vector2FA":{"node":"divide","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_divide_vector3FA":{"node":"divide","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_divide_vector4FA":{"node":"divide","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_modulo_float":{"node":"modulo","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_modulo_color3":{"node":"modulo","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_modulo_color4":{"node":"modulo","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_modulo_vector2":{"node":"modulo","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_modulo_vector3":{"node":"modulo","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_modulo_vector4":{"node":"modulo","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_modulo_color3FA":{"node":"modulo","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_modulo_color4FA":{"node":"modulo","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_modulo_vector2FA":{"node":"modulo","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_modulo_vector3FA":{"node":"modulo","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_modulo_vector4FA":{"node":"modulo","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_fract_float":{"node":"fract","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_fract_color3":{"node":"fract","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_fract_color4":{"node":"fract","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_fract_vector2":{"node":"fract","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_fract_vector3":{"node":"fract","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_fract_vector4":{"node":"fract","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_invert_float":{"node":"invert","inputs":{"in":"float","amount":"float"},"outputs":{"out":"float"}},"ND_invert_color3":{"node":"invert","inputs":{"in":"color3","amount":"color3"},"outputs":{"out":"color3"}},"ND_invert_color4":{"node":"invert","inputs":{"in":"color4","amount":"color4"},"outputs":{"out":"color4"}},"ND_invert_vector2":{"node":"invert","inputs":{"in":"vector2","amount":"vector2"},"outputs":{"out":"vector2"}},"ND_invert_vector3":{"node":"invert","inputs":{"in":"vector3","amount":"vector3"},"outputs":{"out":"vector3"}},"ND_invert_vector4":{"node":"invert","inputs":{"in":"vector4","amount":"vector4"},"outputs":{"out":"vector4"}},"ND_invert_color3FA":{"node":"invert","inputs":{"in":"color3","amount":"float"},"outputs":{"out":"color3"}},"ND_invert_color4FA":{"node":"invert","inputs":{"in":"color4","amount":"float"},"outputs":{"out":"color4"}},"ND_invert_vector2FA":{"node":"invert","inputs":{"in":"vector2","amount":"float"},"outputs":{"out":"vector2"}},"ND_invert_vector3FA":{"node":"invert","inputs":{"in":"vector3","amount":"float"},"outputs":{"out":"vector3"}},"ND_invert_vector4FA":{"node":"invert","inputs":{"in":"vector4","amount":"float"},"outputs":{"out":"vector4"}},"ND_absval_float":{"node":"absval","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_absval_color3":{"node":"absval","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_absval_color4":{"node":"absval","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_absval_vector2":{"node":"absval","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_absval_vector3":{"node":"absval","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_absval_vector4":{"node":"absval","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_floor_float":{"node":"floor","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_floor_color3":{"node":"floor","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_floor_color4":{"node":"floor","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_floor_vector2":{"node":"floor","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_floor_vector3":{"node":"floor","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_floor_vector4":{"node":"floor","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_floor_integer":{"node":"floor","inputs":{"in":"float"},"outputs":{"out":"integer"}},"ND_ceil_float":{"node":"ceil","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_ceil_color3":{"node":"ceil","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_ceil_color4":{"node":"ceil","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_ceil_vector2":{"node":"ceil","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_ceil_vector3":{"node":"ceil","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_ceil_vector4":{"node":"ceil","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_ceil_integer":{"node":"ceil","inputs":{"in":"float"},"outputs":{"out":"integer"}},"ND_round_float":{"node":"round","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_round_color3":{"node":"round","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_round_color4":{"node":"round","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_round_vector2":{"node":"round","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_round_vector3":{"node":"round","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_round_vector4":{"node":"round","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_round_integer":{"node":"round","inputs":{"in":"float"},"outputs":{"out":"integer"}},"ND_power_float":{"node":"power","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_power_color3":{"node":"power","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_power_color4":{"node":"power","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_power_vector2":{"node":"power","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_power_vector3":{"node":"power","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_power_vector4":{"node":"power","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_power_color3FA":{"node":"power","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_power_color4FA":{"node":"power","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_power_vector2FA":{"node":"power","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_power_vector3FA":{"node":"power","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_power_vector4FA":{"node":"power","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_safepower_float":{"node":"safepower","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_safepower_color3":{"node":"safepower","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_safepower_color4":{"node":"safepower","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_safepower_vector2":{"node":"safepower","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_safepower_vector3":{"node":"safepower","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_safepower_vector4":{"node":"safepower","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_safepower_color3FA":{"node":"safepower","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_safepower_color4FA":{"node":"safepower","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_safepower_vector2FA":{"node":"safepower","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_safepower_vector3FA":{"node":"safepower","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_safepower_vector4FA":{"node":"safepower","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_sin_float":{"node":"sin","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_cos_float":{"node":"cos","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_tan_float":{"node":"tan","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_asin_float":{"node":"asin","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_acos_float":{"node":"acos","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_atan2_float":{"node":"atan2","inputs":{"iny":"float","inx":"float"},"outputs":{"out":"float"}},"ND_sin_vector2":{"node":"sin","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_cos_vector2":{"node":"cos","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_tan_vector2":{"node":"tan","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_asin_vector2":{"node":"asin","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_acos_vector2":{"node":"acos","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_atan2_vector2":{"node":"atan2","inputs":{"iny":"vector2","inx":"vector2"},"outputs":{"out":"vector2"}},"ND_sin_vector3":{"node":"sin","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_cos_vector3":{"node":"cos","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_tan_vector3":{"node":"tan","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_asin_vector3":{"node":"asin","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_acos_vector3":{"node":"acos","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_atan2_vector3":{"node":"atan2","inputs":{"iny":"vector3","inx":"vector3"},"outputs":{"out":"vector3"}},"ND_sin_vector4":{"node":"sin","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_cos_vector4":{"node":"cos","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_tan_vector4":{"node":"tan","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_asin_vector4":{"node":"asin","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_acos_vector4":{"node":"acos","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_atan2_vector4":{"node":"atan2","inputs":{"iny":"vector4","inx":"vector4"},"outputs":{"out":"vector4"}},"ND_sqrt_float":{"node":"sqrt","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_ln_float":{"node":"ln","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_exp_float":{"node":"exp","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_sqrt_vector2":{"node":"sqrt","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_ln_vector2":{"node":"ln","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_exp_vector2":{"node":"exp","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_sqrt_vector3":{"node":"sqrt","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_ln_vector3":{"node":"ln","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_exp_vector3":{"node":"exp","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_sqrt_vector4":{"node":"sqrt","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_ln_vector4":{"node":"ln","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_exp_vector4":{"node":"exp","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_sign_float":{"node":"sign","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_sign_color3":{"node":"sign","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_sign_color4":{"node":"sign","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_sign_vector2":{"node":"sign","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_sign_vector3":{"node":"sign","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_sign_vector4":{"node":"sign","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_clamp_float":{"node":"clamp","inputs":{"in":"float","low":"float","high":"float"},"outputs":{"out":"float"}},"ND_clamp_color3":{"node":"clamp","inputs":{"in":"color3","low":"color3","high":"color3"},"outputs":{"out":"color3"}},"ND_clamp_color4":{"node":"clamp","inputs":{"in":"color4","low":"color4","high":"color4"},"outputs":{"out":"color4"}},"ND_clamp_vector2":{"node":"clamp","inputs":{"in":"vector2","low":"vector2","high":"vector2"},"outputs":{"out":"vector2"}},"ND_clamp_vector3":{"node":"clamp","inputs":{"in":"vector3","low":"vector3","high":"vector3"},"outputs":{"out":"vector3"}},"ND_clamp_vector4":{"node":"clamp","inputs":{"in":"vector4","low":"vector4","high":"vector4"},"outputs":{"out":"vector4"}},"ND_clamp_color3FA":{"node":"clamp","inputs":{"in":"color3","low":"float","high":"float"},"outputs":{"out":"color3"}},"ND_clamp_color4FA":{"node":"clamp","inputs":{"in":"color4","low":"float","high":"float"},"outputs":{"out":"color4"}},"ND_clamp_vector2FA":{"node":"clamp","inputs":{"in":"vector2","low":"float","high":"float"},"outputs":{"out":"vector2"}},"ND_clamp_vector3FA":{"node":"clamp","inputs":{"in":"vector3","low":"float","high":"float"},"outputs":{"out":"vector3"}},"ND_clamp_vector4FA":{"node":"clamp","inputs":{"in":"vector4","low":"float","high":"float"},"outputs":{"out":"vector4"}},"ND_min_float":{"node":"min","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_min_color3":{"node":"min","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_min_color4":{"node":"min","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_min_vector2":{"node":"min","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_min_vector3":{"node":"min","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_min_vector4":{"node":"min","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_min_color3FA":{"node":"min","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_min_color4FA":{"node":"min","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_min_vector2FA":{"node":"min","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_min_vector3FA":{"node":"min","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_min_vector4FA":{"node":"min","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_max_float":{"node":"max","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_max_color3":{"node":"max","inputs":{"in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_max_color4":{"node":"max","inputs":{"in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_max_vector2":{"node":"max","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_max_vector3":{"node":"max","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_max_vector4":{"node":"max","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_max_color3FA":{"node":"max","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color3"}},"ND_max_color4FA":{"node":"max","inputs":{"in1":"color4","in2":"float"},"outputs":{"out":"color4"}},"ND_max_vector2FA":{"node":"max","inputs":{"in1":"vector2","in2":"float"},"outputs":{"out":"vector2"}},"ND_max_vector3FA":{"node":"max","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector3"}},"ND_max_vector4FA":{"node":"max","inputs":{"in1":"vector4","in2":"float"},"outputs":{"out":"vector4"}},"ND_normalize_vector2":{"node":"normalize","inputs":{"in":"vector2"},"outputs":{"out":"vector2"}},"ND_normalize_vector3":{"node":"normalize","inputs":{"in":"vector3"},"outputs":{"out":"vector3"}},"ND_normalize_vector4":{"node":"normalize","inputs":{"in":"vector4"},"outputs":{"out":"vector4"}},"ND_magnitude_vector2":{"node":"magnitude","inputs":{"in":"vector2"},"outputs":{"out":"float"}},"ND_magnitude_vector3":{"node":"magnitude","inputs":{"in":"vector3"},"outputs":{"out":"float"}},"ND_magnitude_vector4":{"node":"magnitude","inputs":{"in":"vector4"},"outputs":{"out":"float"}},"ND_distance_vector2":{"node":"distance","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"float"}},"ND_distance_vector3":{"node":"distance","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"float"}},"ND_distance_vector4":{"node":"distance","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"float"}},"ND_dotproduct_vector2":{"node":"dotproduct","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"float"}},"ND_dotproduct_vector3":{"node":"dotproduct","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"float"}},"ND_dotproduct_vector4":{"node":"dotproduct","inputs":{"in1":"vector4","in2":"vector4"},"outputs":{"out":"float"}},"ND_crossproduct_vector3":{"node":"crossproduct","inputs":{"in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_transformpoint_vector3":{"node":"transformpoint","inputs":{"in":"vector3","fromspace":"string","tospace":"string"},"outputs":{"out":"vector3"}},"ND_transformvector_vector3":{"node":"transformvector","inputs":{"in":"vector3","fromspace":"string","tospace":"string"},"outputs":{"out":"vector3"}},"ND_transformnormal_vector3":{"node":"transformnormal","inputs":{"in":"vector3","fromspace":"string","tospace":"string"},"outputs":{"out":"vector3"}},"ND_transformmatrix_vector2M3":{"node":"transformmatrix","inputs":{"in":"vector2","mat":"matrix33"},"outputs":{"out":"vector2"}},"ND_transformmatrix_vector3":{"node":"transformmatrix","inputs":{"in":"vector3","mat":"matrix33"},"outputs":{"out":"vector3"}},"ND_transformmatrix_vector3M4":{"node":"transformmatrix","inputs":{"in":"vector3","mat":"matrix44"},"outputs":{"out":"vector3"}},"ND_transformmatrix_vector4":{"node":"transformmatrix","inputs":{"in":"vector4","mat":"matrix44"},"outputs":{"out":"vector4"}},"ND_normalmap_float":{"node":"normalmap","inputs":{"in":"vector3","scale":"float","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_normalmap_vector2":{"node":"normalmap","inputs":{"in":"vector3","scale":"vector2","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_hextilednormalmap_vector3":{"node":"hextilednormalmap","inputs":{"file":"filename","default":"vector3","texcoord":"vector2","tiling":"vector2","rotation":"float","rotationrange":"vector2","scale":"float","scalerange":"vector2","offset":"float","offsetrange":"vector2","falloff":"float","strength":"float","flip_g":"boolean","normal":"vector3","tangent":"vector3","bitangent":"vector3"},"outputs":{"out":"vector3"}},"ND_transpose_matrix33":{"node":"transpose","inputs":{"in":"matrix33"},"outputs":{"out":"matrix33"}},"ND_transpose_matrix44":{"node":"transpose","inputs":{"in":"matrix44"},"outputs":{"out":"matrix44"}},"ND_determinant_matrix33":{"node":"determinant","inputs":{"in":"matrix33"},"outputs":{"out":"float"}},"ND_determinant_matrix44":{"node":"determinant","inputs":{"in":"matrix44"},"outputs":{"out":"float"}},"ND_invertmatrix_matrix33":{"node":"invertmatrix","inputs":{"in":"matrix33"},"outputs":{"out":"matrix33"}},"ND_invertmatrix_matrix44":{"node":"invertmatrix","inputs":{"in":"matrix44"},"outputs":{"out":"matrix44"}},"ND_rotate2d_vector2":{"node":"rotate2d","inputs":{"in":"vector2","amount":"float"},"outputs":{"out":"vector2"}},"ND_rotate3d_vector3":{"node":"rotate3d","inputs":{"in":"vector3","amount":"float","axis":"vector3"},"outputs":{"out":"vector3"}},"ND_place2d_vector2":{"node":"place2d","inputs":{"texcoord":"vector2","pivot":"vector2","scale":"vector2","rotate":"float","offset":"vector2","operationorder":"integer"},"outputs":{"out":"vector2"}},"ND_trianglewave_float":{"node":"trianglewave","inputs":{"in":"float"},"outputs":{"out":"float"}},"ND_reflect_vector3":{"node":"reflect","inputs":{"in":"vector3","normal":"vector3"},"outputs":{"out":"vector3"}},"ND_refract_vector3":{"node":"refract","inputs":{"in":"vector3","normal":"vector3","ior":"float"},"outputs":{"out":"vector3"}},"ND_remap_float":{"node":"remap","inputs":{"in":"float","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"float"}},"ND_remap_color3":{"node":"remap","inputs":{"in":"color3","inlow":"color3","inhigh":"color3","outlow":"color3","outhigh":"color3"},"outputs":{"out":"color3"}},"ND_remap_color4":{"node":"remap","inputs":{"in":"color4","inlow":"color4","inhigh":"color4","outlow":"color4","outhigh":"color4"},"outputs":{"out":"color4"}},"ND_remap_vector2":{"node":"remap","inputs":{"in":"vector2","inlow":"vector2","inhigh":"vector2","outlow":"vector2","outhigh":"vector2"},"outputs":{"out":"vector2"}},"ND_remap_vector3":{"node":"remap","inputs":{"in":"vector3","inlow":"vector3","inhigh":"vector3","outlow":"vector3","outhigh":"vector3"},"outputs":{"out":"vector3"}},"ND_remap_vector4":{"node":"remap","inputs":{"in":"vector4","inlow":"vector4","inhigh":"vector4","outlow":"vector4","outhigh":"vector4"},"outputs":{"out":"vector4"}},"ND_remap_color3FA":{"node":"remap","inputs":{"in":"color3","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"color3"}},"ND_remap_color4FA":{"node":"remap","inputs":{"in":"color4","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"color4"}},"ND_remap_vector2FA":{"node":"remap","inputs":{"in":"vector2","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"vector2"}},"ND_remap_vector3FA":{"node":"remap","inputs":{"in":"vector3","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"vector3"}},"ND_remap_vector4FA":{"node":"remap","inputs":{"in":"vector4","inlow":"float","inhigh":"float","outlow":"float","outhigh":"float"},"outputs":{"out":"vector4"}},"ND_smoothstep_float":{"node":"smoothstep","inputs":{"in":"float","low":"float","high":"float"},"outputs":{"out":"float"}},"ND_smoothstep_color3":{"node":"smoothstep","inputs":{"in":"color3","low":"color3","high":"color3"},"outputs":{"out":"color3"}},"ND_smoothstep_color4":{"node":"smoothstep","inputs":{"in":"color4","low":"color4","high":"color4"},"outputs":{"out":"color4"}},"ND_smoothstep_vector2":{"node":"smoothstep","inputs":{"in":"vector2","low":"vector2","high":"vector2"},"outputs":{"out":"vector2"}},"ND_smoothstep_vector3":{"node":"smoothstep","inputs":{"in":"vector3","low":"vector3","high":"vector3"},"outputs":{"out":"vector3"}},"ND_smoothstep_vector4":{"node":"smoothstep","inputs":{"in":"vector4","low":"vector4","high":"vector4"},"outputs":{"out":"vector4"}},"ND_smoothstep_color3FA":{"node":"smoothstep","inputs":{"in":"color3","low":"float","high":"float"},"outputs":{"out":"color3"}},"ND_smoothstep_color4FA":{"node":"smoothstep","inputs":{"in":"color4","low":"float","high":"float"},"outputs":{"out":"color4"}},"ND_smoothstep_vector2FA":{"node":"smoothstep","inputs":{"in":"vector2","low":"float","high":"float"},"outputs":{"out":"vector2"}},"ND_smoothstep_vector3FA":{"node":"smoothstep","inputs":{"in":"vector3","low":"float","high":"float"},"outputs":{"out":"vector3"}},"ND_smoothstep_vector4FA":{"node":"smoothstep","inputs":{"in":"vector4","low":"float","high":"float"},"outputs":{"out":"vector4"}},"ND_luminance_color3":{"node":"luminance","inputs":{"in":"color3","lumacoeffs":"color3"},"outputs":{"out":"color3"}},"ND_luminance_color4":{"node":"luminance","inputs":{"in":"color4","lumacoeffs":"color3"},"outputs":{"out":"color4"}},"ND_rgbtohsv_color3":{"node":"rgbtohsv","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_rgbtohsv_color4":{"node":"rgbtohsv","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_hsvtorgb_color3":{"node":"hsvtorgb","inputs":{"in":"color3"},"outputs":{"out":"color3"}},"ND_hsvtorgb_color4":{"node":"hsvtorgb","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_contrast_float":{"node":"contrast","inputs":{"in":"float","amount":"float","pivot":"float"},"outputs":{"out":"float"}},"ND_contrast_color3":{"node":"contrast","inputs":{"in":"color3","amount":"color3","pivot":"color3"},"outputs":{"out":"color3"}},"ND_contrast_color4":{"node":"contrast","inputs":{"in":"color4","amount":"color4","pivot":"color4"},"outputs":{"out":"color4"}},"ND_contrast_vector2":{"node":"contrast","inputs":{"in":"vector2","amount":"vector2","pivot":"vector2"},"outputs":{"out":"vector2"}},"ND_contrast_vector3":{"node":"contrast","inputs":{"in":"vector3","amount":"vector3","pivot":"vector3"},"outputs":{"out":"vector3"}},"ND_contrast_vector4":{"node":"contrast","inputs":{"in":"vector4","amount":"vector4","pivot":"vector4"},"outputs":{"out":"vector4"}},"ND_contrast_color3FA":{"node":"contrast","inputs":{"in":"color3","amount":"float","pivot":"float"},"outputs":{"out":"color3"}},"ND_contrast_color4FA":{"node":"contrast","inputs":{"in":"color4","amount":"float","pivot":"float"},"outputs":{"out":"color4"}},"ND_contrast_vector2FA":{"node":"contrast","inputs":{"in":"vector2","amount":"float","pivot":"float"},"outputs":{"out":"vector2"}},"ND_contrast_vector3FA":{"node":"contrast","inputs":{"in":"vector3","amount":"float","pivot":"float"},"outputs":{"out":"vector3"}},"ND_contrast_vector4FA":{"node":"contrast","inputs":{"in":"vector4","amount":"float","pivot":"float"},"outputs":{"out":"vector4"}},"ND_range_float":{"node":"range","inputs":{"in":"float","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"float"}},"ND_range_color3":{"node":"range","inputs":{"in":"color3","inlow":"color3","inhigh":"color3","gamma":"color3","outlow":"color3","outhigh":"color3","doclamp":"boolean"},"outputs":{"out":"color3"}},"ND_range_color4":{"node":"range","inputs":{"in":"color4","inlow":"color4","inhigh":"color4","gamma":"color4","outlow":"color4","outhigh":"color4","doclamp":"boolean"},"outputs":{"out":"color4"}},"ND_range_vector2":{"node":"range","inputs":{"in":"vector2","inlow":"vector2","inhigh":"vector2","gamma":"vector2","outlow":"vector2","outhigh":"vector2","doclamp":"boolean"},"outputs":{"out":"vector2"}},"ND_range_vector3":{"node":"range","inputs":{"in":"vector3","inlow":"vector3","inhigh":"vector3","gamma":"vector3","outlow":"vector3","outhigh":"vector3","doclamp":"boolean"},"outputs":{"out":"vector3"}},"ND_range_vector4":{"node":"range","inputs":{"in":"vector4","inlow":"vector4","inhigh":"vector4","gamma":"vector4","outlow":"vector4","outhigh":"vector4","doclamp":"boolean"},"outputs":{"out":"vector4"}},"ND_range_color3FA":{"node":"range","inputs":{"in":"color3","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"color3"}},"ND_range_color4FA":{"node":"range","inputs":{"in":"color4","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"color4"}},"ND_range_vector2FA":{"node":"range","inputs":{"in":"vector2","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"vector2"}},"ND_range_vector3FA":{"node":"range","inputs":{"in":"vector3","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"vector3"}},"ND_range_vector4FA":{"node":"range","inputs":{"in":"vector4","inlow":"float","inhigh":"float","gamma":"float","outlow":"float","outhigh":"float","doclamp":"boolean"},"outputs":{"out":"vector4"}},"ND_hsvadjust_color3":{"node":"hsvadjust","inputs":{"in":"color3","amount":"vector3"},"outputs":{"out":"color3"}},"ND_hsvadjust_color4":{"node":"hsvadjust","inputs":{"in":"color4","amount":"vector3"},"outputs":{"out":"color4"}},"ND_saturate_color3":{"node":"saturate","inputs":{"in":"color3","amount":"float","lumacoeffs":"color3"},"outputs":{"out":"color3"}},"ND_saturate_color4":{"node":"saturate","inputs":{"in":"color4","amount":"float","lumacoeffs":"color3"},"outputs":{"out":"color4"}},"ND_colorcorrect_color3":{"node":"colorcorrect","inputs":{"in":"color3","hue":"float","saturation":"float","gamma":"float","lift":"float","gain":"float","contrast":"float","contrastpivot":"float","exposure":"float"},"outputs":{"out":"color3"}},"ND_colorcorrect_color4":{"node":"colorcorrect","inputs":{"in":"color4","hue":"float","saturation":"float","gamma":"float","lift":"float","gain":"float","contrast":"float","contrastpivot":"float","exposure":"float"},"outputs":{"out":"color4"}},"ND_premult_color4":{"node":"premult","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_unpremult_color4":{"node":"unpremult","inputs":{"in":"color4"},"outputs":{"out":"color4"}},"ND_plus_float":{"node":"plus","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_plus_color3":{"node":"plus","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_plus_color4":{"node":"plus","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_minus_float":{"node":"minus","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_minus_color3":{"node":"minus","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_minus_color4":{"node":"minus","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_difference_float":{"node":"difference","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_difference_color3":{"node":"difference","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_difference_color4":{"node":"difference","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_burn_float":{"node":"burn","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_burn_color3":{"node":"burn","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_burn_color4":{"node":"burn","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_dodge_float":{"node":"dodge","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_dodge_color3":{"node":"dodge","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_dodge_color4":{"node":"dodge","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_screen_float":{"node":"screen","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_screen_color3":{"node":"screen","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_screen_color4":{"node":"screen","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_overlay_float":{"node":"overlay","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_overlay_color3":{"node":"overlay","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_overlay_color4":{"node":"overlay","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_disjointover_color4":{"node":"disjointover","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_in_color4":{"node":"in","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_mask_color4":{"node":"mask","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_matte_color4":{"node":"matte","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_out_color4":{"node":"out","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_over_color4":{"node":"over","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_inside_float":{"node":"inside","inputs":{"in":"float","mask":"float"},"outputs":{"out":"float"}},"ND_inside_color3":{"node":"inside","inputs":{"in":"color3","mask":"float"},"outputs":{"out":"color3"}},"ND_inside_color4":{"node":"inside","inputs":{"in":"color4","mask":"float"},"outputs":{"out":"color4"}},"ND_outside_float":{"node":"outside","inputs":{"in":"float","mask":"float"},"outputs":{"out":"float"}},"ND_outside_color3":{"node":"outside","inputs":{"in":"color3","mask":"float"},"outputs":{"out":"color3"}},"ND_outside_color4":{"node":"outside","inputs":{"in":"color4","mask":"float"},"outputs":{"out":"color4"}},"ND_mix_float":{"node":"mix","inputs":{"fg":"float","bg":"float","mix":"float"},"outputs":{"out":"float"}},"ND_mix_color3":{"node":"mix","inputs":{"fg":"color3","bg":"color3","mix":"float"},"outputs":{"out":"color3"}},"ND_mix_color3_color3":{"node":"mix","inputs":{"fg":"color3","bg":"color3","mix":"color3"},"outputs":{"out":"color3"}},"ND_mix_color4":{"node":"mix","inputs":{"fg":"color4","bg":"color4","mix":"float"},"outputs":{"out":"color4"}},"ND_mix_color4_color4":{"node":"mix","inputs":{"fg":"color4","bg":"color4","mix":"color4"},"outputs":{"out":"color4"}},"ND_mix_vector2":{"node":"mix","inputs":{"fg":"vector2","bg":"vector2","mix":"float"},"outputs":{"out":"vector2"}},"ND_mix_vector2_vector2":{"node":"mix","inputs":{"fg":"vector2","bg":"vector2","mix":"vector2"},"outputs":{"out":"vector2"}},"ND_mix_vector3":{"node":"mix","inputs":{"fg":"vector3","bg":"vector3","mix":"float"},"outputs":{"out":"vector3"}},"ND_mix_vector3_vector3":{"node":"mix","inputs":{"fg":"vector3","bg":"vector3","mix":"vector3"},"outputs":{"out":"vector3"}},"ND_mix_vector4":{"node":"mix","inputs":{"fg":"vector4","bg":"vector4","mix":"float"},"outputs":{"out":"vector4"}},"ND_mix_vector4_vector4":{"node":"mix","inputs":{"fg":"vector4","bg":"vector4","mix":"vector4"},"outputs":{"out":"vector4"}},"ND_mix_surfaceshader":{"node":"mix","inputs":{"fg":"surfaceshader","bg":"surfaceshader","mix":"float"},"outputs":{"out":"surfaceshader"}},"ND_mix_displacementshader":{"node":"mix","inputs":{"fg":"displacementshader","bg":"displacementshader","mix":"float"},"outputs":{"out":"displacementshader"}},"ND_mix_volumeshader":{"node":"mix","inputs":{"fg":"volumeshader","bg":"volumeshader","mix":"float"},"outputs":{"out":"volumeshader"}},"ND_ifgreater_float":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreater_integer":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreater_color3":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreater_color4":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreater_vector2":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreater_vector3":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreater_vector4":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreater_matrix33":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreater_matrix44":{"node":"ifgreater","inputs":{"value1":"float","value2":"float","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreater_boolean":{"node":"ifgreater","inputs":{"value1":"float","value2":"float"},"outputs":{"out":"boolean"}},"ND_ifgreater_floatI":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreater_integerI":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreater_color3I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreater_color4I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreater_vector2I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreater_vector3I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreater_vector4I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreater_matrix33I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreater_matrix44I":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreater_booleanI":{"node":"ifgreater","inputs":{"value1":"integer","value2":"integer"},"outputs":{"out":"boolean"}},"ND_ifgreatereq_float":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreatereq_integer":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreatereq_color3":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreatereq_color4":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreatereq_vector2":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreatereq_vector3":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreatereq_vector4":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreatereq_matrix33":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreatereq_matrix44":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreatereq_boolean":{"node":"ifgreatereq","inputs":{"value1":"float","value2":"float"},"outputs":{"out":"boolean"}},"ND_ifgreatereq_floatI":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifgreatereq_integerI":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifgreatereq_color3I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifgreatereq_color4I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifgreatereq_vector2I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifgreatereq_vector3I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifgreatereq_vector4I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifgreatereq_matrix33I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifgreatereq_matrix44I":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifgreatereq_booleanI":{"node":"ifgreatereq","inputs":{"value1":"integer","value2":"integer"},"outputs":{"out":"boolean"}},"ND_ifequal_float":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifequal_integer":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifequal_color3":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifequal_color4":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifequal_vector2":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifequal_vector3":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifequal_vector4":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifequal_matrix33":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifequal_matrix44":{"node":"ifequal","inputs":{"value1":"float","value2":"float","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifequal_boolean":{"node":"ifequal","inputs":{"value1":"float","value2":"float"},"outputs":{"out":"boolean"}},"ND_ifequal_floatI":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifequal_integerI":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifequal_color3I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifequal_color4I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifequal_vector2I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifequal_vector3I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifequal_vector4I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifequal_matrix33I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifequal_matrix44I":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifequal_booleanI":{"node":"ifequal","inputs":{"value1":"integer","value2":"integer"},"outputs":{"out":"boolean"}},"ND_ifequal_floatB":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"float","in2":"float"},"outputs":{"out":"float"}},"ND_ifequal_integerB":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"integer","in2":"integer"},"outputs":{"out":"integer"}},"ND_ifequal_color3B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"color3","in2":"color3"},"outputs":{"out":"color3"}},"ND_ifequal_color4B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"color4","in2":"color4"},"outputs":{"out":"color4"}},"ND_ifequal_vector2B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"vector2","in2":"vector2"},"outputs":{"out":"vector2"}},"ND_ifequal_vector3B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"vector3","in2":"vector3"},"outputs":{"out":"vector3"}},"ND_ifequal_vector4B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"vector4","in2":"vector4"},"outputs":{"out":"vector4"}},"ND_ifequal_matrix33B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"matrix33","in2":"matrix33"},"outputs":{"out":"matrix33"}},"ND_ifequal_matrix44B":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean","in1":"matrix44","in2":"matrix44"},"outputs":{"out":"matrix44"}},"ND_ifequal_booleanB":{"node":"ifequal","inputs":{"value1":"boolean","value2":"boolean"},"outputs":{"out":"boolean"}},"ND_switch_float":{"node":"switch","inputs":{"in1":"float","in2":"float","in3":"float","in4":"float","in5":"float","in6":"float","in7":"float","in8":"float","in9":"float","in10":"float","which":"float"},"outputs":{"out":"float"}},"ND_switch_color3":{"node":"switch","inputs":{"in1":"color3","in2":"color3","in3":"color3","in4":"color3","in5":"color3","in6":"color3","in7":"color3","in8":"color3","in9":"color3","in10":"color3","which":"float"},"outputs":{"out":"color3"}},"ND_switch_color4":{"node":"switch","inputs":{"in1":"color4","in2":"color4","in3":"color4","in4":"color4","in5":"color4","in6":"color4","in7":"color4","in8":"color4","in9":"color4","in10":"color4","which":"float"},"outputs":{"out":"color4"}},"ND_switch_vector2":{"node":"switch","inputs":{"in1":"vector2","in2":"vector2","in3":"vector2","in4":"vector2","in5":"vector2","in6":"vector2","in7":"vector2","in8":"vector2","in9":"vector2","in10":"vector2","which":"float"},"outputs":{"out":"vector2"}},"ND_switch_vector3":{"node":"switch","inputs":{"in1":"vector3","in2":"vector3","in3":"vector3","in4":"vector3","in5":"vector3","in6":"vector3","in7":"vector3","in8":"vector3","in9":"vector3","in10":"vector3","which":"float"},"outputs":{"out":"vector3"}},"ND_switch_vector4":{"node":"switch","inputs":{"in1":"vector4","in2":"vector4","in3":"vector4","in4":"vector4","in5":"vector4","in6":"vector4","in7":"vector4","in8":"vector4","in9":"vector4","in10":"vector4","which":"float"},"outputs":{"out":"vector4"}},"ND_switch_matrix33":{"node":"switch","inputs":{"in1":"matrix33","in2":"matrix33","in3":"matrix33","in4":"matrix33","in5":"matrix33","in6":"matrix33","in7":"matrix33","in8":"matrix33","in9":"matrix33","in10":"matrix33","which":"float"},"outputs":{"out":"matrix33"}},"ND_switch_matrix44":{"node":"switch","inputs":{"in1":"matrix44","in2":"matrix44","in3":"matrix44","in4":"matrix44","in5":"matrix44","in6":"matrix44","in7":"matrix44","in8":"matrix44","in9":"matrix44","in10":"matrix44","which":"float"},"outputs":{"out":"matrix44"}},"ND_switch_floatI":{"node":"switch","inputs":{"in1":"float","in2":"float","in3":"float","in4":"float","in5":"float","in6":"float","in7":"float","in8":"float","in9":"float","in10":"float","which":"integer"},"outputs":{"out":"float"}},"ND_switch_color3I":{"node":"switch","inputs":{"in1":"color3","in2":"color3","in3":"color3","in4":"color3","in5":"color3","in6":"color3","in7":"color3","in8":"color3","in9":"color3","in10":"color3","which":"integer"},"outputs":{"out":"color3"}},"ND_switch_color4I":{"node":"switch","inputs":{"in1":"color4","in2":"color4","in3":"color4","in4":"color4","in5":"color4","in6":"color4","in7":"color4","in8":"color4","in9":"color4","in10":"color4","which":"integer"},"outputs":{"out":"color4"}},"ND_switch_vector2I":{"node":"switch","inputs":{"in1":"vector2","in2":"vector2","in3":"vector2","in4":"vector2","in5":"vector2","in6":"vector2","in7":"vector2","in8":"vector2","in9":"vector2","in10":"vector2","which":"integer"},"outputs":{"out":"vector2"}},"ND_switch_vector3I":{"node":"switch","inputs":{"in1":"vector3","in2":"vector3","in3":"vector3","in4":"vector3","in5":"vector3","in6":"vector3","in7":"vector3","in8":"vector3","in9":"vector3","in10":"vector3","which":"integer"},"outputs":{"out":"vector3"}},"ND_switch_vector4I":{"node":"switch","inputs":{"in1":"vector4","in2":"vector4","in3":"vector4","in4":"vector4","in5":"vector4","in6":"vector4","in7":"vector4","in8":"vector4","in9":"vector4","in10":"vector4","which":"integer"},"outputs":{"out":"vector4"}},"ND_switch_matrix33I":{"node":"switch","inputs":{"in1":"matrix33","in2":"matrix33","in3":"matrix33","in4":"matrix33","in5":"matrix33","in6":"matrix33","in7":"matrix33","in8":"matrix33","in9":"matrix33","in10":"matrix33","which":"integer"},"outputs":{"out":"matrix33"}},"ND_switch_matrix44I":{"node":"switch","inputs":{"in1":"matrix44","in2":"matrix44","in3":"matrix44","in4":"matrix44","in5":"matrix44","in6":"matrix44","in7":"matrix44","in8":"matrix44","in9":"matrix44","in10":"matrix44","which":"integer"},"outputs":{"out":"matrix44"}},"ND_convert_float_color3":{"node":"convert","inputs":{"in":"float"},"outputs":{"out":"color3"}},"ND_convert_float_color4":{"node":"convert","inputs":{"in":"float"},"outputs":{"out":"color4"}},"ND_convert_float_vector2":{"node":"convert","inputs":{"in":"float"},"outputs":{"out":"vector2"}},"ND_convert_float_vector3":{"node":"convert","inputs":{"in":"float"},"outputs":{"out":"vector3"}},"ND_convert_float_vector4":{"node":"convert","inputs":{"in":"float"},"outputs":{"out":"vector4"}},"ND_convert_color3_color4":{"node":"convert","inputs":{"in":"color3"},"outputs":{"out":"color4"}},"ND_convert_color3_vector2":{"node":"convert","inputs":{"in":"color3"},"outputs":{"out":"vector2"}},"ND_convert_color3_vector3":{"node":"convert","inputs":{"in":"color3"},"outputs":{"out":"vector3"}},"ND_convert_color3_vector4":{"node":"convert","inputs":{"in":"color3"},"outputs":{"out":"vector4"}},"ND_convert_color4_color3":{"node":"convert","inputs":{"in":"color4"},"outputs":{"out":"color3"}},"ND_convert_color4_vector2":{"node":"convert","inputs":{"in":"color4"},"outputs":{"out":"vector2"}},"ND_convert_color4_vector3":{"node":"convert","inputs":{"in":"color4"},"outputs":{"out":"vector3"}},"ND_convert_color4_vector4":{"node":"convert","inputs":{"in":"color4"},"outputs":{"out":"vector4"}},"ND_convert_vector2_color3":{"node":"convert","inputs":{"in":"vector2"},"outputs":{"out":"color3"}},"ND_convert_vector2_color4":{"node":"convert","inputs":{"in":"vector2"},"outputs":{"out":"color4"}},"ND_convert_vector2_vector3":{"node":"convert","inputs":{"in":"vector2"},"outputs":{"out":"vector3"}},"ND_convert_vector2_vector4":{"node":"convert","inputs":{"in":"vector2"},"outputs":{"out":"vector4"}},"ND_convert_vector3_color3":{"node":"convert","inputs":{"in":"vector3"},"outputs":{"out":"color3"}},"ND_convert_vector3_color4":{"node":"convert","inputs":{"in":"vector3"},"outputs":{"out":"color4"}},"ND_convert_vector3_vector2":{"node":"convert","inputs":{"in":"vector3"},"outputs":{"out":"vector2"}},"ND_convert_vector3_vector4":{"node":"convert","inputs":{"in":"vector3"},"outputs":{"out":"vector4"}},"ND_convert_vector4_color3":{"node":"convert","inputs":{"in":"vector4"},"outputs":{"out":"color3"}},"ND_convert_vector4_color4":{"node":"convert","inputs":{"in":"vector4"},"outputs":{"out":"color4"}},"ND_convert_vector4_vector2":{"node":"convert","inputs":{"in":"vector4"},"outputs":{"out":"vector2"}},"ND_convert_vector4_vector3":{"node":"convert","inputs":{"in":"vector4"},"outputs":{"out":"vector3"}},"ND_convert_boolean_float":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"float"}},"ND_convert_boolean_color3":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"color3"}},"ND_convert_boolean_color4":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"color4"}},"ND_convert_boolean_vector2":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"vector2"}},"ND_convert_boolean_vector3":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"vector3"}},"ND_convert_boolean_vector4":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"vector4"}},"ND_convert_boolean_integer":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"integer"}},"ND_convert_integer_float":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"float"}},"ND_convert_integer_color3":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"color3"}},"ND_convert_integer_color4":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"color4"}},"ND_convert_integer_vector2":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"vector2"}},"ND_convert_integer_vector3":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"vector3"}},"ND_convert_integer_vector4":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"vector4"}},"ND_convert_integer_boolean":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"boolean"}},"ND_convert_color3_surfaceshader":{"node":"convert","inputs":{"in":"color3"},"outputs":{"out":"surfaceshader"}},"ND_convert_color4_surfaceshader":{"node":"convert","inputs":{"in":"color4"},"outputs":{"out":"surfaceshader"}},"ND_convert_float_surfaceshader":{"node":"convert","inputs":{"in":"float"},"outputs":{"out":"surfaceshader"}},"ND_convert_vector2_surfaceshader":{"node":"convert","inputs":{"in":"vector2"},"outputs":{"out":"surfaceshader"}},"ND_convert_vector3_surfaceshader":{"node":"convert","inputs":{"in":"vector3"},"outputs":{"out":"surfaceshader"}},"ND_convert_vector4_surfaceshader":{"node":"convert","inputs":{"in":"vector4"},"outputs":{"out":"surfaceshader"}},"ND_convert_integer_surfaceshader":{"node":"convert","inputs":{"in":"integer"},"outputs":{"out":"surfaceshader"}},"ND_convert_boolean_surfaceshader":{"node":"convert","inputs":{"in":"boolean"},"outputs":{"out":"surfaceshader"}},"ND_combine2_vector2":{"node":"combine2","inputs":{"in1":"float","in2":"float"},"outputs":{"out":"vector2"}},"ND_combine2_color4CF":{"node":"combine2","inputs":{"in1":"color3","in2":"float"},"outputs":{"out":"color4"}},"ND_combine2_vector4VF":{"node":"combine2","inputs":{"in1":"vector3","in2":"float"},"outputs":{"out":"vector4"}},"ND_combine2_vector4VV":{"node":"combine2","inputs":{"in1":"vector2","in2":"vector2"},"outputs":{"out":"vector4"}},"ND_combine3_color3":{"node":"combine3","inputs":{"in1":"float","in2":"float","in3":"float"},"outputs":{"out":"color3"}},"ND_combine3_vector3":{"node":"combine3","inputs":{"in1":"float","in2":"float","in3":"float"},"outputs":{"out":"vector3"}},"ND_combine4_color4":{"node":"combine4","inputs":{"in1":"float","in2":"float","in3":"float","in4":"float"},"outputs":{"out":"color4"}},"ND_combine4_vector4":{"node":"combine4","inputs":{"in1":"float","in2":"float","in3":"float","in4":"float"},"outputs":{"out":"vector4"}},"ND_creatematrix_vector3_matrix33":{"node":"creatematrix","inputs":{"in1":"vector3","in2":"vector3","in3":"vector3"},"outputs":{"out":"matrix33"}},"ND_creatematrix_vector3_matrix44":{"node":"creatematrix","inputs":{"in1":"vector3","in2":"vector3","in3":"vector3","in4":"vector3"},"outputs":{"out":"matrix44"}},"ND_creatematrix_vector4_matrix44":{"node":"creatematrix","inputs":{"in1":"vector4","in2":"vector4","in3":"vector4","in4":"vector4"},"outputs":{"out":"matrix44"}},"ND_extract_color3":{"node":"extract","inputs":{"in":"color3","index":"integer"},"outputs":{"out":"float"}},"ND_extract_color4":{"node":"extract","inputs":{"in":"color4","index":"integer"},"outputs":{"out":"float"}},"ND_extract_vector2":{"node":"extract","inputs":{"in":"vector2","index":"integer"},"outputs":{"out":"float"}},"ND_extract_vector3":{"node":"extract","inputs":{"in":"vector3","index":"integer"},"outputs":{"out":"float"}},"ND_extract_vector4":{"node":"extract","inputs":{"in":"vector4","index":"integer"},"outputs":{"out":"float"}},"ND_extract_matrix33":{"node":"extract","inputs":{"in":"matrix33","index":"integer"},"outputs":{"out":"vector3"}},"ND_extract_matrix44":{"node":"extract","inputs":{"in":"matrix44","index":"integer"},"outputs":{"out":"vector4"}},"ND_separate2_vector2":{"node":"separate2","inputs":{"in":"vector2"},"outputs":{"outx":"float","outy":"float"}},"ND_separate3_color3":{"node":"separate3","inputs":{"in":"color3"},"outputs":{"outr":"float","outg":"float","outb":"float"}},"ND_separate3_vector3":{"node":"separate3","inputs":{"in":"vector3"},"outputs":{"outx":"float","outy":"float","outz":"float"}},"ND_separate4_color4":{"node":"separate4","inputs":{"in":"color4"},"outputs":{"outr":"float","outg":"float","outb":"float","outa":"float"}},"ND_separate4_vector4":{"node":"separate4","inputs":{"in":"vector4"},"outputs":{"outx":"float","outy":"float","outz":"float","outw":"float"}},"ND_blur_float":{"node":"blur","inputs":{"in":"float","size":"float","filtertype":"string"},"outputs":{"out":"float"}},"ND_blur_color3":{"node":"blur","inputs":{"in":"color3","size":"float","filtertype":"string"},"outputs":{"out":"color3"}},"ND_blur_color4":{"node":"blur","inputs":{"in":"color4","size":"float","filtertype":"string"},"outputs":{"out":"color4"}},"ND_blur_vector2":{"node":"blur","inputs":{"in":"vector2","size":"float","filtertype":"string"},"outputs":{"out":"vector2"}},"ND_blur_vector3":{"node":"blur","inputs":{"in":"vector3","size":"float","filtertype":"string"},"outputs":{"out":"vector3"}},"ND_blur_vector4":{"node":"blur","inputs":{"in":"vector4","size":"float","filtertype":"string"},"outputs":{"out":"vector4"}},"ND_heighttonormal_vector3":{"node":"heighttonormal","inputs":{"in":"float","scale":"float","texcoord":"vector2"},"outputs":{"out":"vector3"}},"ND_logical_and":{"node":"and","inputs":{"in1":"boolean","in2":"boolean"},"outputs":{"out":"boolean"}},"ND_logical_or":{"node":"or","inputs":{"in1":"boolean","in2":"boolean"},"outputs":{"out":"boolean"}},"ND_logical_xor":{"node":"xor","inputs":{"in1":"boolean","in2":"boolean"},"outputs":{"out":"boolean"}},"ND_logical_not":{"node":"not","inputs":{"in":"boolean"},"outputs":{"out":"boolean"}},"ND_dot_float":{"node":"dot","inputs":{"in":"float","note":"string"},"outputs":{"out":"float"}},"ND_dot_color3":{"node":"dot","inputs":{"in":"color3","note":"string"},"outputs":{"out":"color3"}},"ND_dot_color4":{"node":"dot","inputs":{"in":"color4","note":"string"},"outputs":{"out":"color4"}},"ND_dot_vector2":{"node":"dot","inputs":{"in":"vector2","note":"string"},"outputs":{"out":"vector2"}},"ND_dot_vector3":{"node":"dot","inputs":{"in":"vector3","note":"string"},"outputs":{"out":"vector3"}},"ND_dot_vector4":{"node":"dot","inputs":{"in":"vector4","note":"string"},"outputs":{"out":"vector4"}},"ND_dot_boolean":{"node":"dot","inputs":{"in":"boolean","note":"string"},"outputs":{"out":"boolean"}},"ND_dot_integer":{"node":"dot","inputs":{"in":"integer","note":"string"},"outputs":{"out":"integer"}},"ND_dot_matrix33":{"node":"dot","inputs":{"in":"matrix33","note":"string"},"outputs":{"out":"matrix33"}},"ND_dot_matrix44":{"node":"dot","inputs":{"in":"matrix44","note":"string"},"outputs":{"out":"matrix44"}},"ND_dot_string":{"node":"dot","inputs":{"in":"string","note":"string"},"outputs":{"out":"string"}},"ND_dot_filename":{"node":"dot","inputs":{"in":"filename","note":"string"},"outputs":{"out":"filename"}},"ND_dot_surfaceshader":{"node":"dot","inputs":{"in":"surfaceshader","note":"string"},"outputs":{"out":"surfaceshader"}},"ND_dot_displacementshader":{"node":"dot","inputs":{"in":"displacementshader","note":"string"},"outputs":{"out":"displacementshader"}},"ND_dot_volumeshader":{"node":"dot","inputs":{"in":"volumeshader","note":"string"},"outputs":{"out":"volumeshader"}},"ND_dot_lightshader":{"node":"dot","inputs":{"in":"lightshader","note":"string"},"outputs":{"out":"lightshader"}},"ND_point_light":{"node":"point_light","inputs":{"position":"vector3","color":"color3","intensity":"float","decay_rate":"float"},"outputs":{"out":"lightshader"}},"ND_directional_light":{"node":"directional_light","inputs":{"direction":"vector3","color":"color3","intensity":"float"},"outputs":{"out":"lightshader"}},"ND_spot_light":{"node":"spot_light","inputs":{"position":"vector3","direction":"vector3","color":"color3","intensity":"float","decay_rate":"float","inner_angle":"float","outer_angle":"float"},"outputs":{"out":"lightshader"}},"ND_open_pbr_surface_to_standard_surface":{"node":"open_pbr_surface_to_standard_surface","inputs":{"base_weight":"float","base_color":"color3","base_diffuse_roughness":"float","base_metalness":"float","specular_weight":"float","specular_color":"color3","specular_roughness":"float","specular_ior":"float","specular_roughness_anisotropy":"float","transmission_weight":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion_scale":"float","subsurface_weight":"float","subsurface_color":"color3","subsurface_radius":"float","subsurface_radius_scale":"color3","subsurface_scatter_anisotropy":"float","fuzz_weight":"float","fuzz_color":"color3","fuzz_roughness":"float","coat_weight":"float","coat_color":"color3","coat_roughness":"float","coat_roughness_anisotropy":"float","coat_ior":"float","coat_darkening":"float","thin_film_weight":"float","thin_film_thickness":"float","thin_film_ior":"float","emission_luminance":"float","emission_color":"color3","geometry_opacity":"float","geometry_thin_walled":"boolean"},"outputs":{"base_out":"float","base_color_out":"color3","diffuse_roughness_out":"float","metalness_out":"float","specular_out":"float","specular_color_out":"color3","specular_roughness_out":"float","specular_IOR_out":"float","specular_anisotropy_out":"float","transmission_out":"float","transmission_color_out":"color3","transmission_depth_out":"float","transmission_scatter_out":"color3","transmission_scatter_anisotropy_out":"float","transmission_dispersion_out":"float","subsurface_out":"float","subsurface_color_out":"color3","subsurface_radius_out":"color3","subsurface_scale_out":"float","subsurface_anisotropy_out":"float","sheen_out":"float","sheen_color_out":"color3","sheen_roughness_out":"float","coat_out":"float","coat_color_out":"color3","coat_roughness_out":"float","coat_anisotropy_out":"float","coat_IOR_out":"float","coat_affect_roughness_out":"float","thin_film_thickness_out":"float","thin_film_IOR_out":"float","emission_out":"float","emission_color_out":"color3","opacity_out":"color3","thin_walled_out":"boolean"}},"ND_standard_surface_to_open_pbr_surface":{"node":"standard_surface_to_open_pbr_surface","inputs":{"base":"float","base_color":"color3","diffuse_roughness":"float","metalness":"float","specular":"float","specular_color":"color3","specular_roughness":"float","specular_IOR":"float","specular_anisotropy":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_scatter":"color3","transmission_scatter_anisotropy":"float","transmission_dispersion":"float","subsurface":"float","subsurface_color":"color3","subsurface_radius":"color3","subsurface_scale":"float","subsurface_anisotropy":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","coat_anisotropy":"float","coat_IOR":"float","coat_affect_roughness":"float","thin_film_thickness":"float","thin_film_IOR":"float","emission":"float","emission_color":"color3","opacity":"color3","thin_walled":"boolean"},"outputs":{"base_weight_out":"float","base_color_out":"color3","base_diffuse_roughness_out":"float","base_metalness_out":"float","specular_weight_out":"float","specular_color_out":"color3","specular_roughness_out":"float","specular_ior_out":"float","specular_roughness_anisotropy_out":"float","transmission_weight_out":"float","transmission_color_out":"color3","transmission_depth_out":"float","transmission_scatter_out":"color3","transmission_scatter_anisotropy_out":"float","transmission_dispersion_scale_out":"float","subsurface_weight_out":"float","subsurface_color_out":"color3","subsurface_radius_out":"float","subsurface_radius_scale_out":"color3","subsurface_scatter_anisotropy_out":"float","fuzz_weight_out":"float","fuzz_color_out":"color3","fuzz_roughness_out":"float","coat_weight_out":"float","coat_color_out":"color3","coat_roughness_out":"float","coat_roughness_anisotropy_out":"float","coat_ior_out":"float","coat_darkening_out":"float","thin_film_weight_out":"float","thin_film_thickness_out":"float","thin_film_ior_out":"float","emission_luminance_out":"float","emission_color_out":"color3","geometry_opacity_out":"float","geometry_thin_walled_out":"boolean"}},"ND_standard_surface_to_UsdPreviewSurface":{"node":"standard_surface_to_UsdPreviewSurface","inputs":{"metalness":"float","base":"float","base_color":"color3","specular":"float","specular_color":"color3","specular_IOR":"float","specular_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","subsurface":"float","subsurface_color":"color3","emission":"float","emission_color":"color3","opacity":"color3","normal":"vector3"},"outputs":{"diffuseColor_out":"color3","emissiveColor_out":"color3","metallic_out":"float","roughness_out":"float","clearcoat_out":"float","clearcoatRoughness_out":"float","opacity_out":"float","ior_out":"float","normal_out":"vector3"}},"ND_standard_surface_to_gltf_pbr":{"node":"standard_surface_to_gltf_pbr","inputs":{"base":"float","base_color":"color3","metalness":"float","specular":"float","specular_color":"color3","specular_anisotropy":"float","specular_rotation":"float","specular_roughness":"float","specular_IOR":"float","transmission":"float","transmission_color":"color3","transmission_depth":"float","transmission_dispersion":"float","sheen":"float","sheen_color":"color3","sheen_roughness":"float","coat":"float","coat_color":"color3","coat_roughness":"float","emission":"float","emission_color":"color3","normal":"vector3","tangent":"vector3","opacity":"color3","thin_walled":"boolean"},"outputs":{"base_color_out":"color3","metallic_out":"float","roughness_out":"float","specular_out":"float","specular_color_out":"color3","ior_out":"float","anisotropy_strength_out":"float","anisotropy_rotation_out":"float","transmission_out":"float","thickness_out":"float","attenuation_color_out":"color3","attenuation_distance_out":"float","sheen_color_out":"color3","sheen_roughness_out":"float","clearcoat_out":"float","clearcoat_roughness_out":"float","dispersion_out":"float","emissive_out":"color3","emissive_strength_out":"float","normal_out":"vector3","tangent_out":"vector3","alpha_out":"float","alpha_mode_out":"integer"}},"ND_lama_sheen":{"node":"LamaSheen","inputs":{"color":"color3","roughness":"float","normal":"vector3"},"outputs":{"out":"BSDF"}},"ND_lama_sss":{"node":"LamaSSS","inputs":{"color":"color3","normal":"vector3","sssRadius":"color3","sssScale":"float","sssMode":"integer","sssIOR":"float","sssAnisotropy":"float","sssBleed":"float","sssFollowTopology":"float","sssSubset":"string","sssContinuationRays":"integer","sssUnitLength":"float","mode":"integer","albedoInversionMethod":"integer"},"outputs":{"out":"BSDF"}},"ND_lama_dielectric":{"node":"LamaDielectric","inputs":{"reflectionTint":"color3","transmissionTint":"color3","fresnelMode":"integer","IOR":"float","reflectivity":"float","roughness":"float","normal":"vector3","anisotropy":"float","direction":"vector3","rotation":"float","absorptionColor":"color3","absorptionRadius":"float","scatterColor":"color3","scatterAnisotropy":"float"},"outputs":{"out":"BSDF"}},"ND_lama_iridescence":{"node":"LamaIridescence","inputs":{"roughness":"float","anisotropy":"float","anisotropyDirection":"vector3","anisotropyRotation":"float","relativeFilmThickness":"float","minFilmThickness":"float","maxFilmThickness":"float","filmIOR":"float"},"outputs":{"out":"BSDF"}},"ND_lama_diffuse":{"node":"LamaDiffuse","inputs":{"color":"color3","roughness":"float","normal":"vector3","energyCompensation":"float"},"outputs":{"out":"BSDF"}},"ND_lama_mix_bsdf":{"node":"LamaMix","inputs":{"material1":"BSDF","material2":"BSDF","mix":"float"},"outputs":{"out":"BSDF"}},"ND_lama_mix_edf":{"node":"LamaMix","inputs":{"material1":"EDF","material2":"EDF","mix":"float"},"outputs":{"out":"EDF"}},"ND_lama_add_bsdf":{"node":"LamaAdd","inputs":{"material1":"BSDF","material2":"BSDF","weight1":"float","weight2":"float"},"outputs":{"out":"BSDF"}},"ND_lama_add_edf":{"node":"LamaAdd","inputs":{"material1":"EDF","material2":"EDF","weight1":"float","weight2":"float"},"outputs":{"out":"EDF"}},"ND_lama_conductor":{"node":"LamaConductor","inputs":{"tint":"color3","fresnelMode":"integer","IOR":"vector3","extinction":"vector3","reflectivity":"color3","edgeColor":"color3","roughness":"float","normal":"vector3","anisotropy":"float","anisotropyDirection":"vector3","anisotropyRotation":"float"},"outputs":{"out":"BSDF"}},"ND_lama_emission":{"node":"LamaEmission","inputs":{"color":"color3"},"outputs":{"out":"EDF"}},"ND_lama_surface":{"node":"LamaSurface","inputs":{"materialFront":"BSDF","materialBack":"BSDF","presence":"float"},"outputs":{"out":"material"}},"ND_lama_generalized_schlick":{"node":"LamaGeneralizedSchlick","inputs":{"reflectionTint":"color3","transmissionTint":"color3","fresnelMode":"integer","IOR":"vector3","reflectivity":"color3","reflectivity90":"color3","reflectivityProfile":"float","roughness":"float","normal":"vector3","anisotropy":"float","anisotropyDirection":"vector3","anisotropyRotation":"float","absorptionColor":"color3","absorptionRadius":"float","scatterColor":"color3","scatterAnisotropy":"float"},"outputs":{"out":"BSDF"}},"ND_lama_translucent":{"node":"LamaTranslucent","inputs":{"color":"color3","roughness":"float","normal":"vector3","energyCompensation":"float"},"outputs":{"out":"BSDF"}},"ND_lama_layer_bsdf":{"node":"LamaLayer","inputs":{"materialTop":"BSDF","materialBase":"BSDF","topMix":"float","topThickness":"float"},"outputs":{"out":"BSDF"}}},"byNode":{"oren_nayar_diffuse_bsdf":["ND_oren_nayar_diffuse_bsdf"],"burley_diffuse_bsdf":["ND_burley_diffuse_bsdf"],"translucent_bsdf":["ND_translucent_bsdf"],"dielectric_bsdf":["ND_dielectric_bsdf"],"conductor_bsdf":["ND_conductor_bsdf"],"generalized_schlick_bsdf":["ND_generalized_schlick_bsdf"],"subsurface_bsdf":["ND_subsurface_bsdf"],"sheen_bsdf":["ND_sheen_bsdf"],"chiang_hair_bsdf":["ND_chiang_hair_bsdf"],"uniform_edf":["ND_uniform_edf"],"conical_edf":["ND_conical_edf"],"measured_edf":["ND_measured_edf"],"generalized_schlick_edf":["ND_generalized_schlick_edf"],"absorption_vdf":["ND_absorption_vdf"],"anisotropic_vdf":["ND_anisotropic_vdf"],"surface":["ND_surface"],"volume":["ND_volume"],"light":["ND_light"],"displacement":["ND_displacement_float","ND_displacement_vector3"],"layer":["ND_layer_bsdf","ND_layer_vdf"],"mix":["ND_mix_bsdf","ND_mix_edf","ND_mix_vdf","ND_mix_float","ND_mix_color3","ND_mix_color3_color3","ND_mix_color4","ND_mix_color4_color4","ND_mix_vector2","ND_mix_vector2_vector2","ND_mix_vector3","ND_mix_vector3_vector3","ND_mix_vector4","ND_mix_vector4_vector4","ND_mix_surfaceshader","ND_mix_displacementshader","ND_mix_volumeshader"],"add":["ND_add_bsdf","ND_add_edf","ND_add_vdf","ND_add_float","ND_add_integer","ND_add_color3","ND_add_color4","ND_add_vector2","ND_add_vector3","ND_add_vector4","ND_add_matrix33","ND_add_matrix44","ND_add_color3FA","ND_add_color4FA","ND_add_vector2FA","ND_add_vector3FA","ND_add_vector4FA","ND_add_matrix33FA","ND_add_matrix44FA"],"multiply":["ND_multiply_bsdfC","ND_multiply_bsdfF","ND_multiply_edfC","ND_multiply_edfF","ND_multiply_vdfC","ND_multiply_vdfF","ND_multiply_float","ND_multiply_color3","ND_multiply_color4","ND_multiply_vector2","ND_multiply_vector3","ND_multiply_vector4","ND_multiply_matrix33","ND_multiply_matrix44","ND_multiply_color3FA","ND_multiply_color4FA","ND_multiply_vector2FA","ND_multiply_vector3FA","ND_multiply_vector4FA"],"roughness_anisotropy":["ND_roughness_anisotropy"],"roughness_dual":["ND_roughness_dual"],"glossiness_anisotropy":["ND_glossiness_anisotropy"],"blackbody":["ND_blackbody"],"artistic_ior":["ND_artistic_ior"],"deon_hair_absorption_from_melanin":["ND_deon_hair_absorption_from_melanin"],"chiang_hair_absorption_from_color":["ND_chiang_hair_absorption_from_color"],"chiang_hair_roughness":["ND_chiang_hair_roughness"],"disney_principled":["ND_disney_principled"],"open_pbr_surface":["ND_open_pbr_surface_surfaceshader"],"open_pbr_anisotropy":["ND_open_pbr_anisotropy"],"UsdPreviewSurface":["ND_UsdPreviewSurface_surfaceshader"],"UsdUVTexture":["ND_UsdUVTexture","ND_UsdUVTexture_23"],"UsdPrimvarReader":["ND_UsdPrimvarReader_integer","ND_UsdPrimvarReader_boolean","ND_UsdPrimvarReader_string","ND_UsdPrimvarReader_filename","ND_UsdPrimvarReader_float","ND_UsdPrimvarReader_vector2","ND_UsdPrimvarReader_vector3","ND_UsdPrimvarReader_vector4"],"UsdTransform2d":["ND_UsdTransform2d"],"standard_surface":["ND_standard_surface_surfaceshader","ND_standard_surface_surfaceshader_100"],"gltf_pbr":["ND_gltf_pbr_surfaceshader"],"gltf_colorimage":["ND_gltf_colorimage"],"gltf_image":["ND_gltf_image_color3_color3_1_0","ND_gltf_image_color4_color4_1_0","ND_gltf_image_float_float_1_0","ND_gltf_image_vector3_vector3_1_0"],"gltf_normalmap":["ND_gltf_normalmap_vector3_1_0"],"gltf_iridescence_thickness":["ND_gltf_iridescence_thickness_float_1_0"],"gltf_anisotropy_image":["ND_gltf_anisotropy_image"],"viewdirection":["ND_viewdirection_vector3"],"facingratio":["ND_facingratio_float"],"gooch_shade":["ND_gooch_shade"],"g18_rec709_to_lin_rec709":["ND_g18_rec709_to_lin_rec709_color3","ND_g18_rec709_to_lin_rec709_color4"],"g22_rec709_to_lin_rec709":["ND_g22_rec709_to_lin_rec709_color3","ND_g22_rec709_to_lin_rec709_color4"],"rec709_display_to_lin_rec709":["ND_rec709_display_to_lin_rec709_color3","ND_rec709_display_to_lin_rec709_color4"],"acescg_to_lin_rec709":["ND_acescg_to_lin_rec709_color3","ND_acescg_to_lin_rec709_color4"],"g22_ap1_to_lin_rec709":["ND_g22_ap1_to_lin_rec709_color3","ND_g22_ap1_to_lin_rec709_color4"],"srgb_texture_to_lin_rec709":["ND_srgb_texture_to_lin_rec709_color3","ND_srgb_texture_to_lin_rec709_color4"],"lin_adobergb_to_lin_rec709":["ND_lin_adobergb_to_lin_rec709_color3","ND_lin_adobergb_to_lin_rec709_color4"],"adobergb_to_lin_rec709":["ND_adobergb_to_lin_rec709_color3","ND_adobergb_to_lin_rec709_color4"],"srgb_displayp3_to_lin_rec709":["ND_srgb_displayp3_to_lin_rec709_color3","ND_srgb_displayp3_to_lin_rec709_color4"],"lin_displayp3_to_lin_rec709":["ND_lin_displayp3_to_lin_rec709_color3","ND_lin_displayp3_to_lin_rec709_color4"],"surfacematerial":["ND_surfacematerial"],"volumematerial":["ND_volumematerial"],"surface_unlit":["ND_surface_unlit"],"image":["ND_image_float","ND_image_color3","ND_image_color4","ND_image_vector2","ND_image_vector3","ND_image_vector4"],"tiledimage":["ND_tiledimage_float","ND_tiledimage_color3","ND_tiledimage_color4","ND_tiledimage_vector2","ND_tiledimage_vector3","ND_tiledimage_vector4"],"latlongimage":["ND_latlongimage"],"hextiledimage":["ND_hextiledimage_color3","ND_hextiledimage_color4"],"triplanarprojection":["ND_triplanarprojection_float","ND_triplanarprojection_color3","ND_triplanarprojection_color4","ND_triplanarprojection_vector2","ND_triplanarprojection_vector3","ND_triplanarprojection_vector4"],"constant":["ND_constant_float","ND_constant_color3","ND_constant_color4","ND_constant_vector2","ND_constant_vector3","ND_constant_vector4","ND_constant_boolean","ND_constant_integer","ND_constant_matrix33","ND_constant_matrix44","ND_constant_string","ND_constant_filename"],"ramp":["ND_ramp"],"ramp_gradient":["ND_ramp_gradient"],"ramplr":["ND_ramplr_float","ND_ramplr_color3","ND_ramplr_color4","ND_ramplr_vector2","ND_ramplr_vector3","ND_ramplr_vector4"],"ramptb":["ND_ramptb_float","ND_ramptb_color3","ND_ramptb_color4","ND_ramptb_vector2","ND_ramptb_vector3","ND_ramptb_vector4"],"ramp4":["ND_ramp4_float","ND_ramp4_color3","ND_ramp4_color4","ND_ramp4_vector2","ND_ramp4_vector3","ND_ramp4_vector4"],"splitlr":["ND_splitlr_float","ND_splitlr_color3","ND_splitlr_color4","ND_splitlr_vector2","ND_splitlr_vector3","ND_splitlr_vector4"],"splittb":["ND_splittb_float","ND_splittb_color3","ND_splittb_color4","ND_splittb_vector2","ND_splittb_vector3","ND_splittb_vector4"],"noise2d":["ND_noise2d_float","ND_noise2d_color3","ND_noise2d_color4","ND_noise2d_vector2","ND_noise2d_vector3","ND_noise2d_vector4","ND_noise2d_color3FA","ND_noise2d_color4FA","ND_noise2d_vector2FA","ND_noise2d_vector3FA","ND_noise2d_vector4FA"],"noise3d":["ND_noise3d_float","ND_noise3d_color3","ND_noise3d_color4","ND_noise3d_vector2","ND_noise3d_vector3","ND_noise3d_vector4","ND_noise3d_color3FA","ND_noise3d_color4FA","ND_noise3d_vector2FA","ND_noise3d_vector3FA","ND_noise3d_vector4FA"],"fractal2d":["ND_fractal2d_float","ND_fractal2d_color3","ND_fractal2d_color4","ND_fractal2d_vector2","ND_fractal2d_vector3","ND_fractal2d_vector4","ND_fractal2d_color3FA","ND_fractal2d_color4FA","ND_fractal2d_vector2FA","ND_fractal2d_vector3FA","ND_fractal2d_vector4FA"],"fractal3d":["ND_fractal3d_float","ND_fractal3d_color3","ND_fractal3d_color4","ND_fractal3d_vector2","ND_fractal3d_vector3","ND_fractal3d_vector4","ND_fractal3d_color3FA","ND_fractal3d_color4FA","ND_fractal3d_vector2FA","ND_fractal3d_vector3FA","ND_fractal3d_vector4FA"],"cellnoise2d":["ND_cellnoise2d_float"],"cellnoise3d":["ND_cellnoise3d_float"],"worleynoise2d":["ND_worleynoise2d_float","ND_worleynoise2d_vector2","ND_worleynoise2d_vector3"],"worleynoise3d":["ND_worleynoise3d_float","ND_worleynoise3d_vector2","ND_worleynoise3d_vector3"],"unifiednoise2d":["ND_unifiednoise2d_float"],"unifiednoise3d":["ND_unifiednoise3d_float"],"flake2d":["ND_flake2d"],"flake3d":["ND_flake3d"],"randomfloat":["ND_randomfloat_float","ND_randomfloat_integer"],"randomcolor":["ND_randomcolor_float","ND_randomcolor_integer"],"checkerboard":["ND_checkerboard_color3"],"line":["ND_line_float"],"circle":["ND_circle_float"],"cloverleaf":["ND_cloverleaf_float"],"hexagon":["ND_hexagon_float"],"grid":["ND_grid_color3"],"crosshatch":["ND_crosshatch_color3"],"tiledcircles":["ND_tiledcircles_color3"],"tiledcloverleafs":["ND_tiledcloverleafs_color3"],"tiledhexagons":["ND_tiledhexagons_color3"],"position":["ND_position_vector3"],"normal":["ND_normal_vector3"],"tangent":["ND_tangent_vector3"],"bitangent":["ND_bitangent_vector3"],"texcoord":["ND_texcoord_vector2","ND_texcoord_vector3"],"geomcolor":["ND_geomcolor_float","ND_geomcolor_color3","ND_geomcolor_color4"],"geompropvalue":["ND_geompropvalue_integer","ND_geompropvalue_boolean","ND_geompropvalue_float","ND_geompropvalue_color3","ND_geompropvalue_color4","ND_geompropvalue_vector2","ND_geompropvalue_vector3","ND_geompropvalue_vector4"],"geompropvalueuniform":["ND_geompropvalueuniform_string","ND_geompropvalueuniform_filename"],"bump":["ND_bump_vector3"],"frame":["ND_frame_float"],"time":["ND_time_float"],"subtract":["ND_subtract_float","ND_subtract_integer","ND_subtract_color3","ND_subtract_color4","ND_subtract_vector2","ND_subtract_vector3","ND_subtract_vector4","ND_subtract_matrix33","ND_subtract_matrix44","ND_subtract_color3FA","ND_subtract_color4FA","ND_subtract_vector2FA","ND_subtract_vector3FA","ND_subtract_vector4FA","ND_subtract_matrix33FA","ND_subtract_matrix44FA"],"divide":["ND_divide_float","ND_divide_color3","ND_divide_color4","ND_divide_vector2","ND_divide_vector3","ND_divide_vector4","ND_divide_matrix33","ND_divide_matrix44","ND_divide_color3FA","ND_divide_color4FA","ND_divide_vector2FA","ND_divide_vector3FA","ND_divide_vector4FA"],"modulo":["ND_modulo_float","ND_modulo_color3","ND_modulo_color4","ND_modulo_vector2","ND_modulo_vector3","ND_modulo_vector4","ND_modulo_color3FA","ND_modulo_color4FA","ND_modulo_vector2FA","ND_modulo_vector3FA","ND_modulo_vector4FA"],"fract":["ND_fract_float","ND_fract_color3","ND_fract_color4","ND_fract_vector2","ND_fract_vector3","ND_fract_vector4"],"invert":["ND_invert_float","ND_invert_color3","ND_invert_color4","ND_invert_vector2","ND_invert_vector3","ND_invert_vector4","ND_invert_color3FA","ND_invert_color4FA","ND_invert_vector2FA","ND_invert_vector3FA","ND_invert_vector4FA"],"absval":["ND_absval_float","ND_absval_color3","ND_absval_color4","ND_absval_vector2","ND_absval_vector3","ND_absval_vector4"],"floor":["ND_floor_float","ND_floor_color3","ND_floor_color4","ND_floor_vector2","ND_floor_vector3","ND_floor_vector4","ND_floor_integer"],"ceil":["ND_ceil_float","ND_ceil_color3","ND_ceil_color4","ND_ceil_vector2","ND_ceil_vector3","ND_ceil_vector4","ND_ceil_integer"],"round":["ND_round_float","ND_round_color3","ND_round_color4","ND_round_vector2","ND_round_vector3","ND_round_vector4","ND_round_integer"],"power":["ND_power_float","ND_power_color3","ND_power_color4","ND_power_vector2","ND_power_vector3","ND_power_vector4","ND_power_color3FA","ND_power_color4FA","ND_power_vector2FA","ND_power_vector3FA","ND_power_vector4FA"],"safepower":["ND_safepower_float","ND_safepower_color3","ND_safepower_color4","ND_safepower_vector2","ND_safepower_vector3","ND_safepower_vector4","ND_safepower_color3FA","ND_safepower_color4FA","ND_safepower_vector2FA","ND_safepower_vector3FA","ND_safepower_vector4FA"],"sin":["ND_sin_float","ND_sin_vector2","ND_sin_vector3","ND_sin_vector4"],"cos":["ND_cos_float","ND_cos_vector2","ND_cos_vector3","ND_cos_vector4"],"tan":["ND_tan_float","ND_tan_vector2","ND_tan_vector3","ND_tan_vector4"],"asin":["ND_asin_float","ND_asin_vector2","ND_asin_vector3","ND_asin_vector4"],"acos":["ND_acos_float","ND_acos_vector2","ND_acos_vector3","ND_acos_vector4"],"atan2":["ND_atan2_float","ND_atan2_vector2","ND_atan2_vector3","ND_atan2_vector4"],"sqrt":["ND_sqrt_float","ND_sqrt_vector2","ND_sqrt_vector3","ND_sqrt_vector4"],"ln":["ND_ln_float","ND_ln_vector2","ND_ln_vector3","ND_ln_vector4"],"exp":["ND_exp_float","ND_exp_vector2","ND_exp_vector3","ND_exp_vector4"],"sign":["ND_sign_float","ND_sign_color3","ND_sign_color4","ND_sign_vector2","ND_sign_vector3","ND_sign_vector4"],"clamp":["ND_clamp_float","ND_clamp_color3","ND_clamp_color4","ND_clamp_vector2","ND_clamp_vector3","ND_clamp_vector4","ND_clamp_color3FA","ND_clamp_color4FA","ND_clamp_vector2FA","ND_clamp_vector3FA","ND_clamp_vector4FA"],"min":["ND_min_float","ND_min_color3","ND_min_color4","ND_min_vector2","ND_min_vector3","ND_min_vector4","ND_min_color3FA","ND_min_color4FA","ND_min_vector2FA","ND_min_vector3FA","ND_min_vector4FA"],"max":["ND_max_float","ND_max_color3","ND_max_color4","ND_max_vector2","ND_max_vector3","ND_max_vector4","ND_max_color3FA","ND_max_color4FA","ND_max_vector2FA","ND_max_vector3FA","ND_max_vector4FA"],"normalize":["ND_normalize_vector2","ND_normalize_vector3","ND_normalize_vector4"],"magnitude":["ND_magnitude_vector2","ND_magnitude_vector3","ND_magnitude_vector4"],"distance":["ND_distance_vector2","ND_distance_vector3","ND_distance_vector4"],"dotproduct":["ND_dotproduct_vector2","ND_dotproduct_vector3","ND_dotproduct_vector4"],"crossproduct":["ND_crossproduct_vector3"],"transformpoint":["ND_transformpoint_vector3"],"transformvector":["ND_transformvector_vector3"],"transformnormal":["ND_transformnormal_vector3"],"transformmatrix":["ND_transformmatrix_vector2M3","ND_transformmatrix_vector3","ND_transformmatrix_vector3M4","ND_transformmatrix_vector4"],"normalmap":["ND_normalmap_float","ND_normalmap_vector2"],"hextilednormalmap":["ND_hextilednormalmap_vector3"],"transpose":["ND_transpose_matrix33","ND_transpose_matrix44"],"determinant":["ND_determinant_matrix33","ND_determinant_matrix44"],"invertmatrix":["ND_invertmatrix_matrix33","ND_invertmatrix_matrix44"],"rotate2d":["ND_rotate2d_vector2"],"rotate3d":["ND_rotate3d_vector3"],"place2d":["ND_place2d_vector2"],"trianglewave":["ND_trianglewave_float"],"reflect":["ND_reflect_vector3"],"refract":["ND_refract_vector3"],"remap":["ND_remap_float","ND_remap_color3","ND_remap_color4","ND_remap_vector2","ND_remap_vector3","ND_remap_vector4","ND_remap_color3FA","ND_remap_color4FA","ND_remap_vector2FA","ND_remap_vector3FA","ND_remap_vector4FA"],"smoothstep":["ND_smoothstep_float","ND_smoothstep_color3","ND_smoothstep_color4","ND_smoothstep_vector2","ND_smoothstep_vector3","ND_smoothstep_vector4","ND_smoothstep_color3FA","ND_smoothstep_color4FA","ND_smoothstep_vector2FA","ND_smoothstep_vector3FA","ND_smoothstep_vector4FA"],"luminance":["ND_luminance_color3","ND_luminance_color4"],"rgbtohsv":["ND_rgbtohsv_color3","ND_rgbtohsv_color4"],"hsvtorgb":["ND_hsvtorgb_color3","ND_hsvtorgb_color4"],"contrast":["ND_contrast_float","ND_contrast_color3","ND_contrast_color4","ND_contrast_vector2","ND_contrast_vector3","ND_contrast_vector4","ND_contrast_color3FA","ND_contrast_color4FA","ND_contrast_vector2FA","ND_contrast_vector3FA","ND_contrast_vector4FA"],"range":["ND_range_float","ND_range_color3","ND_range_color4","ND_range_vector2","ND_range_vector3","ND_range_vector4","ND_range_color3FA","ND_range_color4FA","ND_range_vector2FA","ND_range_vector3FA","ND_range_vector4FA"],"hsvadjust":["ND_hsvadjust_color3","ND_hsvadjust_color4"],"saturate":["ND_saturate_color3","ND_saturate_color4"],"colorcorrect":["ND_colorcorrect_color3","ND_colorcorrect_color4"],"premult":["ND_premult_color4"],"unpremult":["ND_unpremult_color4"],"plus":["ND_plus_float","ND_plus_color3","ND_plus_color4"],"minus":["ND_minus_float","ND_minus_color3","ND_minus_color4"],"difference":["ND_difference_float","ND_difference_color3","ND_difference_color4"],"burn":["ND_burn_float","ND_burn_color3","ND_burn_color4"],"dodge":["ND_dodge_float","ND_dodge_color3","ND_dodge_color4"],"screen":["ND_screen_float","ND_screen_color3","ND_screen_color4"],"overlay":["ND_overlay_float","ND_overlay_color3","ND_overlay_color4"],"disjointover":["ND_disjointover_color4"],"in":["ND_in_color4"],"mask":["ND_mask_color4"],"matte":["ND_matte_color4"],"out":["ND_out_color4"],"over":["ND_over_color4"],"inside":["ND_inside_float","ND_inside_color3","ND_inside_color4"],"outside":["ND_outside_float","ND_outside_color3","ND_outside_color4"],"ifgreater":["ND_ifgreater_float","ND_ifgreater_integer","ND_ifgreater_color3","ND_ifgreater_color4","ND_ifgreater_vector2","ND_ifgreater_vector3","ND_ifgreater_vector4","ND_ifgreater_matrix33","ND_ifgreater_matrix44","ND_ifgreater_boolean","ND_ifgreater_floatI","ND_ifgreater_integerI","ND_ifgreater_color3I","ND_ifgreater_color4I","ND_ifgreater_vector2I","ND_ifgreater_vector3I","ND_ifgreater_vector4I","ND_ifgreater_matrix33I","ND_ifgreater_matrix44I","ND_ifgreater_booleanI"],"ifgreatereq":["ND_ifgreatereq_float","ND_ifgreatereq_integer","ND_ifgreatereq_color3","ND_ifgreatereq_color4","ND_ifgreatereq_vector2","ND_ifgreatereq_vector3","ND_ifgreatereq_vector4","ND_ifgreatereq_matrix33","ND_ifgreatereq_matrix44","ND_ifgreatereq_boolean","ND_ifgreatereq_floatI","ND_ifgreatereq_integerI","ND_ifgreatereq_color3I","ND_ifgreatereq_color4I","ND_ifgreatereq_vector2I","ND_ifgreatereq_vector3I","ND_ifgreatereq_vector4I","ND_ifgreatereq_matrix33I","ND_ifgreatereq_matrix44I","ND_ifgreatereq_booleanI"],"ifequal":["ND_ifequal_float","ND_ifequal_integer","ND_ifequal_color3","ND_ifequal_color4","ND_ifequal_vector2","ND_ifequal_vector3","ND_ifequal_vector4","ND_ifequal_matrix33","ND_ifequal_matrix44","ND_ifequal_boolean","ND_ifequal_floatI","ND_ifequal_integerI","ND_ifequal_color3I","ND_ifequal_color4I","ND_ifequal_vector2I","ND_ifequal_vector3I","ND_ifequal_vector4I","ND_ifequal_matrix33I","ND_ifequal_matrix44I","ND_ifequal_booleanI","ND_ifequal_floatB","ND_ifequal_integerB","ND_ifequal_color3B","ND_ifequal_color4B","ND_ifequal_vector2B","ND_ifequal_vector3B","ND_ifequal_vector4B","ND_ifequal_matrix33B","ND_ifequal_matrix44B","ND_ifequal_booleanB"],"switch":["ND_switch_float","ND_switch_color3","ND_switch_color4","ND_switch_vector2","ND_switch_vector3","ND_switch_vector4","ND_switch_matrix33","ND_switch_matrix44","ND_switch_floatI","ND_switch_color3I","ND_switch_color4I","ND_switch_vector2I","ND_switch_vector3I","ND_switch_vector4I","ND_switch_matrix33I","ND_switch_matrix44I"],"convert":["ND_convert_float_color3","ND_convert_float_color4","ND_convert_float_vector2","ND_convert_float_vector3","ND_convert_float_vector4","ND_convert_color3_color4","ND_convert_color3_vector2","ND_convert_color3_vector3","ND_convert_color3_vector4","ND_convert_color4_color3","ND_convert_color4_vector2","ND_convert_color4_vector3","ND_convert_color4_vector4","ND_convert_vector2_color3","ND_convert_vector2_color4","ND_convert_vector2_vector3","ND_convert_vector2_vector4","ND_convert_vector3_color3","ND_convert_vector3_color4","ND_convert_vector3_vector2","ND_convert_vector3_vector4","ND_convert_vector4_color3","ND_convert_vector4_color4","ND_convert_vector4_vector2","ND_convert_vector4_vector3","ND_convert_boolean_float","ND_convert_boolean_color3","ND_convert_boolean_color4","ND_convert_boolean_vector2","ND_convert_boolean_vector3","ND_convert_boolean_vector4","ND_convert_boolean_integer","ND_convert_integer_float","ND_convert_integer_color3","ND_convert_integer_color4","ND_convert_integer_vector2","ND_convert_integer_vector3","ND_convert_integer_vector4","ND_convert_integer_boolean","ND_convert_color3_surfaceshader","ND_convert_color4_surfaceshader","ND_convert_float_surfaceshader","ND_convert_vector2_surfaceshader","ND_convert_vector3_surfaceshader","ND_convert_vector4_surfaceshader","ND_convert_integer_surfaceshader","ND_convert_boolean_surfaceshader"],"combine2":["ND_combine2_vector2","ND_combine2_color4CF","ND_combine2_vector4VF","ND_combine2_vector4VV"],"combine3":["ND_combine3_color3","ND_combine3_vector3"],"combine4":["ND_combine4_color4","ND_combine4_vector4"],"creatematrix":["ND_creatematrix_vector3_matrix33","ND_creatematrix_vector3_matrix44","ND_creatematrix_vector4_matrix44"],"extract":["ND_extract_color3","ND_extract_color4","ND_extract_vector2","ND_extract_vector3","ND_extract_vector4","ND_extract_matrix33","ND_extract_matrix44"],"separate2":["ND_separate2_vector2"],"separate3":["ND_separate3_color3","ND_separate3_vector3"],"separate4":["ND_separate4_color4","ND_separate4_vector4"],"blur":["ND_blur_float","ND_blur_color3","ND_blur_color4","ND_blur_vector2","ND_blur_vector3","ND_blur_vector4"],"heighttonormal":["ND_heighttonormal_vector3"],"and":["ND_logical_and"],"or":["ND_logical_or"],"xor":["ND_logical_xor"],"not":["ND_logical_not"],"dot":["ND_dot_float","ND_dot_color3","ND_dot_color4","ND_dot_vector2","ND_dot_vector3","ND_dot_vector4","ND_dot_boolean","ND_dot_integer","ND_dot_matrix33","ND_dot_matrix44","ND_dot_string","ND_dot_filename","ND_dot_surfaceshader","ND_dot_displacementshader","ND_dot_volumeshader","ND_dot_lightshader"],"point_light":["ND_point_light"],"directional_light":["ND_directional_light"],"spot_light":["ND_spot_light"],"open_pbr_surface_to_standard_surface":["ND_open_pbr_surface_to_standard_surface"],"standard_surface_to_open_pbr_surface":["ND_standard_surface_to_open_pbr_surface"],"standard_surface_to_UsdPreviewSurface":["ND_standard_surface_to_UsdPreviewSurface"],"standard_surface_to_gltf_pbr":["ND_standard_surface_to_gltf_pbr"],"LamaSheen":["ND_lama_sheen"],"LamaSSS":["ND_lama_sss"],"LamaDielectric":["ND_lama_dielectric"],"LamaIridescence":["ND_lama_iridescence"],"LamaDiffuse":["ND_lama_diffuse"],"LamaMix":["ND_lama_mix_bsdf","ND_lama_mix_edf"],"LamaAdd":["ND_lama_add_bsdf","ND_lama_add_edf"],"LamaConductor":["ND_lama_conductor"],"LamaEmission":["ND_lama_emission"],"LamaSurface":["ND_lama_surface"],"LamaGeneralizedSchlick":["ND_lama_generalized_schlick"],"LamaTranslucent":["ND_lama_translucent"],"LamaLayer":["ND_lama_layer_bsdf"]}}; + +export default registryData; diff --git a/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js b/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js new file mode 100644 index 00000000000000..2e824f03593b86 --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXNodeLibrary.js @@ -0,0 +1,1021 @@ +import { + abs, + add, + clamp, + floor, + ceil, + round, + sign, + sin, + cos, + tan, + asin, + acos, + sqrt, + log, + exp, + min, + max, + normalize, + length, + dot, + cross, + mul, + div, + pow, + distance, + remap, + luminance, + mx_rgbtohsv, + mx_hsvtorgb, + mix, + saturation as mx_saturation, + transpose, + determinant, + inverse, + mat3, + mx_ramp4, + mx_ramplr, + mx_ramptb, + mx_splitlr, + mx_splittb, + mx_fractal_noise_float, + mx_fractal_noise_vec3, + mx_noise_float, + mx_noise_vec3, + mx_cell_noise_float, + mx_cell_noise_vec3, + mx_smoothstep, + mx_worley_noise_float_2d, + mx_worley_noise_float_3d, + mx_worley_noise_vec3_style, + mx_unifiednoise2d, + mx_unifiednoise3d, + mx_modulo, + mx_invert, + mx_place2d, + mx_rotate2d, + mx_rotate3d, + mx_safepower, + mx_contrast, + element, + reflect, + refract, + mx_timer, + mx_frame, + mx_ifgreater, + mx_ifgreatereq, + mx_ifequal, + mx_atan2, + positionLocal, + positionWorld, + normalWorld, + tangentWorld, + bitangentWorld, + cameraPosition, + mx_heighttonormal, + float, + int, + bool, + color, + modelNormalMatrix, + modelWorldMatrix, + modelWorldMatrixInverse, + vec2, + vec3, + vec4, + fract, + sub, + step, + and as tslAnd, + or as tslOr, + xor as tslXor, + not as tslNot, + Fn, + Loop, +} from 'three/tsl'; +import { normalizeSpaceName, toBooleanNode, toVec3Channels } from './MaterialXUtils.js'; + +const createMXElement = ( name, nodeFunc, params = [], defaults = {}, usesNode = false ) => ( { name, nodeFunc, params, defaults, usesNode } ); + +const mx_range = ( inNode, inLow, inHigh, outLow, outHigh, gamma = 1 ) => { + + const inSpan = max( sub( inHigh, inLow ), 1e-6 ); + const normalized = div( sub( inNode, inLow ), inSpan ); + const reciprocalGamma = div( 1, gamma ); + const gammaApplied = mul( pow( abs( normalized ), reciprocalGamma ), sign( normalized ) ); + return add( outLow, mul( gammaApplied, sub( outHigh, outLow ) ) ); + +}; + +const mx_open_pbr_anisotropy = ( roughness = 0, anisotropy = 0 ) => { + + const anisoInvert = sub( float( 1 ), anisotropy ); + const anisoInvertSq = mul( anisoInvert, anisoInvert ); + const denom = add( anisoInvertSq, float( 1 ) ); + const fraction = div( float( 2 ), denom ); + const sqrtFraction = sqrt( fraction ); + const roughSq = mul( roughness, roughness ); + const alphaX = mul( roughSq, sqrtFraction ); + const alphaY = mul( anisoInvert, alphaX ); + return vec2( alphaX, alphaY ); + +}; + +const mx_boolean = ( inNode ) => toBooleanNode( inNode ); +const mx_and = ( in1, in2 ) => tslAnd( mx_boolean( in1 ), mx_boolean( in2 ) ); +const mx_or = ( in1, in2 ) => tslOr( mx_boolean( in1 ), mx_boolean( in2 ) ); +const mx_xor = ( in1, in2 ) => tslXor( mx_boolean( in1 ), mx_boolean( in2 ) ); +const mx_not = ( inNode ) => tslNot( mx_boolean( inNode ) ); +const mx_checkerboard = ( color1, color2, uvtiling, uvoffset, texcoord ) => { + + const tiledUv = sub( mul( texcoord, uvtiling ), uvoffset ); + const checkerMix = mx_modulo( dot( floor( tiledUv ), vec2( 1, 1 ) ), float( 2 ) ); + return mix( color2, color1, checkerMix ); + +}; + +const mx_circle = ( texcoord, center, radius ) => { + + const delta = sub( texcoord, center ); + const distanceSquared = dot( delta, delta ); + const radiusSquared = mul( radius, radius ); + return mx_ifgreater( distanceSquared, radiusSquared, 0, 1 ); + +}; + +const mx_normalmap = ( + value = vec3( 0.5, 0.5, 1.0 ), + scale = 1.0, + normal = vec3( 0.0, 0.0, 1.0 ), + tangent = vec3( 1.0, 0.0, 0.0 ), + bitangent = vec3( 0.0, 1.0, 0.0 ), +) => { + + const mapValue = toVec3Channels( value ); + const decoded = sub( mul( mapValue, 2.0 ), vec3( 1.0, 1.0, 1.0 ) ); + const safeValue = dot( mapValue, mapValue ).equal( 0 ).mix( decoded, vec3( 0.0, 0.0, 1.0 ) ); + const normalScale = vec2( scale ); + const blended = + add( + add( + mul( tangent, mul( element( safeValue, 0 ), element( normalScale, 0 ) ) ), + mul( bitangent, mul( element( safeValue, 1 ), element( normalScale, 1 ) ) ), + ), + mul( normal, element( safeValue, 2 ) ), + ); + return normalize( blended ); + +}; + +const mx_bump = ( + height, + scale = 1, + normal = vec3( 0.0, 0.0, 1.0 ), + tangent = vec3( 1.0, 0.0, 0.0 ), + bitangent = vec3( 0.0, 1.0, 0.0 ), +) => mx_normalmap( mx_heighttonormal( height, 1 ), scale, normal, tangent, bitangent ); +const mx_dot = ( inNode ) => inNode; + +const mx_viewdirection = ( space = 'world' ) => { + + const outputSpace = normalizeSpaceName( space, 'world' ); + const worldDirection = normalize( sub( positionWorld, cameraPosition ) ); + + if ( outputSpace === 'world' ) { + + return worldDirection; + + } + + return mx_transformnormal( worldDirection, 'world', outputSpace ); + +}; + +const mx_blackbody = ( temperature = 5000 ) => { + + const temperatureKelvin = clamp( temperature, float( 800 ), float( 25000 ) ); + const t = div( float( 1000 ), temperatureKelvin ); + const t2 = mul( t, t ); + const t3 = mul( t2, t ); + const lowX = add( add( mul( float( - 0.2661239 ), t3 ), mul( float( - 0.234358 ), t2 ) ), add( mul( float( 0.8776956 ), t ), float( 0.17991 ) ) ); + const highX = add( + add( mul( float( - 3.0258469 ), t3 ), mul( float( 2.1070379 ), t2 ) ), + add( mul( float( 0.2226347 ), t ), float( 0.24039 ) ), + ); + const xc = mx_ifgreatereq( temperatureKelvin, float( 4000 ), highX, lowX ); + const xc2 = mul( xc, xc ); + const xc3 = mul( xc2, xc ); + const ycLow = add( + add( mul( float( - 1.1063814 ), xc3 ), mul( float( - 1.3481102 ), xc2 ) ), + add( mul( float( 2.18555832 ), xc ), float( - 0.20219683 ) ), + ); + const ycMid = add( + add( mul( float( - 0.9549476 ), xc3 ), mul( float( - 1.37418593 ), xc2 ) ), + add( mul( float( 2.09137015 ), xc ), float( - 0.16748867 ) ), + ); + const ycHigh = add( + add( mul( float( 3.081758 ), xc3 ), mul( float( - 5.8733867 ), xc2 ) ), + add( mul( float( 3.75112997 ), xc ), float( - 0.37001483 ) ), + ); + const ycLowMid = mx_ifgreatereq( temperatureKelvin, float( 2222 ), ycMid, ycLow ); + const yc = mx_ifgreatereq( temperatureKelvin, float( 4000 ), ycHigh, ycLowMid ); + const safeYc = max( yc, float( 1e-6 ) ); + const xyz = vec3( div( xc, safeYc ), float( 1 ), div( sub( sub( float( 1 ), xc ), yc ), safeYc ) ); + const rgb = vec3( + add( add( mul( float( 3.2406 ), element( xyz, 0 ) ), mul( float( - 1.5372 ), element( xyz, 1 ) ) ), mul( float( - 0.4986 ), element( xyz, 2 ) ) ), + add( add( mul( float( - 0.9689 ), element( xyz, 0 ) ), mul( float( 1.8758 ), element( xyz, 1 ) ) ), mul( float( 0.0415 ), element( xyz, 2 ) ) ), + add( add( mul( float( 0.0557 ), element( xyz, 0 ) ), mul( float( - 0.204 ), element( xyz, 1 ) ) ), mul( float( 1.057 ), element( xyz, 2 ) ) ), + ); + const clampedRgb = max( rgb, vec3( 0, 0, 0 ) ); + const validYcMask = step( float( 1e-6 ), yc ); + return mix( vec3( 1, 1, 1 ), clampedRgb, validYcMask ); + +}; + +const mx_unpremult = ( input ) => { + + const alpha = element( input, 3 ); + const rgb = toVec3Channels( input ); + const unpremultiplied = alpha.equal( 0 ).mix( rgb, div( rgb, alpha ) ); + return vec4( unpremultiplied, alpha ); + +}; + +const mx_colorcorrect = ( + input, + hue = 0, + saturationAmount = 1, + gamma = 1, + lift = 0, + gain = 1, + contrast = 1, + contrastPivot = 0.5, + exposure = 0, +) => { + + const rgbInput = toVec3Channels( input ); + const hsv = mx_rgbtohsv( rgbInput ); + const hueAdjusted = mx_hsvtorgb( add( hsv, vec3( hue, 0, 0 ) ) ); + const saturationAdjusted = mx_saturation( hueAdjusted, saturationAmount ); + const gammaAdjusted = mx_range( saturationAdjusted, 0, 1, 0, 1, gamma ); + const liftApplied = add( mul( gammaAdjusted, sub( 1, lift ) ), lift ); + const gainApplied = mul( liftApplied, gain ); + const contrastApplied = mx_contrast( gainApplied, contrast, contrastPivot ); + const exposureApplied = mul( contrastApplied, pow( 2, exposure ) ); + const preserveAlpha = input && ( input.nodeType === 'vec4' || input.nodeType === 'color4' ); + return preserveAlpha ? vec4( exposureApplied, element( input, 3 ) ) : exposureApplied; + +}; + +const mx_minus = ( fg, bg, mixval = 1 ) => add( mul( mixval, sub( bg, fg ) ), mul( sub( 1, mixval ), bg ) ); +const mx_difference = ( fg, bg, mixval = 1 ) => add( mul( mixval, abs( sub( bg, fg ) ) ), mul( sub( 1, mixval ), bg ) ); +const mx_screen = ( fg, bg, mixval = 1 ) => { + + const screened = sub( 1, mul( sub( 1, fg ), sub( 1, bg ) ) ); + return mix( bg, screened, mixval ); + +}; + +const mx_overlay = ( fg, bg, mixval = 1 ) => { + + const lowBranch = mul( mul( 2, fg ), bg ); + const highBranch = sub( 1, mul( mul( 2, sub( 1, fg ) ), sub( 1, bg ) ) ); + const overlayed = mix( lowBranch, highBranch, step( 0.5, bg ) ); + return mix( bg, overlayed, mixval ); + +}; + +const mx_transformnormal = ( inNode = vec3( 0, 0, 1 ), fromspace = 'world', tospace = 'world' ) => { + + const from = normalizeSpaceName( fromspace, 'world' ); + const to = normalizeSpaceName( tospace, 'world' ); + const inNormal = vec3( inNode ); + + if ( from === to ) { + + return normalize( inNormal ); + + } + + if ( from === 'object' && to === 'world' ) { + + return normalize( mul( inNormal, modelNormalMatrix ) ); + + } + + return normalize( mul( inNormal, mat3( modelWorldMatrix ) ) ); + +}; + +const mx_transformvector = ( inNode = vec3( 0, 0, 0 ), fromspace = 'world', tospace = 'world' ) => { + + const from = normalizeSpaceName( fromspace, 'world' ); + const to = normalizeSpaceName( tospace, 'world' ); + const inVector = vec3( inNode ); + + if ( from === to ) { + + return inVector; + + } + + if ( from === 'object' && to === 'world' ) { + + return mul( inVector, mat3( modelWorldMatrix ) ); + + } + + return mul( inVector, mat3( modelWorldMatrixInverse ) ); + +}; + +const mx_transformpoint = ( inNode = vec3( 0, 0, 0 ), fromspace = 'world', tospace = 'world' ) => { + + const from = normalizeSpaceName( fromspace, 'world' ); + const to = normalizeSpaceName( tospace, 'world' ); + const inPoint = vec3( inNode ); + + if ( from === to ) { + + return inPoint; + + } + + const point4 = vec4( inPoint, 1 ); + const matrix = from === 'object' && to === 'world' ? modelWorldMatrix : modelWorldMatrixInverse; + const transformed4 = mul( matrix, point4 ); + return vec3( element( transformed4, 0 ), element( transformed4, 1 ), element( transformed4, 2 ) ); + +}; + +const mx_burn_channel = ( fg, bg, mixval = 1 ) => { + + const composed = add( mul( mixval, sub( 1, div( sub( 1, bg ), fg ) ) ), mul( sub( 1, mixval ), bg ) ); + return mul( composed, step( float( 1e-6 ), abs( fg ) ) ); + +}; + +const mx_dodge_channel = ( fg, bg, mixval = 1 ) => { + + const composed = add( mul( mixval, div( bg, sub( 1, fg ) ) ), mul( sub( 1, mixval ), bg ) ); + return mul( composed, step( float( 1e-6 ), abs( sub( 1, fg ) ) ) ); + +}; + +const isVec3Like = ( node ) => + node && ( node.nodeType === 'vec3' || node.nodeType === 'color' || node.nodeType === 'color3' ); +const isVec4Like = ( node ) => node && ( node.nodeType === 'vec4' || node.nodeType === 'color4' ); + +const applyBlendByChannel = ( channelFunc, fg, bg, mixval = 1 ) => { + + if ( isVec4Like( fg ) || isVec4Like( bg ) ) { + + return vec4( + channelFunc( element( fg, 0 ), element( bg, 0 ), mixval ), + channelFunc( element( fg, 1 ), element( bg, 1 ), mixval ), + channelFunc( element( fg, 2 ), element( bg, 2 ), mixval ), + channelFunc( element( fg, 3 ), element( bg, 3 ), mixval ), + ); + + } + + if ( isVec3Like( fg ) || isVec3Like( bg ) ) { + + return vec3( + channelFunc( element( fg, 0 ), element( bg, 0 ), mixval ), + channelFunc( element( fg, 1 ), element( bg, 1 ), mixval ), + channelFunc( element( fg, 2 ), element( bg, 2 ), mixval ), + ); + + } + + return channelFunc( fg, bg, mixval ); + +}; + +const mx_burn = ( fg, bg, mixval = 1 ) => applyBlendByChannel( mx_burn_channel, fg, bg, mixval ); +const mx_dodge = ( fg, bg, mixval = 1 ) => applyBlendByChannel( mx_dodge_channel, fg, bg, mixval ); + +const mixColor4 = ( bg, fg, factor ) => + vec4( + mix( element( bg, 0 ), element( fg, 0 ), factor ), + mix( element( bg, 1 ), element( fg, 1 ), factor ), + mix( element( bg, 2 ), element( fg, 2 ), factor ), + mix( element( bg, 3 ), element( fg, 3 ), factor ), + ); + +const mxRampSegment = ( x, color1, color2, interval1, interval2, interpolation ) => { + + const linearClamped = clamp( x, interval1, interval2 ); + const rangeSize = sub( interval2, interval1 ); + const safeRange = max( rangeSize, float( 1e-6 ) ); + const linearRemap = div( sub( linearClamped, interval1 ), safeRange ); + const smoothVal = mx_smoothstep( x, interval1, interval2 ); + const interpolationDistanceToLinear = abs( sub( interpolation, float( 0 ) ) ); + const useLinear = sub( float( 1 ), step( float( 0.5 ), interpolationDistanceToLinear ) ); + const interpFactor = mix( smoothVal, linearRemap, useLinear ); + const mixedColor = mixColor4( color1, color2, interpFactor ); + const stepColor = mixColor4( color1, color2, step( interval2, x ) ); + const interpolationDistanceToStep = abs( sub( interpolation, float( 2 ) ) ); + const useStep = sub( float( 1 ), step( float( 0.5 ), interpolationDistanceToStep ) ); + return mixColor4( mixedColor, stepColor, useStep ); + +}; + +const mx_ramp_gradient = ( + x = 0, + interval1 = 0, + interval2 = 1, + color1 = vec4( 0, 0, 0, 1 ), + color2 = vec4( 1, 1, 1, 1 ), + interpolation = 1, + prevColor = vec4( 0, 0, 0, 1 ), + intervalNum = 1, + numIntervals = 2, +) => { + + const xFloat = float( x ); + const interval1Float = float( interval1 ); + const interval2Float = float( interval2 ); + const interpolationFloat = float( interpolation ); + const intervalNumFloat = float( intervalNum ); + const numIntervalsFloat = float( numIntervals ); + const interpolated = mxRampSegment( xFloat, color1, color2, interval1Float, interval2Float, interpolationFloat ); + const withinInterval = mixColor4( prevColor, interpolated, step( add( interval1Float, float( 1e-6 ) ), xFloat ) ); + return mixColor4( withinInterval, prevColor, step( numIntervalsFloat, intervalNumFloat ) ); + +}; + +const mx_ramp = ( texcoord = vec2( 0, 0 ), type = 0, interpolation = 1, numIntervals = 2, ...rest ) => { + + const rampTypeFloat = float( type ); + const interpolationFloat = float( interpolation ); + const numIntervalsFloat = float( numIntervals ); + + const clamped = clamp( texcoord, vec2( 0, 0 ), vec2( 1, 1 ) ); + const s = element( clamped, 0 ); + const t = element( clamped, 1 ); + + const centeredS = sub( s, float( 0.5 ) ); + const centeredT = sub( t, float( 0.5 ) ); + + const radialDist = sqrt( add( mul( centeredS, centeredS ), mul( centeredT, centeredT ) ) ); + const radialVal = clamp( mul( radialDist, float( 2 ) ), float( 0 ), float( 1 ) ); + const circularAngle = add( div( mx_atan2( centeredT, centeredS ), float( Math.PI * 2 ) ), float( 0.5 ) ); + const boxVal = clamp( mul( max( abs( centeredS ), abs( centeredT ) ), float( 2 ) ), float( 0 ), float( 1 ) ); + + const typeDistanceToRadial = abs( sub( rampTypeFloat, float( 1 ) ) ); + const typeDistanceToCircular = abs( sub( rampTypeFloat, float( 2 ) ) ); + const typeDistanceToBox = abs( sub( rampTypeFloat, float( 3 ) ) ); + const useRadial = sub( float( 1 ), step( float( 0.5 ), typeDistanceToRadial ) ); + const useCircular = sub( float( 1 ), step( float( 0.5 ), typeDistanceToCircular ) ); + const useBox = sub( float( 1 ), step( float( 0.5 ), typeDistanceToBox ) ); + const afterRadial = mix( s, radialVal, useRadial ); + const afterCircular = mix( afterRadial, circularAngle, useCircular ); + const rampX = mix( afterCircular, boxVal, useBox ); + + const intervals = []; + const colors = []; + for ( let i = 0; i < 10; i += 1 ) { + + const intervalInput = rest[ i * 2 ]; + const colorInput = rest[ i * 2 + 1 ]; + intervals.push( intervalInput ?? float( i <= 1 ? i : 1 ) ); + colors.push( colorInput ?? vec4( i === 0 ? 0 : 1, i === 0 ? 0 : 1, i === 0 ? 0 : 1, 1 ) ); + + } + + let result = colors[ 0 ]; + for ( let i = 0; i < 9; i += 1 ) { + + const iv1 = intervals[ i ]; + const iv2 = intervals[ i + 1 ]; + const c1 = colors[ i ]; + const c2 = colors[ i + 1 ]; + const intNum = float( i + 1 ); + + const interpolated = mxRampSegment( rampX, c1, c2, iv1, iv2, interpolationFloat ); + const withinInterval = mixColor4( result, interpolated, step( add( iv1, float( 1e-6 ) ), rampX ) ); + result = mixColor4( withinInterval, result, step( numIntervalsFloat, intNum ) ); + + } + + return result; + +}; + +const defaultFloat = ( value ) => () => float( value ); +const defaultInt = ( value ) => () => int( value ); +const defaultBool = ( value ) => () => bool( value ); +const defaultColor = ( r, g, b ) => () => color( r, g, b ); +const defaultVec2 = ( x, y ) => () => vec2( x, y ); +const defaultVec3 = ( x, y, z ) => () => vec3( x, y, z ); +const defaultVec4 = ( x, y, z, w ) => () => vec4( x, y, z, w ); +const usesVec2Noise = ( nodeX ) => nodeX && nodeX.type === 'vector2'; +const usesVec3Noise = ( nodeX ) => nodeX && ( nodeX.type === 'vector3' || nodeX.type === 'color3' ); + +const mx_noise_materialx = ( texcoord, amplitude, pivot, nodeX ) => + usesVec3Noise( nodeX ) ? mx_noise_vec3( texcoord, vec3( amplitude ), pivot ) : mx_noise_float( texcoord, amplitude, pivot ); + +const mx_fractal_noise_materialx_2d = ( texcoord, octaves, lacunarity, diminish, amplitude, nodeX ) => + usesVec3Noise( nodeX ) ? mx_fractal_noise_vec3_materialx_2d( texcoord, octaves, lacunarity, diminish, amplitude ) : mx_fractal_noise_float_materialx_2d( texcoord, octaves, lacunarity, diminish, amplitude ); + +const mx_fractal_noise_materialx_3d = ( position, octaves, lacunarity, diminish, amplitude, nodeX ) => + usesVec3Noise( nodeX ) ? mx_fractal_noise_vec3( position, octaves, lacunarity, diminish, vec3( amplitude ) ) : mx_fractal_noise_float( position, octaves, lacunarity, diminish, amplitude ); + +const mx_cell_noise_materialx = ( position, nodeX ) => + usesVec3Noise( nodeX ) ? mx_cell_noise_vec3( position ) : mx_cell_noise_float( position ); + +const mx_worley_noise_vec2_style = ( position, jitter, style ) => { + + const result = mx_worley_noise_vec3_style( position, jitter, style, 0 ); + return vec2( element( result, 0 ), element( result, 1 ) ); + +}; + +const mx_worley_noise_materialx_2d = ( texcoord, jitter, style, nodeX ) => + usesVec3Noise( nodeX ) ? mx_worley_noise_vec3_style( texcoord, jitter, style, 0 ) : usesVec2Noise( nodeX ) ? mx_worley_noise_vec2_style( texcoord, jitter, style ) : mx_worley_noise_float_2d( texcoord, jitter, style ); + +const mx_worley_noise_materialx_3d = ( position, jitter, style, nodeX ) => + usesVec3Noise( nodeX ) ? mx_worley_noise_vec3_style( position, jitter, style, 0 ) : usesVec2Noise( nodeX ) ? mx_worley_noise_vec2_style( position, jitter, style ) : mx_worley_noise_float_3d( position, jitter, style ); + +const mx_fractal_noise_float_materialx_2d = Fn( ( [ texcoordInput, octavesInput, lacunarityInput, diminishInput, amplitudeInput ] ) => { + + const texcoord = vec2( texcoordInput ).toVar(); + const octaves = int( octavesInput ).toVar(); + const lacunarity = float( lacunarityInput ).toVar(); + const diminish = float( diminishInput ).toVar(); + const amplitude = float( amplitudeInput ).toVar(); + const result = float( 0 ).toVar(); + const octaveAmplitude = float( 1 ).toVar(); + + Loop( octaves, () => { + + result.addAssign( mul( octaveAmplitude, mx_noise_float( texcoord, float( 1 ), float( 0 ) ) ) ); + octaveAmplitude.mulAssign( diminish ); + texcoord.mulAssign( lacunarity ); + + } ); + + return mul( result, amplitude ); + +} ); + +const mx_fractal_noise_vec3_materialx_2d = Fn( ( [ texcoordInput, octavesInput, lacunarityInput, diminishInput, amplitudeInput ] ) => { + + const texcoord = vec2( texcoordInput ).toVar(); + const octaves = int( octavesInput ).toVar(); + const lacunarity = float( lacunarityInput ).toVar(); + const diminish = float( diminishInput ).toVar(); + const amplitude = vec3( amplitudeInput ).toVar(); + const result = vec3( 0 ).toVar(); + const octaveAmplitude = float( 1 ).toVar(); + + Loop( octaves, () => { + + result.addAssign( mul( octaveAmplitude, mx_noise_vec3( texcoord, vec3( 1 ), float( 0 ) ) ) ); + octaveAmplitude.mulAssign( diminish ); + texcoord.mulAssign( lacunarity ); + + } ); + + return mul( result, amplitude ); + +} ); + +const MXElements = [ + createMXElement( 'add', add, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'subtract', sub, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'multiply', mul, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 1 ) } ), + createMXElement( 'divide', div, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 1 ) } ), + createMXElement( 'modulo', mx_modulo, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 1 ) } ), + createMXElement( 'absval', abs, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'sign', sign, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'floor', floor, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'ceil', ceil, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'round', round, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'power', pow, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 1 ) } ), + createMXElement( 'sin', sin, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'cos', cos, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'tan', tan, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'asin', asin, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'acos', acos, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'atan2', mx_atan2, [ 'iny', 'inx' ], { iny: defaultFloat( 0 ), inx: defaultFloat( 1 ) } ), + createMXElement( 'sqrt', sqrt, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'ln', log, [ 'in' ], { in: defaultFloat( 1 ) } ), + createMXElement( 'exp', exp, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'fract', fract, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'clamp', clamp, [ 'in', 'low', 'high' ], { + in: defaultFloat( 0 ), + low: defaultFloat( 0 ), + high: defaultFloat( 1 ), + } ), + createMXElement( 'min', min, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'max', max, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'normalize', normalize, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'magnitude', length, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'length', length, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'dot', mx_dot, [ 'in' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'dotproduct', dot, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'viewdirection', mx_viewdirection, [ 'space' ], { space: () => 'world' } ), + createMXElement( 'crossproduct', cross, [ 'in1', 'in2' ], { in1: defaultVec3( 0, 0, 0 ), in2: defaultVec3( 0, 0, 0 ) } ), + createMXElement( 'distance', distance, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'invert', mx_invert, [ 'in', 'amount' ], { in: defaultFloat( 0 ), amount: defaultFloat( 1 ) } ), + createMXElement( 'transformmatrix', mul, [ 'in', 'mat' ], { in: defaultFloat( 0 ) } ), + createMXElement( 'transformnormal', mx_transformnormal, [ 'in', 'fromspace', 'tospace' ], { + in: defaultVec3( 0, 0, 1 ), + fromspace: () => 'world', + tospace: () => 'world', + } ), + createMXElement( 'transformpoint', mx_transformpoint, [ 'in', 'fromspace', 'tospace' ], { + in: defaultVec3( 0, 0, 0 ), + fromspace: () => 'world', + tospace: () => 'world', + } ), + createMXElement( 'transformvector', mx_transformvector, [ 'in', 'fromspace', 'tospace' ], { + in: defaultVec3( 0, 0, 0 ), + fromspace: () => 'world', + tospace: () => 'world', + } ), + createMXElement( 'normalmap', mx_normalmap, [ 'in', 'scale', 'normal', 'tangent', 'bitangent' ], { + in: defaultVec3( 0.5, 0.5, 1.0 ), + scale: defaultFloat( 1 ), + normal: () => normalWorld, + tangent: () => tangentWorld, + bitangent: () => bitangentWorld, + } ), + createMXElement( 'transpose', transpose, [ 'in' ] ), + createMXElement( 'determinant', determinant, [ 'in' ] ), + createMXElement( 'invertmatrix', inverse, [ 'in' ] ), + createMXElement( 'creatematrix', mat3, [ 'in1', 'in2', 'in3' ], { + in1: defaultVec3( 1, 0, 0 ), + in2: defaultVec3( 0, 1, 0 ), + in3: defaultVec3( 0, 0, 1 ), + } ), + createMXElement( 'remap', remap, [ 'in', 'inlow', 'inhigh', 'outlow', 'outhigh' ], { + in: defaultFloat( 0 ), + inlow: defaultFloat( 0 ), + inhigh: defaultFloat( 1 ), + outlow: defaultFloat( 0 ), + outhigh: defaultFloat( 1 ), + } ), + createMXElement( 'range', mx_range, [ 'in', 'inlow', 'inhigh', 'outlow', 'outhigh', 'gamma' ], { + in: defaultFloat( 0 ), + inlow: defaultFloat( 0 ), + inhigh: defaultFloat( 1 ), + outlow: defaultFloat( 0 ), + outhigh: defaultFloat( 1 ), + gamma: defaultFloat( 1 ), + } ), + createMXElement( 'open_pbr_anisotropy', mx_open_pbr_anisotropy, [ 'roughness', 'anisotropy' ], { + roughness: defaultFloat( 0 ), + anisotropy: defaultFloat( 0 ), + } ), + createMXElement( 'smoothstep', mx_smoothstep, [ 'in', 'low', 'high' ], { + in: defaultFloat( 0 ), + low: defaultFloat( 0 ), + high: defaultFloat( 1 ), + } ), + createMXElement( 'luminance', luminance, [ 'in', 'lumacoeffs' ], { + in: defaultColor( 0, 0, 0 ), + lumacoeffs: defaultColor( 0.2722287, 0.6740818, 0.0536895 ), + } ), + createMXElement( 'rgbtohsv', mx_rgbtohsv, [ 'in' ], { in: defaultColor( 0, 0, 0 ) } ), + createMXElement( 'hsvtorgb', mx_hsvtorgb, [ 'in' ], { in: defaultColor( 0, 0, 0 ) } ), + createMXElement( 'mix', mix, [ 'bg', 'fg', 'mix' ], { bg: defaultFloat( 0 ), fg: defaultFloat( 0 ), mix: defaultFloat( 0 ) } ), + createMXElement( 'minus', mx_minus, [ 'fg', 'bg', 'mix' ], { + fg: defaultFloat( 0 ), + bg: defaultFloat( 0 ), + mix: defaultFloat( 1 ), + } ), + createMXElement( 'difference', mx_difference, [ 'fg', 'bg', 'mix' ], { + fg: defaultFloat( 0 ), + bg: defaultFloat( 0 ), + mix: defaultFloat( 1 ), + } ), + createMXElement( 'screen', mx_screen, [ 'fg', 'bg', 'mix' ], { + fg: defaultFloat( 0 ), + bg: defaultFloat( 0 ), + mix: defaultFloat( 1 ), + } ), + createMXElement( 'overlay', mx_overlay, [ 'fg', 'bg', 'mix' ], { + fg: defaultFloat( 0 ), + bg: defaultFloat( 0 ), + mix: defaultFloat( 1 ), + } ), + createMXElement( 'burn', mx_burn, [ 'fg', 'bg', 'mix' ], { + fg: defaultFloat( 0 ), + bg: defaultFloat( 0 ), + mix: defaultFloat( 1 ), + } ), + createMXElement( 'dodge', mx_dodge, [ 'fg', 'bg', 'mix' ], { + fg: defaultFloat( 0 ), + bg: defaultFloat( 0 ), + mix: defaultFloat( 1 ), + } ), + createMXElement( + 'colorcorrect', + mx_colorcorrect, + [ 'in', 'hue', 'saturation', 'gamma', 'lift', 'gain', 'contrast', 'contrastpivot', 'exposure' ], + { + in: defaultColor( 1, 1, 1 ), + hue: defaultFloat( 0 ), + saturation: defaultFloat( 1 ), + gamma: defaultFloat( 1 ), + lift: defaultFloat( 0 ), + gain: defaultFloat( 1 ), + contrast: defaultFloat( 1 ), + contrastpivot: defaultFloat( 0.5 ), + exposure: defaultFloat( 0 ), + }, + ), + createMXElement( 'unpremult', mx_unpremult, [ 'in' ], { in: defaultVec4( 0, 0, 0, 1 ) } ), + createMXElement( 'combine2', vec2, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 0 ) } ), + createMXElement( 'combine3', vec3, [ 'in1', 'in2', 'in3' ], { + in1: defaultFloat( 0 ), + in2: defaultFloat( 0 ), + in3: defaultFloat( 0 ), + } ), + createMXElement( 'combine4', vec4, [ 'in1', 'in2', 'in3', 'in4' ], { + in1: defaultFloat( 0 ), + in2: defaultFloat( 0 ), + in3: defaultFloat( 0 ), + in4: defaultFloat( 0 ), + } ), + createMXElement( 'ramplr', mx_ramplr, [ 'valuel', 'valuer', 'texcoord' ], { + valuel: defaultFloat( 0 ), + valuer: defaultFloat( 0 ), + } ), + createMXElement( 'ramptb', mx_ramptb, [ 'valueb', 'valuet', 'texcoord' ], { + valueb: defaultFloat( 0 ), + valuet: defaultFloat( 0 ), + } ), + createMXElement( 'ramp4', mx_ramp4, [ 'valuetl', 'valuetr', 'valuebl', 'valuebr', 'texcoord' ], { + valuetl: defaultColor( 0, 0, 0 ), + valuetr: defaultColor( 0, 0, 0 ), + valuebl: defaultColor( 0, 0, 0 ), + valuebr: defaultColor( 0, 0, 0 ), + texcoord: defaultVec2( 0, 0 ), + } ), + createMXElement( + 'ramp_gradient', + mx_ramp_gradient, + [ 'x', 'interval1', 'interval2', 'color1', 'color2', 'interpolation', 'prev_color', 'interval_num', 'num_intervals' ], + { + x: defaultFloat( 0 ), + interval1: defaultFloat( 0 ), + interval2: defaultFloat( 1 ), + color1: defaultVec4( 0, 0, 0, 1 ), + color2: defaultVec4( 1, 1, 1, 1 ), + interpolation: defaultFloat( 1 ), + prev_color: defaultVec4( 0, 0, 0, 1 ), + interval_num: defaultFloat( 1 ), + num_intervals: defaultFloat( 2 ), + }, + ), + createMXElement( + 'ramp', + mx_ramp, + [ + 'texcoord', + 'type', + 'interpolation', + 'num_intervals', + 'interval1', + 'color1', + 'interval2', + 'color2', + 'interval3', + 'color3', + 'interval4', + 'color4', + 'interval5', + 'color5', + 'interval6', + 'color6', + 'interval7', + 'color7', + 'interval8', + 'color8', + 'interval9', + 'color9', + 'interval10', + 'color10', + ], + { + texcoord: defaultVec2( 0, 0 ), + type: defaultFloat( 0 ), + interpolation: defaultFloat( 1 ), + num_intervals: defaultFloat( 2 ), + interval1: defaultFloat( 0 ), + color1: defaultVec4( 0, 0, 0, 1 ), + interval2: defaultFloat( 1 ), + color2: defaultVec4( 1, 1, 1, 1 ), + interval3: defaultFloat( 1 ), + color3: defaultVec4( 1, 1, 1, 1 ), + interval4: defaultFloat( 1 ), + color4: defaultVec4( 1, 1, 1, 1 ), + interval5: defaultFloat( 1 ), + color5: defaultVec4( 1, 1, 1, 1 ), + interval6: defaultFloat( 1 ), + color6: defaultVec4( 1, 1, 1, 1 ), + interval7: defaultFloat( 1 ), + color7: defaultVec4( 1, 1, 1, 1 ), + interval8: defaultFloat( 1 ), + color8: defaultVec4( 1, 1, 1, 1 ), + interval9: defaultFloat( 1 ), + color9: defaultVec4( 1, 1, 1, 1 ), + interval10: defaultFloat( 1 ), + color10: defaultVec4( 1, 1, 1, 1 ), + }, + ), + createMXElement( 'splitlr', mx_splitlr, [ 'valuel', 'valuer', 'center', 'texcoord' ], { + valuel: defaultFloat( 0 ), + valuer: defaultFloat( 0 ), + center: defaultFloat( 0.5 ), + } ), + createMXElement( 'splittb', mx_splittb, [ 'valueb', 'valuet', 'center', 'texcoord' ], { + valueb: defaultFloat( 0 ), + valuet: defaultFloat( 0 ), + center: defaultFloat( 0.5 ), + } ), + createMXElement( 'noise2d', mx_noise_materialx, [ 'texcoord', 'amplitude', 'pivot' ], { + texcoord: defaultVec2( 0, 0 ), + amplitude: defaultFloat( 1 ), + pivot: defaultFloat( 0 ), + }, true ), + createMXElement( 'noise3d', mx_noise_materialx, [ 'position', 'amplitude', 'pivot' ], { + position: () => positionLocal, + amplitude: defaultFloat( 1 ), + pivot: defaultFloat( 0 ), + }, true ), + createMXElement( 'fractal2d', mx_fractal_noise_materialx_2d, [ 'texcoord', 'octaves', 'lacunarity', 'diminish', 'amplitude' ], { + texcoord: defaultVec2( 0, 0 ), + octaves: defaultInt( 3 ), + lacunarity: defaultFloat( 2.0 ), + diminish: defaultFloat( 0.5 ), + amplitude: defaultFloat( 1.0 ), + }, true ), + createMXElement( 'fractal3d', mx_fractal_noise_materialx_3d, [ 'position', 'octaves', 'lacunarity', 'diminish', 'amplitude' ], { + position: () => positionLocal, + octaves: defaultInt( 3 ), + lacunarity: defaultFloat( 2.0 ), + diminish: defaultFloat( 0.5 ), + amplitude: defaultFloat( 1.0 ), + }, true ), + createMXElement( 'cellnoise2d', mx_cell_noise_materialx, [ 'texcoord' ], { texcoord: defaultVec2( 0, 0 ) }, true ), + createMXElement( 'cellnoise3d', mx_cell_noise_materialx, [ 'position' ], { position: () => positionLocal }, true ), + createMXElement( 'worleynoise2d', mx_worley_noise_materialx_2d, [ 'texcoord', 'jitter', 'style' ], { + texcoord: defaultVec2( 0, 0 ), + jitter: defaultFloat( 1 ), + style: defaultInt( 0 ), + }, true ), + createMXElement( 'worleynoise3d', mx_worley_noise_materialx_3d, [ 'position', 'jitter', 'style' ], { + position: () => positionLocal, + jitter: defaultFloat( 1 ), + style: defaultInt( 0 ), + }, true ), + createMXElement( + 'unifiednoise2d', + mx_unifiednoise2d, + [ + 'type', + 'texcoord', + 'freq', + 'offset', + 'jitter', + 'outmin', + 'outmax', + 'clampoutput', + 'octaves', + 'lacunarity', + 'diminish', + 'style', + ], + { + type: defaultInt( 0 ), + texcoord: defaultVec2( 0, 0 ), + freq: defaultVec2( 1, 1 ), + offset: defaultVec2( 0, 0 ), + jitter: defaultFloat( 1 ), + outmin: defaultFloat( 0 ), + outmax: defaultFloat( 1 ), + clampoutput: defaultBool( true ), + octaves: defaultInt( 3 ), + lacunarity: defaultFloat( 2 ), + diminish: defaultFloat( 0.5 ), + style: defaultInt( 0 ), + }, + ), + createMXElement( + 'unifiednoise3d', + mx_unifiednoise3d, + [ + 'type', + 'position', + 'freq', + 'offset', + 'jitter', + 'outmin', + 'outmax', + 'clampoutput', + 'octaves', + 'lacunarity', + 'diminish', + 'style', + ], + { + type: defaultInt( 0 ), + position: () => positionLocal, + freq: defaultVec3( 1, 1, 1 ), + offset: defaultVec3( 0, 0, 0 ), + jitter: defaultFloat( 1 ), + outmin: defaultFloat( 0 ), + outmax: defaultFloat( 1 ), + clampoutput: defaultBool( true ), + octaves: defaultInt( 3 ), + lacunarity: defaultFloat( 2 ), + diminish: defaultFloat( 0.5 ), + style: defaultInt( 0 ), + }, + ), + createMXElement( 'place2d', mx_place2d, [ 'texcoord', 'pivot', 'scale', 'rotate', 'offset', 'operationorder' ], { + texcoord: defaultVec2( 0, 0 ), + pivot: defaultVec2( 0, 0 ), + scale: defaultVec2( 1, 1 ), + rotate: defaultFloat( 0 ), + offset: defaultVec2( 0, 0 ), + operationorder: defaultInt( 0 ), + } ), + createMXElement( 'safepower', mx_safepower, [ 'in1', 'in2' ], { in1: defaultFloat( 0 ), in2: defaultFloat( 1 ) } ), + createMXElement( 'contrast', mx_contrast, [ 'in', 'amount', 'pivot' ], { + in: defaultFloat( 0 ), + amount: defaultFloat( 1 ), + pivot: defaultFloat( 0.5 ), + } ), + createMXElement( 'saturate', mx_saturation, [ 'in', 'amount' ], { in: defaultColor( 0, 0, 0 ), amount: defaultFloat( 1 ) } ), + createMXElement( 'extract', element, [ 'in', 'index' ], { in: defaultFloat( 0 ), index: defaultInt( 0 ) } ), + createMXElement( 'separate2', element, [ 'in' ], { in: defaultVec2( 0, 0 ) } ), + createMXElement( 'separate3', element, [ 'in' ], { in: defaultVec3( 0, 0, 0 ) } ), + createMXElement( 'separate4', element, [ 'in' ], { in: defaultVec4( 0, 0, 0, 0 ) } ), + createMXElement( 'reflect', reflect, [ 'in', 'normal' ], { in: defaultVec3( 1, 0, 0 ) } ), + createMXElement( 'refract', refract, [ 'in', 'normal', 'ior' ], { in: defaultVec3( 1, 0, 0 ), ior: defaultFloat( 1 ) } ), + createMXElement( 'time', mx_timer ), + createMXElement( 'frame', mx_frame ), + createMXElement( 'ifgreater', mx_ifgreater, [ 'value1', 'value2', 'in1', 'in2' ], { + value1: defaultFloat( 1 ), + value2: defaultFloat( 0 ), + in1: defaultFloat( 0 ), + in2: defaultFloat( 0 ), + } ), + createMXElement( 'ifgreatereq', mx_ifgreatereq, [ 'value1', 'value2', 'in1', 'in2' ], { + value1: defaultFloat( 1 ), + value2: defaultFloat( 0 ), + in1: defaultFloat( 0 ), + in2: defaultFloat( 0 ), + } ), + createMXElement( 'ifequal', mx_ifequal, [ 'value1', 'value2', 'in1', 'in2' ], { + value1: defaultFloat( 0 ), + value2: defaultFloat( 0 ), + in1: defaultFloat( 0 ), + in2: defaultFloat( 0 ), + } ), + createMXElement( 'rotate2d', mx_rotate2d, [ 'in', 'amount' ], { in: defaultVec2( 0, 0 ), amount: defaultFloat( 0 ) } ), + createMXElement( 'rotate3d', mx_rotate3d, [ 'in', 'amount', 'axis' ], { + in: defaultVec3( 0, 0, 0 ), + amount: defaultFloat( 0 ), + axis: defaultVec3( 0, 1, 0 ), + } ), + createMXElement( 'heighttonormal', mx_heighttonormal, [ 'in', 'scale', 'texcoord' ], { + in: defaultFloat( 0 ), + scale: defaultFloat( 1 ), + } ), + createMXElement( 'and', mx_and, [ 'in1', 'in2' ], { in1: defaultBool( false ), in2: defaultBool( false ) } ), + createMXElement( 'or', mx_or, [ 'in1', 'in2' ], { in1: defaultBool( false ), in2: defaultBool( false ) } ), + createMXElement( 'xor', mx_xor, [ 'in1', 'in2' ], { in1: defaultBool( false ), in2: defaultBool( false ) } ), + createMXElement( 'not', mx_not, [ 'in' ], { in: defaultBool( false ) } ), + createMXElement( 'checkerboard', mx_checkerboard, [ 'color1', 'color2', 'uvtiling', 'uvoffset', 'texcoord' ], { + color1: defaultColor( 1, 1, 1 ), + color2: defaultColor( 0, 0, 0 ), + uvtiling: defaultVec2( 8, 8 ), + uvoffset: defaultVec2( 0, 0 ), + texcoord: defaultVec2( 0, 0 ), + } ), + createMXElement( 'circle', mx_circle, [ 'texcoord', 'center', 'radius' ], { + center: defaultVec2( 0, 0 ), + radius: defaultFloat( 0.5 ), + } ), + createMXElement( 'bump', mx_bump, [ 'height', 'scale', 'normal', 'tangent', 'bitangent' ], { + height: defaultFloat( 0 ), + scale: defaultFloat( 1 ), + normal: () => normalWorld, + tangent: () => tangentWorld, + bitangent: () => bitangentWorld, + } ), + createMXElement( 'blackbody', mx_blackbody, [ 'temperature' ], { temperature: defaultFloat( 5000 ) } ), +]; + +const MtlXLibrary = Object.fromEntries( MXElements.map( ( entry ) => [ entry.name, entry ] ) ); + +export { MtlXLibrary }; diff --git a/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js b/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js new file mode 100644 index 00000000000000..0396472e98cce2 --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXSurfaceMappings.js @@ -0,0 +1,661 @@ +import { DoubleSide } from 'three/webgpu'; +import { MaterialXLogCodes } from './MaterialXLog.js'; +import { float, color, mul, clamp, vec2, cos, sin, pow, mix, element, transformNormalToView } from 'three/tsl'; + +const mappedStandardSurfaceInputs = new Set( [ + 'base', + 'base_color', + 'specular_roughness', + 'metalness', + 'specular', + 'specular_color', + 'specular_anisotropy', + 'specular_rotation', + 'transmission', + 'transmission_color', + 'transmission_depth', + 'thin_film_thickness', + 'thin_film_IOR', + 'sheen', + 'sheen_color', + 'sheen_roughness', + 'coat', + 'coat_color', + 'coat_roughness', + 'coat_normal', + 'normal', + 'opacity', + 'specular_IOR', + 'emission', + 'emission_color', +] ); + +const mappedGltfPbrInputs = new Set( [ + 'base_color', + 'occlusion', + 'roughness', + 'metallic', + 'normal', + 'transmission', + 'specular', + 'specular_color', + 'ior', + 'alpha', + 'alpha_mode', + 'alpha_cutoff', + 'iridescence', + 'iridescence_ior', + 'iridescence_thickness', + 'sheen_color', + 'sheen_roughness', + 'clearcoat', + 'clearcoat_roughness', + 'clearcoat_normal', + 'emissive', + 'emissive_strength', + 'attenuation_distance', + 'attenuation_color', + 'thickness', + 'dispersion', + 'anisotropy_strength', + 'anisotropy_rotation', +] ); + +const mappedOpenPbrInputs = new Set( [ + 'base_weight', + 'base_color', + 'specular_weight', + 'specular_color', + 'specular_roughness', + 'base_metalness', + 'specular_roughness_anisotropy', + 'specular_ior', + 'coat_weight', + 'coat_ior', + 'coat_color', + 'coat_roughness', + 'geometry_coat_normal', + 'fuzz_weight', + 'fuzz_color', + 'fuzz_roughness', + 'transmission_weight', + 'transmission_color', + 'transmission_depth', + 'transmission_dispersion_scale', + 'transmission_dispersion_abbe_number', + 'geometry_normal', + 'geometry_opacity', + 'geometry_thin_walled', + 'thin_film_weight', + 'thin_film_thickness', + 'thin_film_ior', + 'emission_color', + 'emission_luminance', +] ); + +function warnIgnoredInputs( inputs, mappedInputs, log, surfaceCategory, nodeName ) { + + for ( const inputName of Object.keys( inputs ) ) { + + if ( mappedInputs.has( inputName ) === false ) { + + log.add( + MaterialXLogCodes.IGNORED_SURFACE_INPUT, + `${surfaceCategory} input "${inputName}" is currently ignored in MaterialX translation.`, + nodeName, + ); + + } + + } + +} + +function hasNodeValue( value ) { + + return value !== undefined && value !== null; + +} + +function getConstNumber( node ) { + + if ( typeof node === 'number' ) return node; + if ( ! node || typeof node !== 'object' ) return null; + + let cursor = node; + const visited = new Set(); + while ( cursor && typeof cursor === 'object' ) { + + if ( visited.has( cursor ) ) break; + visited.add( cursor ); + if ( typeof cursor.value === 'number' ) return cursor.value; + cursor = cursor.node; + + } + + return null; + +} + +function isConstNear( node, target, epsilon = 1e-6 ) { + + const value = getConstNumber( node ); + if ( value === null ) return false; + return Math.abs( value - target ) <= epsilon; + +} + +function isEffectivelyZero( node, epsilon = 1e-6 ) { + + return isConstNear( node, 0, epsilon ); + +} + +function isEffectivelyOne( node, epsilon = 1e-6 ) { + + return isConstNear( node, 1, epsilon ); + +} + +function isEnabledWeightNode( node ) { + + if ( hasNodeValue( node ) === false ) return false; + return isEffectivelyZero( node ) === false; + +} + +function setAnisotropy( material, strengthNode, rotationNode ) { + + if ( ! hasNodeValue( strengthNode ) && ! hasNodeValue( rotationNode ) ) return; + if ( isEffectivelyZero( strengthNode ) && isEffectivelyZero( rotationNode ) ) return; + const strength = hasNodeValue( strengthNode ) ? strengthNode : float( 0 ); + const rotation = hasNodeValue( rotationNode ) ? rotationNode : float( 0 ); + material.anisotropyNode = vec2( cos( rotation ), sin( rotation ) ).mul( strength ); + material.anisotropyRotationNode = rotation; + +} + +function setTransmissionFlags( material, transmissionNode, opacityNode, allowOpacityTransparency = true ) { + + if ( allowOpacityTransparency && hasNodeValue( opacityNode ) && isEffectivelyOne( opacityNode ) === false ) { + + material.transparent = true; + + } + + if ( isEnabledWeightNode( transmissionNode ) ) { + + material.side = DoubleSide; + material.transparent = true; + + } + +} + +function toAttenuationDistance( distanceNode, hasAttenuationColorInput ) { + + if ( hasNodeValue( distanceNode ) ) return distanceNode; + // When attenuation tint is authored without a distance, default to a + // finite value so absorption tinting is visible. + return hasAttenuationColorInput ? float( 1 ) : undefined; + +} + +function buildGltfOpacityNode( alphaNode, alphaModeNode ) { + + const alphaMode = getConstNumber( alphaModeNode ); + const roundedMode = alphaMode === null ? 2 : Math.round( alphaMode ); + const alpha = alphaNode ?? float( 1 ); + + if ( roundedMode === 0 ) return float( 1 ); + if ( roundedMode === 1 ) return alpha; + return alpha; + +} + +function applyStandardSurface( material, inputs, log, nodeName ) { + + let colorNode = null; + if ( inputs.base && inputs.base_color ) colorNode = mul( inputs.base, inputs.base_color ); + else if ( inputs.base ) colorNode = inputs.base; + else if ( inputs.base_color ) colorNode = inputs.base_color; + + if ( inputs.coat_color ) { + + colorNode = colorNode ? mul( colorNode, inputs.coat_color ) : colorNode; + + } + + const roughnessNode = inputs.specular_roughness; + const opacityNode = hasNodeValue( inputs.opacity ) ? element( inputs.opacity, 0 ) : undefined; + const transmissionNode = inputs.transmission; + const transmissionColorNode = inputs.transmission_color; + const transmissionEnabled = isEnabledWeightNode( transmissionNode ); + const sheenEnabled = isEnabledWeightNode( inputs.sheen ); + const clearcoatEnabled = isEnabledWeightNode( inputs.coat ); + + let emissiveNode = inputs.emission; + const emissionColorNode = inputs.emission_color; + if ( hasNodeValue( emissionColorNode ) ) { + + emissiveNode = emissiveNode ? mul( emissiveNode, emissionColorNode ) : emissionColorNode; + + } + + const thinFilmThicknessNode = inputs.thin_film_thickness; + const thinFilmIorNode = clamp( inputs.thin_film_IOR || float( 1.5 ), float( 1.0 ), float( 2.333 ) ); + const thinFilmEnabled = isEnabledWeightNode( thinFilmThicknessNode ); + const transmissionTintNode = hasNodeValue( transmissionColorNode ) ? transmissionColorNode : color( 1, 1, 1 ); + + if ( transmissionEnabled ) { + + const baseForTransmissionMix = colorNode || color( 0.8, 0.8, 0.8 ); + // Suppress diffuse/base tint as transmission ramps up. + colorNode = mix( baseForTransmissionMix, transmissionTintNode, transmissionNode ); + + } + + material.colorNode = colorNode || color( 0.8, 0.8, 0.8 ); + if ( hasNodeValue( opacityNode ) && isEffectivelyOne( opacityNode ) === false ) { + + material.opacityNode = opacityNode; + + } + + material.roughnessNode = roughnessNode || float( 0.2 ); + if ( hasNodeValue( inputs.metalness ) && isEffectivelyZero( inputs.metalness ) === false ) { + + material.metalnessNode = inputs.metalness; + + } + + if ( hasNodeValue( inputs.specular ) && isEffectivelyOne( inputs.specular ) === false ) { + + material.specularIntensityNode = inputs.specular; + + } + + material.specularColorNode = inputs.specular_color || color( 1, 1, 1 ); + const iorNode = inputs.specular_IOR; + if ( hasNodeValue( iorNode ) && isConstNear( iorNode, 1.5 ) === false ) { + + material.iorNode = iorNode; + + } + + setAnisotropy( material, inputs.specular_anisotropy, inputs.specular_rotation ); + + if ( transmissionEnabled ) { + + material.transmissionNode = transmissionNode; + if ( hasNodeValue( transmissionColorNode ) ) material.transmissionColorNode = transmissionColorNode; + if ( hasNodeValue( inputs.transmission_depth ) && isEffectivelyZero( inputs.transmission_depth ) === false ) { + + material.thicknessNode = inputs.transmission_depth; + + } else { + + // Keep transmissive standard_surface materials volumetric when + // transmission_depth is omitted or authored as zero. + material.thickness = 1; + + } + + } + + if ( thinFilmEnabled ) { + + material.iridescenceThicknessNode = thinFilmThicknessNode; + material.iridescenceIORNode = thinFilmIorNode; + material.iridescenceNode = float( 1 ); + + } + + const sheenColor = inputs.sheen_color || color( 1, 1, 1 ); + if ( sheenEnabled ) { + + const sheenRoughness = hasNodeValue( inputs.sheen_roughness ) ? inputs.sheen_roughness : float( 0.3 ); + material.sheenNode = mul( inputs.sheen, sheenColor ); + material.sheenRoughnessNode = sheenRoughness; + + } + + if ( clearcoatEnabled ) { + + material.clearcoatNode = inputs.coat; + if ( hasNodeValue( inputs.coat_roughness ) ) { + + material.clearcoatRoughnessNode = inputs.coat_roughness; + + } + + } + + if ( clearcoatEnabled && hasNodeValue( inputs.coat_normal ) ) { + + material.clearcoatNormalNode = transformNormalToView( inputs.coat_normal ); + + } + + if ( hasNodeValue( inputs.normal ) ) material.normalNode = transformNormalToView( inputs.normal ); + if ( hasNodeValue( emissiveNode ) ) material.emissiveNode = emissiveNode; + + setTransmissionFlags( material, transmissionNode, opacityNode ); + warnIgnoredInputs( inputs, mappedStandardSurfaceInputs, log, 'standard_surface', nodeName ); + +} + +function applyGltfPbrSurface( material, inputs, log, nodeName ) { + + const alphaModeLiteral = getConstNumber( inputs.alpha_mode ); + const alphaMode = alphaModeLiteral === null ? 2 : Math.round( alphaModeLiteral ); + const isAlphaMaskMode = alphaMode === 1; + const isAlphaBlendMode = alphaMode === 2; + const opacityNode = buildGltfOpacityNode( inputs.alpha, inputs.alpha_mode ); + const alphaCutoffNode = inputs.alpha_cutoff ?? float( 0.5 ); + const hasAttenuationColorInput = Object.prototype.hasOwnProperty.call( inputs, 'attenuation_color' ); + const transmissionEnabled = isEnabledWeightNode( inputs.transmission ); + const clearcoatEnabled = isEnabledWeightNode( inputs.clearcoat ); + const sheenEnabled = hasNodeValue( inputs.sheen_color ) || isEnabledWeightNode( inputs.sheen_roughness ); + const iridescenceEnabled = isEnabledWeightNode( inputs.iridescence ); + + material.colorNode = inputs.base_color || color( 1, 1, 1 ); + if ( hasNodeValue( inputs.occlusion ) ) material.aoNode = inputs.occlusion; + material.roughnessNode = inputs.roughness || float( 1 ); + material.metalnessNode = inputs.metallic || float( 1 ); + if ( hasNodeValue( inputs.specular ) && isEffectivelyOne( inputs.specular ) === false ) { + + material.specularIntensityNode = inputs.specular; + + } + + material.specularColorNode = inputs.specular_color || color( 1, 1, 1 ); + if ( hasNodeValue( inputs.ior ) && isConstNear( inputs.ior, 1.5 ) === false ) { + + material.iorNode = inputs.ior; + + } + + if ( hasNodeValue( opacityNode ) && isEffectivelyOne( opacityNode ) === false ) { + + material.opacityNode = opacityNode; + + } + + if ( isAlphaMaskMode ) { + + material.alphaTestNode = alphaCutoffNode; + const alphaCutoff = getConstNumber( alphaCutoffNode ); + if ( alphaCutoff !== null ) material.alphaTest = alphaCutoff; + + } + + if ( transmissionEnabled ) { + + material.transmissionNode = inputs.transmission; + + } + + if ( clearcoatEnabled ) { + + material.clearcoatNode = inputs.clearcoat; + if ( hasNodeValue( inputs.clearcoat_roughness ) && isEffectivelyZero( inputs.clearcoat_roughness ) === false ) { + + material.clearcoatRoughnessNode = inputs.clearcoat_roughness; + + } + + } + + if ( sheenEnabled ) { + + const sheenColor = hasNodeValue( inputs.sheen_color ) ? inputs.sheen_color : color( 0, 0, 0 ); + const sheenRoughness = hasNodeValue( inputs.sheen_roughness ) ? inputs.sheen_roughness : float( 0 ); + material.sheenRoughnessNode = sheenRoughness; + material.sheenNode = sheenColor; + + } + + if ( iridescenceEnabled ) { + + material.iridescenceNode = inputs.iridescence; + if ( hasNodeValue( inputs.iridescence_ior ) && isConstNear( inputs.iridescence_ior, 1.3 ) === false ) { + + material.iridescenceIORNode = inputs.iridescence_ior; + + } + + if ( hasNodeValue( inputs.iridescence_thickness ) && isConstNear( inputs.iridescence_thickness, 100 ) === false ) { + + material.iridescenceThicknessNode = inputs.iridescence_thickness; + + } + + } + + material.attenuationDistanceNode = toAttenuationDistance( inputs.attenuation_distance, hasAttenuationColorInput ); + material.attenuationColorNode = inputs.attenuation_color || color( 1, 1, 1 ); + if ( hasNodeValue( inputs.thickness ) ) { + + if ( isEffectivelyZero( inputs.thickness ) === false ) { + + material.thicknessNode = inputs.thickness; + + } + + } else if ( transmissionEnabled ) { + + // Keep transmissive glTF materials volumetric even when thickness is omitted. + material.thickness = 1; + + } + + if ( hasNodeValue( inputs.dispersion ) && isEffectivelyZero( inputs.dispersion ) === false ) { + + material.dispersionNode = inputs.dispersion; + + } + + const anisotropyStrength = inputs.anisotropy_strength; + const anisotropyRotation = inputs.anisotropy_rotation; + setAnisotropy( material, anisotropyStrength, anisotropyRotation ); + + if ( hasNodeValue( inputs.normal ) ) material.normalNode = transformNormalToView( inputs.normal ); + if ( hasNodeValue( inputs.clearcoat_normal ) ) { + + material.clearcoatNormalNode = transformNormalToView( inputs.clearcoat_normal ); + + } + + if ( hasNodeValue( inputs.emissive ) && hasNodeValue( inputs.emissive_strength ) ) + material.emissiveNode = mul( inputs.emissive, inputs.emissive_strength ); + else if ( hasNodeValue( inputs.emissive ) ) material.emissiveNode = inputs.emissive; + + setTransmissionFlags( material, inputs.transmission, opacityNode, isAlphaBlendMode ); + warnIgnoredInputs( inputs, mappedGltfPbrInputs, log, 'gltf_pbr', nodeName ); + +} + +function applyOpenPbrSurface( material, inputs, log, nodeName ) { + + const baseWeight = inputs.base_weight || float( 1 ); + const baseColor = inputs.base_color || color( 0.8, 0.8, 0.8 ); + const coatEnabled = isEnabledWeightNode( inputs.coat_weight ); + const fuzzEnabled = isEnabledWeightNode( inputs.fuzz_weight ); + const transmissionEnabled = isEnabledWeightNode( inputs.transmission_weight ); + const thinFilmEnabled = isEnabledWeightNode( inputs.thin_film_weight ); + material.colorNode = mul( baseWeight, baseColor ); + + if ( hasNodeValue( inputs.base_metalness ) && isEffectivelyZero( inputs.base_metalness ) === false ) { + + material.metalnessNode = inputs.base_metalness; + + } + + material.roughnessNode = inputs.specular_roughness || float( 0.3 ); + if ( hasNodeValue( inputs.specular_weight ) && isEffectivelyOne( inputs.specular_weight ) === false ) { + + material.specularIntensityNode = inputs.specular_weight; + + } + + material.specularColorNode = inputs.specular_color || color( 1, 1, 1 ); + const openPbrIorNode = inputs.specular_ior; + if ( hasNodeValue( openPbrIorNode ) && isConstNear( openPbrIorNode, 1.5 ) === false ) { + + material.iorNode = openPbrIorNode; + + } + + setAnisotropy( material, inputs.specular_roughness_anisotropy, float( 0 ) ); + + if ( coatEnabled ) { + + const coatWeightNode = inputs.coat_weight || float( 0 ); + if ( hasNodeValue( inputs.coat_ior ) ) { + + const coatIorNode = inputs.coat_ior; + const coatIorMinusOne = coatIorNode.sub( float( 1 ) ); + const coatIorPlusOne = coatIorNode.add( float( 1 ) ); + const coatF0Node = coatIorMinusOne.div( coatIorPlusOne ); + const normalizedClearcoatNode = coatF0Node.mul( coatF0Node ).div( float( 0.04 ) ); + material.clearcoatNode = clamp( coatWeightNode.mul( normalizedClearcoatNode ), float( 0 ), float( 1 ) ); + + } else { + + material.clearcoatNode = coatWeightNode; + + } + + if ( hasNodeValue( inputs.coat_roughness ) && isEffectivelyZero( inputs.coat_roughness ) === false ) { + + material.clearcoatRoughnessNode = inputs.coat_roughness; + + } + + if ( hasNodeValue( inputs.geometry_coat_normal ) ) { + + material.clearcoatNormalNode = transformNormalToView( inputs.geometry_coat_normal ); + + } + + } + + const fuzzWeight = inputs.fuzz_weight || float( 0 ); + const fuzzColor = inputs.fuzz_color || color( 1, 1, 1 ); + if ( fuzzEnabled ) { + + material.sheenNode = mul( fuzzWeight, fuzzColor ); + if ( hasNodeValue( inputs.fuzz_roughness ) ) { + + material.sheenRoughnessNode = pow( inputs.fuzz_roughness, float( 1.5 ) ); + + } + + } + + if ( transmissionEnabled ) { + + material.transmissionNode = inputs.transmission_weight; + if ( hasNodeValue( inputs.transmission_color ) ) material.attenuationColorNode = inputs.transmission_color; + + } + + const transmissionDepthNode = inputs.transmission_depth; + if ( transmissionEnabled && hasNodeValue( transmissionDepthNode ) && isEffectivelyZero( transmissionDepthNode ) === false ) { + + material.thicknessNode = hasNodeValue( inputs.geometry_thin_walled ) + ? inputs.geometry_thin_walled.select( float( 0 ), transmissionDepthNode ) + : transmissionDepthNode; + material.attenuationDistanceNode = transmissionDepthNode; + + } else if ( transmissionEnabled ) { + + // Keep transmissive OpenPBR materials volumetric even when depth is omitted. + material.thickness = 1; + + } + + const transmissionDispersionAbbe = inputs.transmission_dispersion_abbe_number || float( 20 ); + if ( transmissionEnabled && hasNodeValue( inputs.transmission_dispersion_scale ) && isEffectivelyZero( inputs.transmission_dispersion_scale ) === false ) { + + material.dispersionNode = inputs.transmission_dispersion_scale.mul( float( 20 ) ).div( transmissionDispersionAbbe ); + + } + + if ( hasNodeValue( inputs.geometry_opacity ) && isEffectivelyOne( inputs.geometry_opacity ) === false ) { + + material.opacityNode = inputs.geometry_opacity; + + } + + if ( hasNodeValue( inputs.geometry_normal ) ) material.normalNode = transformNormalToView( inputs.geometry_normal ); + + if ( thinFilmEnabled ) { + + material.iridescenceNode = inputs.thin_film_weight; + if ( hasNodeValue( inputs.thin_film_thickness ) && isConstNear( inputs.thin_film_thickness, 0.5 ) === false ) { + + material.iridescenceThicknessNode = inputs.thin_film_thickness.mul( float( 1000 ) ); + + } + + if ( hasNodeValue( inputs.thin_film_ior ) && isConstNear( inputs.thin_film_ior, 1.4 ) === false ) { + + material.iridescenceIORNode = inputs.thin_film_ior; + + } + + } + + const emissionColor = hasNodeValue( inputs.emission_color ) ? inputs.emission_color : color( 1, 1, 1 ); + const emissionLuminance = hasNodeValue( inputs.emission_luminance ) ? inputs.emission_luminance : float( 0 ); + if ( isEffectivelyZero( emissionLuminance ) === false ) { + + material.emissiveNode = mul( emissionColor, emissionLuminance ); + + } + + if ( hasNodeValue( inputs.geometry_opacity ) && isEffectivelyOne( inputs.geometry_opacity ) === false ) material.transparent = true; + if ( transmissionEnabled ) material.transparent = true; + + setTransmissionFlags( material, inputs.transmission_weight, inputs.geometry_opacity ); + warnIgnoredInputs( inputs, mappedOpenPbrInputs, log, 'open_pbr_surface', nodeName ); + +} + +const MaterialXSurfaceMappings = { + standard_surface: applyStandardSurface, + gltf_pbr: applyGltfPbrSurface, + open_pbr_surface: applyOpenPbrSurface, +}; + +const surfaceMapperRegistry = new Map( Object.entries( MaterialXSurfaceMappings ).map( ( [ category, apply ] ) => [ + category, + { category, apply }, +] ) ); + +function getSurfaceMapper( category ) { + + return surfaceMapperRegistry.get( category ); + +} + +function getSupportedSurfaceCategories() { + + return [ ...surfaceMapperRegistry.keys() ]; + +} + +export { + MaterialXSurfaceMappings, + surfaceMapperRegistry, + getSurfaceMapper, + getSupportedSurfaceCategories, + applyStandardSurface, + applyGltfPbrSurface, + applyOpenPbrSurface, + mappedStandardSurfaceInputs, + mappedGltfPbrInputs, + mappedOpenPbrInputs, +}; diff --git a/examples/jsm/loaders/materialx/MaterialXUtils.js b/examples/jsm/loaders/materialx/MaterialXUtils.js new file mode 100644 index 00000000000000..b0bf44129794b0 --- /dev/null +++ b/examples/jsm/loaders/materialx/MaterialXUtils.js @@ -0,0 +1,57 @@ +import { + bool, + element, + float, + vec3, +} from 'three/tsl'; + +const BOOLEAN_OPERATOR_OPS = new Set( [ '&&', '||', '^^', '!', '==', '!=', '<', '>', '<=', '>=' ] ); + +function normalizeSpaceName( value, fallback = 'world' ) { + + if ( typeof value !== 'string' ) return fallback; + const normalized = value.trim().toLowerCase(); + if ( normalized === '' ) return fallback; + if ( normalized === 'world' ) return 'world'; + if ( normalized === 'object' || normalized === 'model' ) return 'object'; + return fallback; + +} + +function isBooleanNode( node ) { + + return node && ( node.nodeType === 'bool' || ( node.isOperatorNode && BOOLEAN_OPERATOR_OPS.has( node.op ) ) ); + +} + +function toBooleanNode( node ) { + + if ( ! node ) return bool( false ); + if ( typeof node === 'boolean' ) return bool( node ); + if ( typeof node === 'number' ) return bool( node !== 0 ); + if ( isBooleanNode( node ) ) return node; + return node.notEqual( float( 0 ) ); + +} + +function getComponentCountForType( type ) { + + if ( type === 'vector2' ) return 2; + if ( type === 'vector3' || type === 'color3' ) return 3; + return 4; + +} + +function toVec3Channels( input ) { + + return vec3( element( input, 0 ), element( input, 1 ), element( input, 2 ) ); + +} + +export { + getComponentCountForType, + isBooleanNode, + normalizeSpaceName, + toBooleanNode, + toVec3Channels, +}; diff --git a/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js b/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js new file mode 100644 index 00000000000000..b934e1d7f7e57c --- /dev/null +++ b/examples/jsm/loaders/materialx/compile/MaterialXCompileRegistry.js @@ -0,0 +1,997 @@ +import { + element, + float, + int, + mat3, + mat4, + mul, + normalMap, + texture, + uv, + vec2, + vec3, + vec4, + vertexColor, + positionLocal, + positionWorld, + normalLocal, + normalWorld, + tangentLocal, + tangentWorld, + bitangentLocal, + bitangentWorld, + clamp, + add, + abs, + min, + sub, + floor, + mix, + dot, + div, + max, + normalize, + mx_atan2, + pow, + sqrt, + sign, +} from 'three/tsl'; +import { + getComponentCountForType, + normalizeSpaceName, + toBooleanNode, + toVec3Channels, +} from '../MaterialXUtils.js'; +import { MaterialXLogCodes } from '../MaterialXLog.js'; + +const register = ( registry, categories, handler ) => { + + for ( const category of categories ) { + + registry.set( category, handler ); + + } + +}; + +const UV_FALLBACK_CATEGORIES = new Set( [ 'checkerboard', 'noise2d', 'fractal2d', 'cellnoise2d', 'worleynoise2d', 'unifiednoise2d', 'heighttonormal' ] ); +const SCALAR_TYPES = new Set( [ 'boolean', 'integer', 'float' ] ); +const THREE_COMPONENT_TYPES = new Set( [ 'vector2', 'vector3', 'vector4', 'color3', 'color4' ] ); +const TEXTURE_ADDRESS_MODES = new Set( [ 'constant', 'clamp', 'periodic', 'mirror' ] ); +const SWITCH_MIN_INDEX = 1; +const SWITCH_MAX_INDEX = 10; + +const getDefaultUvNode = ( compileContext ) => compileContext.mxToBottomLeftUvSpace( uv( 0 ) ); + +const toBooleanMaskNode = ( node ) => toBooleanNode( node ).select( float( 1 ), float( 0 ) ); + +const getTextureAddressMode = ( nodeX, inputName ) => { + + const value = nodeX.getInputValueByName( inputName ); + if ( value === null || value === undefined || value === '' ) return 'periodic'; + + const mode = value.trim().toLowerCase(); + return TEXTURE_ADDRESS_MODES.has( mode ) ? mode : 'periodic'; + +}; + +const getTextureAddressModes = ( nodeX ) => ( { + u: getTextureAddressMode( nodeX, 'uaddressmode' ), + v: getTextureAddressMode( nodeX, 'vaddressmode' ), +} ); + +const getZeroNodeForType = ( type ) => { + + if ( type === 'vector2' ) return vec2( 0, 0 ); + if ( type === 'vector3' || type === 'color3' ) return vec3( 0, 0, 0 ); + if ( type === 'vector4' || type === 'color4' ) return vec4( 0, 0, 0, 0 ); + return float( 0 ); + +}; + +const toTextureDefaultNode = ( node, type ) => { + + if ( type === 'vector2' ) return vec4( node, 0, 1 ); + if ( type === 'vector3' || type === 'color3' ) return vec4( node, 1 ); + if ( type === 'vector4' || type === 'color4' ) return vec4( node ); + return vec4( node, 0, 0, 1 ); + +}; + +const getTextureInputs = ( nodeX, compileContext ) => { + + const file = nodeX.getChildByName( 'file' ); + const uvNode = nodeX.getNodeByName( 'texcoord' ) || getDefaultUvNode( compileContext ); + const textureFile = file ? file.getTexture() : null; + const defaultNode = nodeX.getNodeByName( 'default' ) || getZeroNodeForType( nodeX.type ); + const addressModes = getTextureAddressModes( nodeX ); + return { file, uvNode, textureFile, defaultNode, addressModes }; + +}; + +const applyTextureAddressModeDefault = ( node, uvNode, addressModes, defaultNode ) => { + + let outsideBounds = null; + + if ( addressModes.u === 'constant' ) { + + const u = element( uvNode, 0 ); + outsideBounds = u.lessThan( 0 ).or( u.greaterThan( 1 ) ); + + } + + if ( addressModes.v === 'constant' ) { + + const v = element( uvNode, 1 ); + const vOutsideBounds = v.lessThan( 0 ).or( v.greaterThan( 1 ) ); + outsideBounds = outsideBounds ? outsideBounds.or( vOutsideBounds ) : vOutsideBounds; + + } + + return outsideBounds ? outsideBounds.select( defaultNode, node ) : node; + +}; + +const sampleTexture = ( textureFile, uvNode, compileContext, fallback, addressModes = null, defaultNode = fallback ) => { + + if ( ! textureFile ) return fallback; + + const textureUvNode = compileContext.mxFromBottomLeftUvSpace( uvNode ); + const sampled = texture( textureFile, textureUvNode ); + return addressModes ? applyTextureAddressModeDefault( sampled, textureUvNode, addressModes, defaultNode ) : sampled; + +}; + +const applyTextureColorSpace = ( node, file ) => { + + const colorSpaceNode = file ? file.getColorSpaceNode() : null; + return colorSpaceNode ? colorSpaceNode( node ) : node; + +}; + +const compileConvertNode = ( nodeX ) => { + + const input = nodeX.getNodeByName( 'in' ); + const inputElement = nodeX.getChildByName( 'in' ); + const inputType = inputElement ? inputElement.type : null; + const nodeClass = nodeX.getClassFromType( nodeX.type ) || float; + + if ( nodeX.type === 'boolean' ) { + + return toBooleanNode( input ); + + } + + if ( inputType === 'boolean' ) { + + const inputMask = toBooleanMaskNode( input ); + if ( THREE_COMPONENT_TYPES.has( nodeX.type ) ) { + + const componentCount = getComponentCountForType( nodeX.type ); + return nodeClass( ...Array( componentCount ).fill( inputMask ) ); + + } + + return nodeClass( inputMask ); + + } + + if ( SCALAR_TYPES.has( inputType ) && THREE_COMPONENT_TYPES.has( nodeX.type ) ) { + + const componentCount = getComponentCountForType( nodeX.type ); + return nodeClass( ...Array( componentCount ).fill( input ) ); + + } + + if ( THREE_COMPONENT_TYPES.has( inputType ) && SCALAR_TYPES.has( nodeX.type ) ) { + + return nodeClass( element( input, 0 ) ); + + } + + return nodeClass( input ); + +}; + +const compileConstantNode = ( nodeX ) => nodeX.getNodeByName( 'value' ); + +const compileArtisticIorNode = ( nodeX, out ) => { + + const reflectivity = clamp( + nodeX.getNodeByName( 'reflectivity' ) || vec3( 0.944, 0.776, 0.373 ), + vec3( 0, 0, 0 ), + vec3( 0.99, 0.99, 0.99 ), + ); + const edgeColor = nodeX.getNodeByName( 'edge_color' ) || vec3( 0.998, 0.981, 0.751 ); + const one = vec3( 1, 1, 1 ); + const nMin = div( sub( one, reflectivity ), add( one, reflectivity ) ); + const nMax = div( add( one, sqrt( reflectivity ) ), sub( one, sqrt( reflectivity ) ) ); + const ior = mix( nMax, nMin, edgeColor ); + const iorPlusOne = add( ior, one ); + const iorMinusOne = sub( ior, one ); + const k2 = max( + div( + sub( + mul( mul( iorPlusOne, iorPlusOne ), reflectivity ), + mul( iorMinusOne, iorMinusOne ), + ), + sub( one, reflectivity ), + ), + vec3( 0, 0, 0 ), + ); + const extinction = sqrt( k2 ); + return out === 'extinction' ? extinction : ior; + +}; + +const compileBooleanConditionalNode = ( nodeX ) => { + + if ( nodeX.type !== 'boolean' ) return null; + + const value1Default = nodeX.element === 'ifequal' ? float( 0 ) : float( 1 ); + const value2Default = float( 0 ); + const value1 = nodeX.getNodeByName( 'value1' ) || value1Default; + const value2 = nodeX.getNodeByName( 'value2' ) || value2Default; + + if ( nodeX.element === 'ifgreater' ) return value1.greaterThan( value2 ); + if ( nodeX.element === 'ifgreatereq' ) return value1.greaterThanEqual( value2 ); + if ( nodeX.element === 'ifequal' ) return value1.equal( value2 ); + + return null; + +}; + +const compileClampNode = ( nodeX ) => { + + const inNode = nodeX.getNodeByName( 'in' ) || float( 0 ); + const low = nodeX.getNodeByName( 'low' ) || float( 0 ); + const high = nodeX.getNodeByName( 'high' ) || float( 1 ); + return min( max( inNode, low ), high ); + +}; + +const compileNormalizeNode = ( nodeX ) => { + + const inNode = nodeX.getNodeByName( 'in' ) || getZeroNodeForType( nodeX.type ); + const zeroNode = getZeroNodeForType( nodeX.type ); + const lengthSquared = dot( inNode, inNode ); + const safeLengthSquared = max( lengthSquared, float( 1e-8 ) ); + const normalized = mul( inNode, div( float( 1 ), sqrt( safeLengthSquared ) ) ); + return abs( lengthSquared ).lessThan( float( 1e-8 ) ).select( zeroNode, normalized ); + +}; + +const compileRemapNode = ( nodeX ) => { + + const inNode = nodeX.getNodeByName( 'in' ) || float( 0 ); + const inLow = nodeX.getNodeByName( 'inlow' ) || float( 0 ); + const inHigh = nodeX.getNodeByName( 'inhigh' ) || float( 1 ); + const outLow = nodeX.getNodeByName( 'outlow' ) || float( 0 ); + const outHigh = nodeX.getNodeByName( 'outhigh' ) || float( 1 ); + const denominator = sub( inHigh, inLow ); + const isDegenerate = abs( denominator ).lessThan( float( 1e-8 ) ); + const safeDenominator = isDegenerate.select( float( 1 ), denominator ); + const remapped = add( + mul( div( sub( inNode, inLow ), safeDenominator ), sub( outHigh, outLow ) ), + outLow, + ); + return isDegenerate.select( outLow, remapped ); + +}; + +const compileRangeNode = ( nodeX ) => { + + const inNode = nodeX.getNodeByName( 'in' ) || float( 0 ); + const inLow = nodeX.getNodeByName( 'inlow' ) || float( 0 ); + const inHigh = nodeX.getNodeByName( 'inhigh' ) || float( 1 ); + const outLow = nodeX.getNodeByName( 'outlow' ) || float( 0 ); + const outHigh = nodeX.getNodeByName( 'outhigh' ) || float( 1 ); + const gamma = nodeX.getNodeByName( 'gamma' ) || float( 1 ); + const doClamp = nodeX.getNodeByName( 'doclamp' ) || int( 0 ); + + const denominator = sub( inHigh, inLow ); + const isDegenerate = abs( denominator ).lessThan( float( 1e-8 ) ); + const safeDenominator = isDegenerate.select( float( 1 ), denominator ); + const normalized = div( sub( inNode, inLow ), safeDenominator ); + // Match stdlib range nodegraph semantics: + // gamma stage is sign(normalized) * pow(abs(normalized), 1 / gamma). + const reciprocalGamma = div( float( 1 ), gamma ); + const gammaApplied = mul( pow( abs( normalized ), reciprocalGamma ), sign( normalized ) ); + const remapped = add( mul( gammaApplied, sub( outHigh, outLow ) ), outLow ); + const result = isDegenerate.select( outLow, remapped ); + const clamped = min( max( result, outLow ), outHigh ); + + return toBooleanNode( doClamp ).select( clamped, result ); + +}; + +const getSwitchBranchNode = ( nodeX, index ) => nodeX.getNodeByName( `in${index}` ) || getZeroNodeForType( nodeX.type ); + +const compileSwitchNode = ( nodeX ) => { + + const fallbackNode = getSwitchBranchNode( nodeX, SWITCH_MIN_INDEX ); + const whichInput = nodeX.getNodeByName( 'which' ); + const switchIndex = add( floor( float( whichInput === undefined || whichInput === null ? 0 : whichInput ) ), 1 ); + const whichNode = clamp( + float( switchIndex ), + float( SWITCH_MIN_INDEX ), + float( SWITCH_MAX_INDEX ), + ); + + let result = fallbackNode; + for ( let branchIndex = SWITCH_MIN_INDEX + 1; branchIndex <= SWITCH_MAX_INDEX; branchIndex += 1 ) { + + const branchNode = getSwitchBranchNode( nodeX, branchIndex ); + result = whichNode.equal( float( branchIndex ) ).select( branchNode, result ); + + } + + return result; + +}; + +const compileSpaceInputNode = ( nodeX, objectNode, worldNode ) => { + + const rawSpace = nodeX.getInputValueByName( 'space' ) ?? nodeX.getAttribute( 'space' ); + const space = normalizeSpaceName( rawSpace, 'object' ); + return space === 'world' ? worldNode : objectNode; + +}; + +const compileNormalizedSpaceInputNode = ( nodeX, objectNode, worldNode ) => normalize( compileSpaceInputNode( nodeX, objectNode, worldNode ) ); + +const compileTexcoordNode = ( nodeX, compileContext ) => { + + const indexNode = nodeX.getChildByName( 'index' ); + const index = indexNode ? parseInt( indexNode.value, 10 ) : 0; + return compileContext.mxToBottomLeftUvSpace( uv( index ) ); + +}; + +const compileGeomColorNode = ( nodeX ) => { + + const indexNode = nodeX.getChildByName( 'index' ); + const index = indexNode ? parseInt( indexNode.value, 10 ) : 0; + return vertexColor( index ); + +}; + +const compileImageLikeNode = ( nodeX, compileContext ) => { + + const { file, uvNode, textureFile, defaultNode, addressModes } = getTextureInputs( nodeX, compileContext ); + const textureDefault = toTextureDefaultNode( defaultNode, nodeX.type ); + const node = sampleTexture( textureFile, uvNode, compileContext, textureDefault, addressModes, textureDefault ); + return applyTextureColorSpace( node, file ); + +}; + +const compileTiledImageNode = ( nodeX, compileContext ) => { + + const { file, uvNode, textureFile, defaultNode, addressModes } = getTextureInputs( nodeX, compileContext ); + const textureDefault = toTextureDefaultNode( defaultNode, nodeX.type ); + if ( ! textureFile ) { + + return textureDefault; + + } + + const uvTiling = nodeX.getNodeByName( 'uvtiling' ); + const uvOffset = nodeX.getNodeByName( 'uvoffset' ); + const transformedUv = compileContext.mxTransformUv( uvTiling, uvOffset, uvNode ); + const node = sampleTexture( textureFile, transformedUv, compileContext, textureDefault, addressModes, textureDefault ); + return applyTextureColorSpace( node, file ); + +}; + +const compileHexTiledNormalMapNode = ( nodeX, compileContext, sampleNode ) => { + + const normalMapNodeElement = compileContext.nodeLibrary.normalmap; + const strengthNode = nodeX.getNodeByName( 'strength' ) || float( 1 ); + + if ( ! normalMapNodeElement || typeof normalMapNodeElement.nodeFunc !== 'function' ) { + + return normalMap( vec4( sampleNode, 1 ), strengthNode ); + + } + + const args = normalMapNodeElement.params.map( ( paramName ) => { + + if ( paramName === 'in' ) return sampleNode; + if ( paramName === 'scale' ) return strengthNode; + return nodeX.getNodeByName( paramName ); + + } ); + + for ( let i = 0; i < normalMapNodeElement.params.length; i += 1 ) { + + if ( args[ i ] !== undefined && args[ i ] !== null ) { + + continue; + + } + + const paramName = normalMapNodeElement.params[ i ]; + const defaultValue = normalMapNodeElement.defaults ? normalMapNodeElement.defaults[ paramName ] : undefined; + args[ i ] = defaultValue !== undefined ? ( typeof defaultValue === 'function' ? defaultValue() : float( defaultValue ) ) : float( 0 ); + + } + + return normalMapNodeElement.nodeFunc( ...args ); + +}; + +const compileHexTiledTextureNode = ( nodeX, compileContext, category ) => { + + const file = nodeX.getChildByName( 'file' ); + if ( ! file ) { + + nodeX.materialX.log.add( + MaterialXLogCodes.INVALID_VALUE, + `Texture node "${nodeX.name || nodeX.element}" is missing required input "file".`, + nodeX.name, + ); + if ( category === 'hextilednormalmap' ) { + + return normalize( nodeX.getNodeByName( 'normal' ) || normalLocal ); + + } + + return vec4( 0, 0, 0, 1 ); + + } + + const textureFile = file.getTexture(); + if ( ! textureFile ) { + + if ( category === 'hextilednormalmap' ) { + + return normalize( nodeX.getNodeByName( 'normal' ) || normalLocal ); + + } + + return vec4( 0, 0, 0, 1 ); + + } + + const uvNode = nodeX.getNodeByName( 'texcoord' ) || getDefaultUvNode( compileContext ); + const tiling = nodeX.getNodeByName( 'tiling' ) || vec2( 1, 1 ); + const rotation = nodeX.getNodeByName( 'rotation' ) || float( 1 ); + const rotationRange = nodeX.getNodeByName( 'rotationrange' ) || vec2( 0, 360 ); + const scale = nodeX.getNodeByName( 'scale' ) || float( 1 ); + const scaleRange = nodeX.getNodeByName( 'scalerange' ) || vec2( 0.5, 2 ); + const offset = nodeX.getNodeByName( 'offset' ) || float( 1 ); + const offsetRange = nodeX.getNodeByName( 'offsetrange' ) || vec2( 0, 1 ); + const falloff = nodeX.getNodeByName( 'falloff' ) || float( 0.5 ); + const falloffContrast = nodeX.getNodeByName( 'falloffcontrast' ) || float( 0.5 ); + let lumaCoeffs = nodeX.getNodeByName( 'lumacoeffs' ) || vec3( 0.2722287, 0.6740818, 0.0536895 ); + const lumaCoeffsInput = nodeX.getChildByName( 'lumacoeffs' ); + if ( lumaCoeffsInput && lumaCoeffsInput.isConst ) { + + const lumaCoeffValues = lumaCoeffsInput.getVector(); + if ( lumaCoeffValues.length === 3 ) { + + // Treat luminance coefficients as raw numeric values, not display colors. + lumaCoeffs = vec3( lumaCoeffValues[ 0 ], lumaCoeffValues[ 1 ], lumaCoeffValues[ 2 ] ); + + } + + } + + const transformedUv = compileContext.mxFromBottomLeftUvSpace( mul( uvNode, tiling ) ); + const tileData = compileContext.mxHextileCoord( transformedUv, rotation, rotationRange, scale, scaleRange, offset, offsetRange ); + + let sample0 = texture( textureFile, tileData.coords[ 0 ] ).grad( + tileData.ddx[ 0 ], + tileData.ddy[ 0 ], + ); + let sample1 = texture( textureFile, tileData.coords[ 1 ] ).grad( + tileData.ddx[ 1 ], + tileData.ddy[ 1 ], + ); + let sample2 = texture( textureFile, tileData.coords[ 2 ] ).grad( + tileData.ddx[ 2 ], + tileData.ddy[ 2 ], + ); + const sample0Raw = sample0; + const sample1Raw = sample1; + const sample2Raw = sample2; + + const colorSpaceNode = file.getColorSpaceNode(); + if ( colorSpaceNode ) { + + sample0 = colorSpaceNode( sample0 ); + sample1 = colorSpaceNode( sample1 ); + sample2 = colorSpaceNode( sample2 ); + + } + + const c0 = toVec3Channels( sample0 ); + const c1 = toVec3Channels( sample1 ); + const c2 = toVec3Channels( sample2 ); + const falloffContrastWeight = mul( falloffContrast, 0.5 ); + const cw = mix( + vec3( 1, 1, 1 ), + vec3( dot( c0, lumaCoeffs ), dot( c1, lumaCoeffs ), dot( c2, lumaCoeffs ) ), + vec3( falloffContrastWeight, falloffContrastWeight, falloffContrastWeight ), + ); + const blendWeights = compileContext.mxHextileComputeBlendWeights( cw, tileData.weights, falloff ); + const alphaWeights = compileContext.mxHextileComputeBlendWeights( vec3( 1, 1, 1 ), tileData.weights, falloff ); + const blendedRgb = add( add( mul( element( blendWeights, 0 ), c0 ), mul( element( blendWeights, 1 ), c1 ) ), mul( element( blendWeights, 2 ), c2 ) ); + const blendedAlpha = add( + add( mul( element( alphaWeights, 0 ), element( sample0Raw, 3 ) ), mul( element( alphaWeights, 1 ), element( sample1Raw, 3 ) ) ), + mul( element( alphaWeights, 2 ), element( sample2Raw, 3 ) ), + ); + const blended = vec4( blendedRgb, blendedAlpha ); + + if ( category === 'hextilednormalmap' ) { + + const flipGNode = nodeX.getNodeByName( 'flip_g' ); + let normalSample = blended; + + if ( flipGNode ) { + + const flippedSample = vec4( + element( blended, 0 ), + sub( 1, element( blended, 1 ) ), + element( blended, 2 ), + element( blended, 3 ), + ); + normalSample = toBooleanNode( flipGNode ).select( flippedSample, blended ); + + } + + return compileHexTiledNormalMapNode( nodeX, compileContext, toVec3Channels( normalSample ) ); + + } + + return blended; + +}; + +const compileGltfTextureNode = ( nodeX, compileContext, category ) => { + + const { file, uvNode, textureFile, addressModes } = getTextureInputs( nodeX, compileContext ); + let transformedUv = uvNode; + const place2d = compileContext.nodeLibrary.place2d; + + if ( place2d ) { + + const pivot = nodeX.getNodeByName( 'pivot' ) || vec2( 0, 1 ); + const scale = nodeX.getNodeByName( 'scale' ) || vec2( 1, 1 ); + const rotate = nodeX.getNodeByName( 'rotate' ) || float( 0 ); + const offset = nodeX.getNodeByName( 'offset' ) || vec2( 0, 0 ); + const operationorder = nodeX.getNodeByName( 'operationorder' ) || int( 0 ); + transformedUv = place2d.nodeFunc( + uvNode, + pivot, + div( vec2( 1, 1 ), scale ), + mul( rotate, - 1 ), + mul( offset, vec2( - 1, 1 ) ), + operationorder, + ); + + } + + const defaultInput = nodeX.getNodeByName( 'default' ); + let fallback; + + if ( nodeX.type === 'color3' || nodeX.type === 'vector3' ) { + + const defaultColor = defaultInput || vec3( 0, 0, 0 ); + fallback = vec4( element( defaultColor, 0 ), element( defaultColor, 1 ), element( defaultColor, 2 ), 1 ); + + } else if ( nodeX.type === 'color4' || nodeX.type === 'vector4' ) { + + fallback = defaultInput || vec4( 0, 0, 0, 1 ); + + } else { + + const defaultValue = defaultInput || float( 0 ); + fallback = vec4( defaultValue, 0, 0, 1 ); + + } + + const node = applyTextureColorSpace( sampleTexture( textureFile, transformedUv, compileContext, fallback, addressModes, fallback ), file ); + + if ( category === 'gltf_normalmap' ) { + + const normalScale = nodeX.getNodeByName( 'scale' ) || float( 1 ); + return normalMap( node, normalScale ); + + } + + const factor = nodeX.getNodeByName( 'factor' ); + + if ( factor ) { + + if ( nodeX.type === 'color3' || nodeX.type === 'vector3' ) { + + return mul( factor, toVec3Channels( node ) ); + + } + + return mul( factor, node ); + + } + + return node; + +}; + +const compileGltfColorImageNode = ( nodeX, out, compileContext ) => { + + const { file, uvNode, textureFile, addressModes } = getTextureInputs( nodeX, compileContext ); + let transformedUv = uvNode; + const place2d = compileContext.nodeLibrary.place2d; + + if ( place2d ) { + + const pivot = nodeX.getNodeByName( 'pivot' ) || vec2( 0, 1 ); + const scale = nodeX.getNodeByName( 'scale' ) || vec2( 1, 1 ); + const rotate = nodeX.getNodeByName( 'rotate' ) || float( 0 ); + const offset = nodeX.getNodeByName( 'offset' ) || vec2( 0, 0 ); + // Match MaterialX's ND_gltf_colorimage graph implementation, which wires gltf_image with operationorder=0. + const operationorder = int( 0 ); + transformedUv = place2d.nodeFunc( + uvNode, + pivot, + div( vec2( 1, 1 ), scale ), + mul( rotate, - 1 ), + mul( offset, vec2( - 1, 1 ) ), + operationorder, + ); + + } + + const defaultInput = nodeX.getNodeByName( 'default' ) || vec4( 0, 0, 0, 0 ); + const fallback = vec4( defaultInput ); + const sampled = sampleTexture( textureFile, transformedUv, compileContext, fallback, addressModes, fallback ); + const converted = applyTextureColorSpace( sampled, file ); + const color = nodeX.getNodeByName( 'color' ) || vec4( 1, 1, 1, 1 ); + const geomcolor = nodeX.getNodeByName( 'geomcolor' ) || vec4( 1, 1, 1, 1 ); + const modulated = mul( mul( converted, color ), geomcolor ); + + if ( out === 'outa' ) { + + return element( modulated, 3 ); + + } + + return toVec3Channels( modulated ); + +}; + +const compileGltfAnisotropyImageNode = ( nodeX, out, compileContext ) => { + + const { uvNode, textureFile, addressModes } = getTextureInputs( nodeX, compileContext ); + const defaultInput = nodeX.getNodeByName( 'default' ) || vec3( 1, 0.5, 1 ); + const fallback = vec4( element( defaultInput, 0 ), element( defaultInput, 1 ), element( defaultInput, 2 ), 1 ); + const sampled = sampleTexture( textureFile, uvNode, compileContext, fallback, addressModes, fallback ); + const anisotropyStrengthFactor = nodeX.getNodeByName( 'anisotropy_strength' ) || float( 1 ); + const anisotropyRotationFactor = nodeX.getNodeByName( 'anisotropy_rotation' ) || float( 0 ); + const encodedDirection = vec2( sub( mul( element( sampled, 0 ), 2 ), 1 ), sub( mul( element( sampled, 1 ), 2 ), 1 ) ); + const textureRotation = mx_atan2( element( encodedDirection, 1 ), element( encodedDirection, 0 ) ); + const anisotropyStrengthOut = clamp( mul( anisotropyStrengthFactor, element( sampled, 2 ) ), 0, 1 ); + const anisotropyRotationOut = add( anisotropyRotationFactor, textureRotation ); + + if ( out === 'anisotropy_rotation_out' ) { + + return anisotropyRotationOut; + + } + + return anisotropyStrengthOut; + +}; + +const compileGltfIridescenceThicknessNode = ( nodeX, compileContext ) => { + + const { uvNode, textureFile, addressModes } = getTextureInputs( nodeX, compileContext ); + const fallback = vec4( 0, 0, 0, 1 ); + const sampled = sampleTexture( textureFile, uvNode, compileContext, fallback, addressModes, fallback ); + const sampledThickness = element( sampled, 0 ); + const thicknessMin = nodeX.getNodeByName( 'thicknessMin' ) || float( 100 ); + const thicknessMax = nodeX.getNodeByName( 'thicknessMax' ) || float( 400 ); + return add( thicknessMin, mul( sampledThickness, sub( thicknessMax, thicknessMin ) ) ); + +}; + +const compileTransformMatrixNode = ( nodeX, compileContext ) => { + + const nodeDefName = nodeX.getAttribute( 'nodedef' ); + const inNode = nodeX.getNodeByName( 'in' ) || float( 0 ); + const matrixNode = + nodeX.getNodeByName( 'mat' ) || + ( nodeDefName === 'ND_transformmatrix_vector2M3' || nodeDefName === 'ND_transformmatrix_vector3' + ? mat3( ...compileContext.IDENTITY_MAT3_VALUES ) + : mat4( ...compileContext.IDENTITY_MAT4_VALUES ) ); + + if ( nodeDefName === 'ND_transformmatrix_vector2M3' ) { + + const transformed = mul( matrixNode, vec3( element( inNode, 0 ), element( inNode, 1 ), 1 ) ); + return vec2( element( transformed, 0 ), element( transformed, 1 ) ); + + } + + if ( nodeDefName === 'ND_transformmatrix_vector3' ) { + + return mul( matrixNode, vec3( element( inNode, 0 ), element( inNode, 1 ), element( inNode, 2 ) ) ); + + } + + if ( nodeDefName === 'ND_transformmatrix_vector3M4' ) { + + const transformed = mul( matrixNode, vec4( element( inNode, 0 ), element( inNode, 1 ), element( inNode, 2 ), 1 ) ); + return vec3( element( transformed, 0 ), element( transformed, 1 ), element( transformed, 2 ) ); + + } + + return mul( matrixNode, vec4( element( inNode, 0 ), element( inNode, 1 ), element( inNode, 2 ), element( inNode, 3 ) ) ); + +}; + +const compileCreateMatrixNode = ( nodeX ) => { + + if ( nodeX.type === 'matrix44' ) { + + const vector3Input = nodeX.getAttribute( 'nodedef' ) === 'ND_creatematrix_vector3_matrix44'; + const toVec4Input = ( name, fallback, w ) => { + + const input = nodeX.getNodeByName( name ) || fallback; + return vector3Input ? vec4( element( input, 0 ), element( input, 1 ), element( input, 2 ), w ) : input; + + }; + + const in1 = toVec4Input( 'in1', vector3Input ? vec3( 1, 0, 0 ) : vec4( 1, 0, 0, 0 ), 0 ); + const in2 = toVec4Input( 'in2', vector3Input ? vec3( 0, 1, 0 ) : vec4( 0, 1, 0, 0 ), 0 ); + const in3 = toVec4Input( 'in3', vector3Input ? vec3( 0, 0, 1 ) : vec4( 0, 0, 1, 0 ), 0 ); + const in4 = toVec4Input( 'in4', vector3Input ? vec3( 0, 0, 0 ) : vec4( 0, 0, 0, 1 ), 1 ); + return mat4( in1, in2, in3, in4 ); + + } + + const in1 = nodeX.getNodeByName( 'in1' ) || vec3( 1, 0, 0 ); + const in2 = nodeX.getNodeByName( 'in2' ) || vec3( 0, 1, 0 ); + const in3 = nodeX.getNodeByName( 'in3' ) || vec3( 0, 0, 1 ); + return mat3( in1, in2, in3 ); + +}; + +const getMatrixElement = ( matrixNode, row, column ) => element( element( matrixNode, column ), row ); + +const determinant2 = ( a, b, c, d ) => sub( mul( a, d ), mul( b, c ) ); + +const determinant3 = ( m00, m01, m02, m10, m11, m12, m20, m21, m22 ) => + add( + sub( mul( m00, determinant2( m11, m12, m21, m22 ) ), mul( m01, determinant2( m10, m12, m20, m22 ) ) ), + mul( m02, determinant2( m10, m11, m20, m21 ) ), + ); + +const compileInvertMatrix3Node = ( matrixNode ) => { + + const m00 = getMatrixElement( matrixNode, 0, 0 ); + const m01 = getMatrixElement( matrixNode, 0, 1 ); + const m02 = getMatrixElement( matrixNode, 0, 2 ); + const m10 = getMatrixElement( matrixNode, 1, 0 ); + const m11 = getMatrixElement( matrixNode, 1, 1 ); + const m12 = getMatrixElement( matrixNode, 1, 2 ); + const m20 = getMatrixElement( matrixNode, 2, 0 ); + const m21 = getMatrixElement( matrixNode, 2, 1 ); + const m22 = getMatrixElement( matrixNode, 2, 2 ); + + const inv00 = determinant2( m11, m12, m21, m22 ); + const inv01 = determinant2( m02, m01, m22, m21 ); + const inv02 = determinant2( m01, m02, m11, m12 ); + const inv10 = determinant2( m12, m10, m22, m20 ); + const inv11 = determinant2( m00, m02, m20, m22 ); + const inv12 = determinant2( m02, m00, m12, m10 ); + const inv20 = determinant2( m10, m11, m20, m21 ); + const inv21 = determinant2( m01, m00, m21, m20 ); + const inv22 = determinant2( m00, m01, m10, m11 ); + const determinant = add( add( mul( m00, inv00 ), mul( m01, inv10 ) ), mul( m02, inv20 ) ); + + return mat3( + div( inv00, determinant ), div( inv10, determinant ), div( inv20, determinant ), + div( inv01, determinant ), div( inv11, determinant ), div( inv21, determinant ), + div( inv02, determinant ), div( inv12, determinant ), div( inv22, determinant ), + ); + +}; + +const compileInvertMatrix4Node = ( matrixNode ) => { + + const m = []; + for ( let row = 0; row < 4; row ++ ) { + + m[ row ] = []; + for ( let column = 0; column < 4; column ++ ) { + + m[ row ][ column ] = getMatrixElement( matrixNode, row, column ); + + } + + } + + const getMinor3 = ( skipRow, skipColumn ) => { + + const rows = [ 0, 1, 2, 3 ].filter( ( row ) => row !== skipRow ); + const columns = [ 0, 1, 2, 3 ].filter( ( column ) => column !== skipColumn ); + return determinant3( + m[ rows[ 0 ] ][ columns[ 0 ] ], m[ rows[ 0 ] ][ columns[ 1 ] ], m[ rows[ 0 ] ][ columns[ 2 ] ], + m[ rows[ 1 ] ][ columns[ 0 ] ], m[ rows[ 1 ] ][ columns[ 1 ] ], m[ rows[ 1 ] ][ columns[ 2 ] ], + m[ rows[ 2 ] ][ columns[ 0 ] ], m[ rows[ 2 ] ][ columns[ 1 ] ], m[ rows[ 2 ] ][ columns[ 2 ] ], + ); + + }; + + const cofactors = []; + for ( let row = 0; row < 4; row ++ ) { + + cofactors[ row ] = []; + for ( let column = 0; column < 4; column ++ ) { + + const minor = getMinor3( row, column ); + cofactors[ row ][ column ] = ( row + column ) % 2 === 0 ? minor : mul( minor, - 1 ); + + } + + } + + const determinant = add( + add( mul( m[ 0 ][ 0 ], cofactors[ 0 ][ 0 ] ), mul( m[ 0 ][ 1 ], cofactors[ 0 ][ 1 ] ) ), + add( mul( m[ 0 ][ 2 ], cofactors[ 0 ][ 2 ] ), mul( m[ 0 ][ 3 ], cofactors[ 0 ][ 3 ] ) ), + ); + const values = []; + for ( let column = 0; column < 4; column ++ ) { + + for ( let row = 0; row < 4; row ++ ) { + + values.push( div( cofactors[ column ][ row ], determinant ) ); + + } + + } + + return mat4( ...values ); + +}; + +const compileInvertMatrixNode = ( nodeX, compileContext ) => { + + const inInput = nodeX.getChildByName( 'in' ); + const matrixType = inInput ? inInput.type : null; + const isMatrixType = matrixType === 'matrix33' || matrixType === 'matrix44'; + + if ( inInput && inInput.isConst && isMatrixType ) { + + const size = matrixType === 'matrix33' ? 3 : 4; + const identityValues = size === 3 ? compileContext.IDENTITY_MAT3_VALUES : compileContext.IDENTITY_MAT4_VALUES; + const matrixValues = inInput.getVector(); + const invertedValues = compileContext.invertConstantMatrixValues( matrixValues, size ); + + if ( invertedValues === null ) { + + nodeX.materialX.log.add( + MaterialXLogCodes.INVALID_VALUE, + `Matrix input for "${nodeX.name || nodeX.element}" is singular; using identity fallback.`, + nodeX.name, + ); + return size === 3 ? mat3( ...identityValues ) : mat4( ...identityValues ); + + } + + return size === 3 ? mat3( ...invertedValues ) : mat4( ...invertedValues ); + + } + + const inNode = nodeX.getNodeByName( 'in' ); + if ( isMatrixType ) { + + const size = matrixType === 'matrix33' ? 3 : 4; + const fallback = size === 3 ? mat3( ...compileContext.IDENTITY_MAT3_VALUES ) : mat4( ...compileContext.IDENTITY_MAT4_VALUES ); + const matrixNode = inNode === undefined || inNode === null ? fallback : inNode; + return size === 3 ? compileInvertMatrix3Node( matrixNode ) : compileInvertMatrix4Node( matrixNode ); + + } + + return inNode === undefined || inNode === null ? float( 0 ) : inNode; + +}; + +function createMaterialXCompileRegistry() { + + const registry = new Map(); + register( registry, [ 'convert' ], ( nodeX ) => compileConvertNode( nodeX ) ); + register( registry, [ 'constant' ], ( nodeX ) => compileConstantNode( nodeX ) ); + register( registry, [ 'artistic_ior' ], ( nodeX, out ) => compileArtisticIorNode( nodeX, out ) ); + register( registry, [ 'clamp' ], ( nodeX ) => compileClampNode( nodeX ) ); + register( registry, [ 'normalize' ], ( nodeX ) => compileNormalizeNode( nodeX ) ); + register( registry, [ 'range' ], ( nodeX ) => compileRangeNode( nodeX ) ); + register( registry, [ 'remap' ], ( nodeX ) => compileRemapNode( nodeX ) ); + register( registry, [ 'position' ], ( nodeX ) => compileSpaceInputNode( nodeX, positionLocal, positionWorld ) ); + register( registry, [ 'normal' ], ( nodeX ) => compileNormalizedSpaceInputNode( nodeX, normalLocal, normalWorld ) ); + register( registry, [ 'tangent' ], ( nodeX ) => compileNormalizedSpaceInputNode( nodeX, tangentLocal, tangentWorld ) ); + register( registry, [ 'bitangent' ], ( nodeX ) => compileNormalizedSpaceInputNode( nodeX, bitangentLocal, bitangentWorld ) ); + register( registry, [ 'texcoord' ], ( nodeX, out, compileContext ) => compileTexcoordNode( nodeX, compileContext ) ); + register( registry, [ 'geomcolor' ], ( nodeX ) => compileGeomColorNode( nodeX ) ); + register( registry, [ 'tiledimage' ], ( nodeX, out, compileContext ) => compileTiledImageNode( nodeX, compileContext ) ); + register( registry, [ 'image' ], ( nodeX, out, compileContext ) => compileImageLikeNode( nodeX, compileContext ) ); + register( registry, [ 'hextiledimage', 'hextilednormalmap' ], ( nodeX, out, compileContext ) => + compileHexTiledTextureNode( nodeX, compileContext, nodeX.element ) ); + register( registry, [ 'gltf_image', 'gltf_normalmap' ], ( nodeX, out, compileContext ) => + compileGltfTextureNode( nodeX, compileContext, nodeX.element ) ); + register( registry, [ 'gltf_colorimage' ], ( nodeX, out, compileContext ) => compileGltfColorImageNode( nodeX, out, compileContext ) ); + register( registry, [ 'gltf_anisotropy_image' ], ( nodeX, out, compileContext ) => + compileGltfAnisotropyImageNode( nodeX, out, compileContext ) ); + register( registry, [ 'gltf_iridescence_thickness' ], ( nodeX, out, compileContext ) => + compileGltfIridescenceThicknessNode( nodeX, compileContext ) ); + register( registry, [ 'switch' ], ( nodeX ) => compileSwitchNode( nodeX ) ); + register( registry, [ 'transformmatrix' ], ( nodeX, out, compileContext ) => compileTransformMatrixNode( nodeX, compileContext ) ); + register( registry, [ 'creatematrix' ], ( nodeX ) => compileCreateMatrixNode( nodeX ) ); + register( registry, [ 'invertmatrix' ], ( nodeX, out, compileContext ) => compileInvertMatrixNode( nodeX, compileContext ) ); + return registry; + +} + +function compileNodeFromRegistry( nodeX, out, compileContext ) { + + const handler = compileContext.compileRegistry.get( nodeX.element ); + if ( handler ) { + + return handler( nodeX, out, compileContext ); + + } + + const booleanConditional = compileBooleanConditionalNode( nodeX ); + if ( booleanConditional ) { + + return booleanConditional; + + } + + const nodeElement = compileContext.nodeLibrary[ nodeX.element ]; + if ( ! nodeElement ) { + + return undefined; + + } + + const args = nodeX.getNodesByNames( ...nodeElement.params ); + for ( let i = 0; i < nodeElement.params.length; i += 1 ) { + + if ( args[ i ] !== undefined && args[ i ] !== null ) { + + continue; + + } + + const paramName = nodeElement.params[ i ]; + if ( paramName === 'texcoord' && UV_FALLBACK_CATEGORIES.has( nodeX.element ) ) { + + args[ i ] = getDefaultUvNode( compileContext ); + continue; + + } + + const defaultValue = nodeElement.defaults ? nodeElement.defaults[ paramName ] : undefined; + if ( defaultValue !== undefined ) { + + args[ i ] = typeof defaultValue === 'function' ? defaultValue() : float( defaultValue ); + continue; + + } + + nodeX.materialX.log.add( + MaterialXLogCodes.INVALID_VALUE, + `Missing input "${paramName}" for node "${nodeX.name || nodeX.element}" (${nodeX.element}). Using fallback 0.`, + nodeX.name, + ); + args[ i ] = float( 0 ); + + } + + return nodeElement.usesNode ? nodeElement.nodeFunc( ...args, nodeX ) : nodeElement.nodeFunc( ...args ); + +} + +export { createMaterialXCompileRegistry, compileNodeFromRegistry }; diff --git a/examples/jsm/loaders/materialx/parse/MaterialXParser.js b/examples/jsm/loaders/materialx/parse/MaterialXParser.js new file mode 100644 index 00000000000000..e276a578144984 --- /dev/null +++ b/examples/jsm/loaders/materialx/parse/MaterialXParser.js @@ -0,0 +1,28 @@ +function parseMaterialXNodeTree( nodeXML, createNode, addNode, nodePath = '' ) { + + const materialXNode = createNode( nodeXML, nodePath ); + if ( materialXNode.nodePath ) { + + addNode( materialXNode ); + + } + + for ( const childNodeXML of nodeXML.children ) { + + const childMXNode = parseMaterialXNodeTree( childNodeXML, createNode, addNode, materialXNode.nodePath ); + materialXNode.add( childMXNode ); + + } + + return materialXNode; + +} + +function parseMaterialXText( text, createNode, addNode ) { + + const rootXML = new DOMParser().parseFromString( text, 'application/xml' ).documentElement; + return parseMaterialXNodeTree( rootXML, createNode, addNode ); + +} + +export { parseMaterialXNodeTree, parseMaterialXText }; diff --git a/examples/materialx/gltf_pbr_glass_dispersion.mtlx b/examples/materialx/gltf_pbr_glass_dispersion.mtlx new file mode 100644 index 00000000000000..4a7725318d5bfa --- /dev/null +++ b/examples/materialx/gltf_pbr_glass_dispersion.mtlx @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/examples/materialx/open_pbr_surface_honey.mtlx b/examples/materialx/open_pbr_surface_honey.mtlx new file mode 100644 index 00000000000000..aff78bee1a0370 --- /dev/null +++ b/examples/materialx/open_pbr_surface_honey.mtlx @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/examples/materialx/open_pbr_surface_pearl.mtlx b/examples/materialx/open_pbr_surface_pearl.mtlx new file mode 100644 index 00000000000000..cc716420cb3d73 --- /dev/null +++ b/examples/materialx/open_pbr_surface_pearl.mtlx @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/examples/materialx/open_pbr_surface_velvet.mtlx b/examples/materialx/open_pbr_surface_velvet.mtlx new file mode 100644 index 00000000000000..61c83e2ab273be --- /dev/null +++ b/examples/materialx/open_pbr_surface_velvet.mtlx @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/examples/materialx/color3_vec3_cm_test.mtlx b/examples/materialx/standard_surface_color3_vec3_cm_test.mtlx similarity index 92% rename from examples/materialx/color3_vec3_cm_test.mtlx rename to examples/materialx/standard_surface_color3_vec3_cm_test.mtlx index 5007e2559d8571..3e8f340e6d29c7 100644 --- a/examples/materialx/color3_vec3_cm_test.mtlx +++ b/examples/materialx/standard_surface_color3_vec3_cm_test.mtlx @@ -4,7 +4,8 @@ - + + diff --git a/examples/materialx/combined_test.mtlx b/examples/materialx/standard_surface_combined_test.mtlx similarity index 85% rename from examples/materialx/combined_test.mtlx rename to examples/materialx/standard_surface_combined_test.mtlx index cb71307fce3b94..bbbf0da02078d4 100644 --- a/examples/materialx/combined_test.mtlx +++ b/examples/materialx/standard_surface_combined_test.mtlx @@ -5,10 +5,10 @@ - + - + diff --git a/examples/materialx/conditional_if_float.mtlx b/examples/materialx/standard_surface_conditional_if_float.mtlx similarity index 100% rename from examples/materialx/conditional_if_float.mtlx rename to examples/materialx/standard_surface_conditional_if_float.mtlx diff --git a/examples/materialx/heightnormal.mtlx b/examples/materialx/standard_surface_heightnormal.mtlx similarity index 100% rename from examples/materialx/heightnormal.mtlx rename to examples/materialx/standard_surface_heightnormal.mtlx diff --git a/examples/materialx/heighttonormal_normal_input.mtlx b/examples/materialx/standard_surface_heighttonormal_normal_input.mtlx similarity index 100% rename from examples/materialx/heighttonormal_normal_input.mtlx rename to examples/materialx/standard_surface_heighttonormal_normal_input.mtlx diff --git a/examples/materialx/image_transform.mtlx b/examples/materialx/standard_surface_image_transform.mtlx similarity index 100% rename from examples/materialx/image_transform.mtlx rename to examples/materialx/standard_surface_image_transform.mtlx diff --git a/examples/materialx/ior_test.mtlx b/examples/materialx/standard_surface_ior_test.mtlx similarity index 90% rename from examples/materialx/ior_test.mtlx rename to examples/materialx/standard_surface_ior_test.mtlx index c08bdcd0d33f8c..70f126c49cb3a1 100644 --- a/examples/materialx/ior_test.mtlx +++ b/examples/materialx/standard_surface_ior_test.mtlx @@ -5,7 +5,7 @@ - + diff --git a/examples/materialx/opacity_only_test.mtlx b/examples/materialx/standard_surface_opacity_only_test.mtlx similarity index 83% rename from examples/materialx/opacity_only_test.mtlx rename to examples/materialx/standard_surface_opacity_only_test.mtlx index ba04ebbb30959c..5c3dfccaa1fda3 100644 --- a/examples/materialx/opacity_only_test.mtlx +++ b/examples/materialx/standard_surface_opacity_only_test.mtlx @@ -5,10 +5,10 @@ - + - + \ No newline at end of file diff --git a/examples/materialx/opacity_test.mtlx b/examples/materialx/standard_surface_opacity_test.mtlx similarity index 89% rename from examples/materialx/opacity_test.mtlx rename to examples/materialx/standard_surface_opacity_test.mtlx index 7e2290e62377fd..db10a91841ff0d 100644 --- a/examples/materialx/opacity_test.mtlx +++ b/examples/materialx/standard_surface_opacity_test.mtlx @@ -5,7 +5,7 @@ - + diff --git a/examples/materialx/rotate2d_test.mtlx b/examples/materialx/standard_surface_rotate2d_test.mtlx similarity index 94% rename from examples/materialx/rotate2d_test.mtlx rename to examples/materialx/standard_surface_rotate2d_test.mtlx index d3af613c37092e..76d91405992f43 100644 --- a/examples/materialx/rotate2d_test.mtlx +++ b/examples/materialx/standard_surface_rotate2d_test.mtlx @@ -11,7 +11,6 @@ - diff --git a/examples/materialx/rotate3d_test.mtlx b/examples/materialx/standard_surface_rotate3d_test.mtlx similarity index 90% rename from examples/materialx/rotate3d_test.mtlx rename to examples/materialx/standard_surface_rotate3d_test.mtlx index a555f4a7334a7f..88f19bbd502255 100644 --- a/examples/materialx/rotate3d_test.mtlx +++ b/examples/materialx/standard_surface_rotate3d_test.mtlx @@ -12,8 +12,8 @@ - - + +