MaterialXSurfaceMappings.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. import { DoubleSide } from 'three/webgpu';
  2. import { MaterialXLogCodes } from './MaterialXLog.js';
  3. import { float, color, mul, clamp, vec2, cos, sin, pow, mix, element, transformNormalToView } from 'three/tsl';
  4. const mappedStandardSurfaceInputs = new Set( [
  5. 'base',
  6. 'base_color',
  7. 'specular_roughness',
  8. 'metalness',
  9. 'specular',
  10. 'specular_color',
  11. 'specular_anisotropy',
  12. 'specular_rotation',
  13. 'transmission',
  14. 'transmission_color',
  15. 'transmission_depth',
  16. 'thin_film_thickness',
  17. 'thin_film_IOR',
  18. 'sheen',
  19. 'sheen_color',
  20. 'sheen_roughness',
  21. 'coat',
  22. 'coat_color',
  23. 'coat_roughness',
  24. 'coat_normal',
  25. 'normal',
  26. 'opacity',
  27. 'specular_IOR',
  28. 'emission',
  29. 'emission_color',
  30. ] );
  31. const mappedGltfPbrInputs = new Set( [
  32. 'base_color',
  33. 'occlusion',
  34. 'roughness',
  35. 'metallic',
  36. 'normal',
  37. 'transmission',
  38. 'specular',
  39. 'specular_color',
  40. 'ior',
  41. 'alpha',
  42. 'alpha_mode',
  43. 'alpha_cutoff',
  44. 'iridescence',
  45. 'iridescence_ior',
  46. 'iridescence_thickness',
  47. 'sheen_color',
  48. 'sheen_roughness',
  49. 'clearcoat',
  50. 'clearcoat_roughness',
  51. 'clearcoat_normal',
  52. 'emissive',
  53. 'emissive_strength',
  54. 'attenuation_distance',
  55. 'attenuation_color',
  56. 'thickness',
  57. 'dispersion',
  58. 'anisotropy_strength',
  59. 'anisotropy_rotation',
  60. ] );
  61. const mappedOpenPbrInputs = new Set( [
  62. 'base_weight',
  63. 'base_color',
  64. 'specular_weight',
  65. 'specular_color',
  66. 'specular_roughness',
  67. 'base_metalness',
  68. 'specular_roughness_anisotropy',
  69. 'specular_ior',
  70. 'coat_weight',
  71. 'coat_ior',
  72. 'coat_color',
  73. 'coat_roughness',
  74. 'geometry_coat_normal',
  75. 'fuzz_weight',
  76. 'fuzz_color',
  77. 'fuzz_roughness',
  78. 'transmission_weight',
  79. 'transmission_color',
  80. 'transmission_depth',
  81. 'transmission_dispersion_scale',
  82. 'transmission_dispersion_abbe_number',
  83. 'geometry_normal',
  84. 'geometry_opacity',
  85. 'geometry_thin_walled',
  86. 'thin_film_weight',
  87. 'thin_film_thickness',
  88. 'thin_film_ior',
  89. 'emission_color',
  90. 'emission_luminance',
  91. ] );
  92. function warnIgnoredInputs( inputs, mappedInputs, log, surfaceCategory, nodeName ) {
  93. for ( const inputName of Object.keys( inputs ) ) {
  94. if ( mappedInputs.has( inputName ) === false ) {
  95. log.add(
  96. MaterialXLogCodes.IGNORED_SURFACE_INPUT,
  97. `${surfaceCategory} input "${inputName}" is currently ignored in MaterialX translation.`,
  98. nodeName,
  99. );
  100. }
  101. }
  102. }
  103. function hasNodeValue( value ) {
  104. return value !== undefined && value !== null;
  105. }
  106. function getConstNumber( node ) {
  107. if ( typeof node === 'number' ) return node;
  108. if ( ! node || typeof node !== 'object' ) return null;
  109. let cursor = node;
  110. const visited = new Set();
  111. while ( cursor && typeof cursor === 'object' ) {
  112. if ( visited.has( cursor ) ) break;
  113. visited.add( cursor );
  114. if ( typeof cursor.value === 'number' ) return cursor.value;
  115. cursor = cursor.node;
  116. }
  117. return null;
  118. }
  119. function isConstNear( node, target, epsilon = 1e-6 ) {
  120. const value = getConstNumber( node );
  121. if ( value === null ) return false;
  122. return Math.abs( value - target ) <= epsilon;
  123. }
  124. function isEffectivelyZero( node, epsilon = 1e-6 ) {
  125. return isConstNear( node, 0, epsilon );
  126. }
  127. function isEffectivelyOne( node, epsilon = 1e-6 ) {
  128. return isConstNear( node, 1, epsilon );
  129. }
  130. function isEnabledWeightNode( node ) {
  131. if ( hasNodeValue( node ) === false ) return false;
  132. return isEffectivelyZero( node ) === false;
  133. }
  134. function setAnisotropy( material, strengthNode, rotationNode ) {
  135. if ( ! hasNodeValue( strengthNode ) && ! hasNodeValue( rotationNode ) ) return;
  136. if ( isEffectivelyZero( strengthNode ) && isEffectivelyZero( rotationNode ) ) return;
  137. const strength = hasNodeValue( strengthNode ) ? strengthNode : float( 0 );
  138. const rotation = hasNodeValue( rotationNode ) ? rotationNode : float( 0 );
  139. material.anisotropyNode = vec2( cos( rotation ), sin( rotation ) ).mul( strength );
  140. material.anisotropyRotationNode = rotation;
  141. }
  142. function setTransmissionFlags( material, transmissionNode, opacityNode, allowOpacityTransparency = true ) {
  143. if ( allowOpacityTransparency && hasNodeValue( opacityNode ) && isEffectivelyOne( opacityNode ) === false ) {
  144. material.transparent = true;
  145. }
  146. if ( isEnabledWeightNode( transmissionNode ) ) {
  147. material.side = DoubleSide;
  148. material.transparent = true;
  149. }
  150. }
  151. function toAttenuationDistance( distanceNode, hasAttenuationColorInput ) {
  152. if ( hasNodeValue( distanceNode ) ) return distanceNode;
  153. // When attenuation tint is authored without a distance, default to a
  154. // finite value so absorption tinting is visible.
  155. return hasAttenuationColorInput ? float( 1 ) : undefined;
  156. }
  157. function buildGltfOpacityNode( alphaNode, alphaModeNode ) {
  158. const alphaMode = getConstNumber( alphaModeNode );
  159. const roundedMode = alphaMode === null ? 2 : Math.round( alphaMode );
  160. const alpha = alphaNode ?? float( 1 );
  161. if ( roundedMode === 0 ) return float( 1 );
  162. if ( roundedMode === 1 ) return alpha;
  163. return alpha;
  164. }
  165. function applyStandardSurface( material, inputs, log, nodeName ) {
  166. let colorNode = null;
  167. if ( inputs.base && inputs.base_color ) colorNode = mul( inputs.base, inputs.base_color );
  168. else if ( inputs.base ) colorNode = inputs.base;
  169. else if ( inputs.base_color ) colorNode = inputs.base_color;
  170. if ( inputs.coat_color ) {
  171. colorNode = colorNode ? mul( colorNode, inputs.coat_color ) : colorNode;
  172. }
  173. const roughnessNode = inputs.specular_roughness;
  174. const opacityNode = hasNodeValue( inputs.opacity ) ? element( inputs.opacity, 0 ) : undefined;
  175. const transmissionNode = inputs.transmission;
  176. const transmissionColorNode = inputs.transmission_color;
  177. const transmissionEnabled = isEnabledWeightNode( transmissionNode );
  178. const sheenEnabled = isEnabledWeightNode( inputs.sheen );
  179. const clearcoatEnabled = isEnabledWeightNode( inputs.coat );
  180. let emissiveNode = inputs.emission;
  181. const emissionColorNode = inputs.emission_color;
  182. if ( hasNodeValue( emissionColorNode ) ) {
  183. emissiveNode = emissiveNode ? mul( emissiveNode, emissionColorNode ) : emissionColorNode;
  184. }
  185. const thinFilmThicknessNode = inputs.thin_film_thickness;
  186. const thinFilmIorNode = clamp( inputs.thin_film_IOR || float( 1.5 ), float( 1.0 ), float( 2.333 ) );
  187. const thinFilmEnabled = isEnabledWeightNode( thinFilmThicknessNode );
  188. const transmissionTintNode = hasNodeValue( transmissionColorNode ) ? transmissionColorNode : color( 1, 1, 1 );
  189. if ( transmissionEnabled ) {
  190. const baseForTransmissionMix = colorNode || color( 0.8, 0.8, 0.8 );
  191. // Suppress diffuse/base tint as transmission ramps up.
  192. colorNode = mix( baseForTransmissionMix, transmissionTintNode, transmissionNode );
  193. }
  194. material.colorNode = colorNode || color( 0.8, 0.8, 0.8 );
  195. if ( hasNodeValue( opacityNode ) && isEffectivelyOne( opacityNode ) === false ) {
  196. material.opacityNode = opacityNode;
  197. }
  198. material.roughnessNode = roughnessNode || float( 0.2 );
  199. if ( hasNodeValue( inputs.metalness ) && isEffectivelyZero( inputs.metalness ) === false ) {
  200. material.metalnessNode = inputs.metalness;
  201. }
  202. if ( hasNodeValue( inputs.specular ) && isEffectivelyOne( inputs.specular ) === false ) {
  203. material.specularIntensityNode = inputs.specular;
  204. }
  205. material.specularColorNode = inputs.specular_color || color( 1, 1, 1 );
  206. const iorNode = inputs.specular_IOR;
  207. if ( hasNodeValue( iorNode ) && isConstNear( iorNode, 1.5 ) === false ) {
  208. material.iorNode = iorNode;
  209. }
  210. setAnisotropy( material, inputs.specular_anisotropy, inputs.specular_rotation );
  211. if ( transmissionEnabled ) {
  212. material.transmissionNode = transmissionNode;
  213. if ( hasNodeValue( transmissionColorNode ) ) material.transmissionColorNode = transmissionColorNode;
  214. if ( hasNodeValue( inputs.transmission_depth ) && isEffectivelyZero( inputs.transmission_depth ) === false ) {
  215. material.thicknessNode = inputs.transmission_depth;
  216. } else {
  217. // Keep transmissive standard_surface materials volumetric when
  218. // transmission_depth is omitted or authored as zero.
  219. material.thickness = 1;
  220. }
  221. }
  222. if ( thinFilmEnabled ) {
  223. material.iridescenceThicknessNode = thinFilmThicknessNode;
  224. material.iridescenceIORNode = thinFilmIorNode;
  225. material.iridescenceNode = float( 1 );
  226. }
  227. const sheenColor = inputs.sheen_color || color( 1, 1, 1 );
  228. if ( sheenEnabled ) {
  229. const sheenRoughness = hasNodeValue( inputs.sheen_roughness ) ? inputs.sheen_roughness : float( 0.3 );
  230. material.sheenNode = mul( inputs.sheen, sheenColor );
  231. material.sheenRoughnessNode = sheenRoughness;
  232. }
  233. if ( clearcoatEnabled ) {
  234. material.clearcoatNode = inputs.coat;
  235. if ( hasNodeValue( inputs.coat_roughness ) ) {
  236. material.clearcoatRoughnessNode = inputs.coat_roughness;
  237. }
  238. }
  239. if ( clearcoatEnabled && hasNodeValue( inputs.coat_normal ) ) {
  240. material.clearcoatNormalNode = transformNormalToView( inputs.coat_normal );
  241. }
  242. if ( hasNodeValue( inputs.normal ) ) material.normalNode = transformNormalToView( inputs.normal );
  243. if ( hasNodeValue( emissiveNode ) ) material.emissiveNode = emissiveNode;
  244. setTransmissionFlags( material, transmissionNode, opacityNode );
  245. warnIgnoredInputs( inputs, mappedStandardSurfaceInputs, log, 'standard_surface', nodeName );
  246. }
  247. function applyGltfPbrSurface( material, inputs, log, nodeName ) {
  248. const alphaModeLiteral = getConstNumber( inputs.alpha_mode );
  249. const alphaMode = alphaModeLiteral === null ? 2 : Math.round( alphaModeLiteral );
  250. const isAlphaMaskMode = alphaMode === 1;
  251. const isAlphaBlendMode = alphaMode === 2;
  252. const opacityNode = buildGltfOpacityNode( inputs.alpha, inputs.alpha_mode );
  253. const alphaCutoffNode = inputs.alpha_cutoff ?? float( 0.5 );
  254. const hasAttenuationColorInput = Object.prototype.hasOwnProperty.call( inputs, 'attenuation_color' );
  255. const transmissionEnabled = isEnabledWeightNode( inputs.transmission );
  256. const clearcoatEnabled = isEnabledWeightNode( inputs.clearcoat );
  257. const sheenEnabled = hasNodeValue( inputs.sheen_color ) || isEnabledWeightNode( inputs.sheen_roughness );
  258. const iridescenceEnabled = isEnabledWeightNode( inputs.iridescence );
  259. material.colorNode = inputs.base_color || color( 1, 1, 1 );
  260. if ( hasNodeValue( inputs.occlusion ) ) material.aoNode = inputs.occlusion;
  261. material.roughnessNode = inputs.roughness || float( 1 );
  262. material.metalnessNode = inputs.metallic || float( 1 );
  263. if ( hasNodeValue( inputs.specular ) && isEffectivelyOne( inputs.specular ) === false ) {
  264. material.specularIntensityNode = inputs.specular;
  265. }
  266. material.specularColorNode = inputs.specular_color || color( 1, 1, 1 );
  267. if ( hasNodeValue( inputs.ior ) && isConstNear( inputs.ior, 1.5 ) === false ) {
  268. material.iorNode = inputs.ior;
  269. }
  270. if ( hasNodeValue( opacityNode ) && isEffectivelyOne( opacityNode ) === false ) {
  271. material.opacityNode = opacityNode;
  272. }
  273. if ( isAlphaMaskMode ) {
  274. material.alphaTestNode = alphaCutoffNode;
  275. const alphaCutoff = getConstNumber( alphaCutoffNode );
  276. if ( alphaCutoff !== null ) material.alphaTest = alphaCutoff;
  277. }
  278. if ( transmissionEnabled ) {
  279. material.transmissionNode = inputs.transmission;
  280. }
  281. if ( clearcoatEnabled ) {
  282. material.clearcoatNode = inputs.clearcoat;
  283. if ( hasNodeValue( inputs.clearcoat_roughness ) && isEffectivelyZero( inputs.clearcoat_roughness ) === false ) {
  284. material.clearcoatRoughnessNode = inputs.clearcoat_roughness;
  285. }
  286. }
  287. if ( sheenEnabled ) {
  288. const sheenColor = hasNodeValue( inputs.sheen_color ) ? inputs.sheen_color : color( 0, 0, 0 );
  289. const sheenRoughness = hasNodeValue( inputs.sheen_roughness ) ? inputs.sheen_roughness : float( 0 );
  290. material.sheenRoughnessNode = sheenRoughness;
  291. material.sheenNode = sheenColor;
  292. }
  293. if ( iridescenceEnabled ) {
  294. material.iridescenceNode = inputs.iridescence;
  295. if ( hasNodeValue( inputs.iridescence_ior ) && isConstNear( inputs.iridescence_ior, 1.3 ) === false ) {
  296. material.iridescenceIORNode = inputs.iridescence_ior;
  297. }
  298. if ( hasNodeValue( inputs.iridescence_thickness ) && isConstNear( inputs.iridescence_thickness, 100 ) === false ) {
  299. material.iridescenceThicknessNode = inputs.iridescence_thickness;
  300. }
  301. }
  302. material.attenuationDistanceNode = toAttenuationDistance( inputs.attenuation_distance, hasAttenuationColorInput );
  303. material.attenuationColorNode = inputs.attenuation_color || color( 1, 1, 1 );
  304. if ( hasNodeValue( inputs.thickness ) ) {
  305. if ( isEffectivelyZero( inputs.thickness ) === false ) {
  306. material.thicknessNode = inputs.thickness;
  307. }
  308. } else if ( transmissionEnabled ) {
  309. // Keep transmissive glTF materials volumetric even when thickness is omitted.
  310. material.thickness = 1;
  311. }
  312. if ( hasNodeValue( inputs.dispersion ) && isEffectivelyZero( inputs.dispersion ) === false ) {
  313. material.dispersionNode = inputs.dispersion;
  314. }
  315. const anisotropyStrength = inputs.anisotropy_strength;
  316. const anisotropyRotation = inputs.anisotropy_rotation;
  317. setAnisotropy( material, anisotropyStrength, anisotropyRotation );
  318. if ( hasNodeValue( inputs.normal ) ) material.normalNode = transformNormalToView( inputs.normal );
  319. if ( hasNodeValue( inputs.clearcoat_normal ) ) {
  320. material.clearcoatNormalNode = transformNormalToView( inputs.clearcoat_normal );
  321. }
  322. if ( hasNodeValue( inputs.emissive ) && hasNodeValue( inputs.emissive_strength ) )
  323. material.emissiveNode = mul( inputs.emissive, inputs.emissive_strength );
  324. else if ( hasNodeValue( inputs.emissive ) ) material.emissiveNode = inputs.emissive;
  325. setTransmissionFlags( material, inputs.transmission, opacityNode, isAlphaBlendMode );
  326. warnIgnoredInputs( inputs, mappedGltfPbrInputs, log, 'gltf_pbr', nodeName );
  327. }
  328. function applyOpenPbrSurface( material, inputs, log, nodeName ) {
  329. const baseWeight = inputs.base_weight || float( 1 );
  330. const baseColor = inputs.base_color || color( 0.8, 0.8, 0.8 );
  331. const coatEnabled = isEnabledWeightNode( inputs.coat_weight );
  332. const fuzzEnabled = isEnabledWeightNode( inputs.fuzz_weight );
  333. const transmissionEnabled = isEnabledWeightNode( inputs.transmission_weight );
  334. const thinFilmEnabled = isEnabledWeightNode( inputs.thin_film_weight );
  335. material.colorNode = mul( baseWeight, baseColor );
  336. if ( hasNodeValue( inputs.base_metalness ) && isEffectivelyZero( inputs.base_metalness ) === false ) {
  337. material.metalnessNode = inputs.base_metalness;
  338. }
  339. material.roughnessNode = inputs.specular_roughness || float( 0.3 );
  340. if ( hasNodeValue( inputs.specular_weight ) && isEffectivelyOne( inputs.specular_weight ) === false ) {
  341. material.specularIntensityNode = inputs.specular_weight;
  342. }
  343. material.specularColorNode = inputs.specular_color || color( 1, 1, 1 );
  344. const openPbrIorNode = inputs.specular_ior;
  345. if ( hasNodeValue( openPbrIorNode ) && isConstNear( openPbrIorNode, 1.5 ) === false ) {
  346. material.iorNode = openPbrIorNode;
  347. }
  348. setAnisotropy( material, inputs.specular_roughness_anisotropy, float( 0 ) );
  349. if ( coatEnabled ) {
  350. const coatWeightNode = inputs.coat_weight || float( 0 );
  351. if ( hasNodeValue( inputs.coat_ior ) ) {
  352. const coatIorNode = inputs.coat_ior;
  353. const coatIorMinusOne = coatIorNode.sub( float( 1 ) );
  354. const coatIorPlusOne = coatIorNode.add( float( 1 ) );
  355. const coatF0Node = coatIorMinusOne.div( coatIorPlusOne );
  356. const normalizedClearcoatNode = coatF0Node.mul( coatF0Node ).div( float( 0.04 ) );
  357. material.clearcoatNode = clamp( coatWeightNode.mul( normalizedClearcoatNode ), float( 0 ), float( 1 ) );
  358. } else {
  359. material.clearcoatNode = coatWeightNode;
  360. }
  361. if ( hasNodeValue( inputs.coat_roughness ) && isEffectivelyZero( inputs.coat_roughness ) === false ) {
  362. material.clearcoatRoughnessNode = inputs.coat_roughness;
  363. }
  364. if ( hasNodeValue( inputs.geometry_coat_normal ) ) {
  365. material.clearcoatNormalNode = transformNormalToView( inputs.geometry_coat_normal );
  366. }
  367. }
  368. const fuzzWeight = inputs.fuzz_weight || float( 0 );
  369. const fuzzColor = inputs.fuzz_color || color( 1, 1, 1 );
  370. if ( fuzzEnabled ) {
  371. material.sheenNode = mul( fuzzWeight, fuzzColor );
  372. if ( hasNodeValue( inputs.fuzz_roughness ) ) {
  373. material.sheenRoughnessNode = pow( inputs.fuzz_roughness, float( 1.5 ) );
  374. }
  375. }
  376. if ( transmissionEnabled ) {
  377. material.transmissionNode = inputs.transmission_weight;
  378. if ( hasNodeValue( inputs.transmission_color ) ) material.attenuationColorNode = inputs.transmission_color;
  379. }
  380. const transmissionDepthNode = inputs.transmission_depth;
  381. if ( transmissionEnabled && hasNodeValue( transmissionDepthNode ) && isEffectivelyZero( transmissionDepthNode ) === false ) {
  382. material.thicknessNode = hasNodeValue( inputs.geometry_thin_walled )
  383. ? inputs.geometry_thin_walled.select( float( 0 ), transmissionDepthNode )
  384. : transmissionDepthNode;
  385. material.attenuationDistanceNode = transmissionDepthNode;
  386. } else if ( transmissionEnabled ) {
  387. // Keep transmissive OpenPBR materials volumetric even when depth is omitted.
  388. material.thickness = 1;
  389. }
  390. const transmissionDispersionAbbe = inputs.transmission_dispersion_abbe_number || float( 20 );
  391. if ( transmissionEnabled && hasNodeValue( inputs.transmission_dispersion_scale ) && isEffectivelyZero( inputs.transmission_dispersion_scale ) === false ) {
  392. material.dispersionNode = inputs.transmission_dispersion_scale.mul( float( 20 ) ).div( transmissionDispersionAbbe );
  393. }
  394. if ( hasNodeValue( inputs.geometry_opacity ) && isEffectivelyOne( inputs.geometry_opacity ) === false ) {
  395. material.opacityNode = inputs.geometry_opacity;
  396. }
  397. if ( hasNodeValue( inputs.geometry_normal ) ) material.normalNode = transformNormalToView( inputs.geometry_normal );
  398. if ( thinFilmEnabled ) {
  399. material.iridescenceNode = inputs.thin_film_weight;
  400. if ( hasNodeValue( inputs.thin_film_thickness ) && isConstNear( inputs.thin_film_thickness, 0.5 ) === false ) {
  401. material.iridescenceThicknessNode = inputs.thin_film_thickness.mul( float( 1000 ) );
  402. }
  403. if ( hasNodeValue( inputs.thin_film_ior ) && isConstNear( inputs.thin_film_ior, 1.4 ) === false ) {
  404. material.iridescenceIORNode = inputs.thin_film_ior;
  405. }
  406. }
  407. const emissionColor = hasNodeValue( inputs.emission_color ) ? inputs.emission_color : color( 1, 1, 1 );
  408. const emissionLuminance = hasNodeValue( inputs.emission_luminance ) ? inputs.emission_luminance : float( 0 );
  409. if ( isEffectivelyZero( emissionLuminance ) === false ) {
  410. material.emissiveNode = mul( emissionColor, emissionLuminance );
  411. }
  412. if ( hasNodeValue( inputs.geometry_opacity ) && isEffectivelyOne( inputs.geometry_opacity ) === false ) material.transparent = true;
  413. if ( transmissionEnabled ) material.transparent = true;
  414. setTransmissionFlags( material, inputs.transmission_weight, inputs.geometry_opacity );
  415. warnIgnoredInputs( inputs, mappedOpenPbrInputs, log, 'open_pbr_surface', nodeName );
  416. }
  417. const MaterialXSurfaceMappings = {
  418. standard_surface: applyStandardSurface,
  419. gltf_pbr: applyGltfPbrSurface,
  420. open_pbr_surface: applyOpenPbrSurface,
  421. };
  422. const surfaceMapperRegistry = new Map( Object.entries( MaterialXSurfaceMappings ).map( ( [ category, apply ] ) => [
  423. category,
  424. { category, apply },
  425. ] ) );
  426. function getSurfaceMapper( category ) {
  427. return surfaceMapperRegistry.get( category );
  428. }
  429. function getSupportedSurfaceCategories() {
  430. return [ ...surfaceMapperRegistry.keys() ];
  431. }
  432. export {
  433. MaterialXSurfaceMappings,
  434. surfaceMapperRegistry,
  435. getSurfaceMapper,
  436. getSupportedSurfaceCategories,
  437. applyStandardSurface,
  438. applyGltfPbrSurface,
  439. applyOpenPbrSurface,
  440. mappedStandardSurfaceInputs,
  441. mappedGltfPbrInputs,
  442. mappedOpenPbrInputs,
  443. };
粤ICP备19079148号