From 2dd5ec8c4188dc6226c9a8493aa6a932ebf04273 Mon Sep 17 00:00:00 2001 From: mrdoob Date: Sat, 17 Jan 2026 01:33:11 -0800 Subject: [PATCH] GLTFLoader: Add getMaterialExtension helper. (#32748) Co-authored-by: Claude Opus 4.5 --- examples/jsm/loaders/GLTFLoader.js | 235 +++++++++-------------------- 1 file changed, 71 insertions(+), 164 deletions(-) diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index fdf43f7d47df0a..d0645d7a734308 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -607,6 +607,20 @@ function GLTFRegistry() { /********** EXTENSIONS ***********/ /*********************************/ +function getMaterialExtension( parser, materialIndex, extensionName ) { + + const materialDef = parser.json.materials[ materialIndex ]; + + if ( materialDef.extensions && materialDef.extensions[ extensionName ] ) { + + return materialDef.extensions[ extensionName ]; + + } + + return null; + +} + const EXTENSIONS = { KHR_BINARY_GLTF: 'KHR_binary_glTF', KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression', @@ -844,20 +858,13 @@ class GLTFMaterialsEmissiveStrengthExtension { extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + if ( extension === null ) return Promise.resolve(); - return Promise.resolve(); + if ( extension.emissiveStrength !== undefined ) { - } - - const emissiveStrength = materialDef.extensions[ this.name ].emissiveStrength; - - if ( emissiveStrength !== undefined ) { - - materialParams.emissiveIntensity = emissiveStrength; + materialParams.emissiveIntensity = extension.emissiveStrength; } @@ -885,30 +892,20 @@ class GLTFMaterialsClearcoatExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return Promise.resolve(); - - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - if ( extension.clearcoatFactor !== undefined ) { materialParams.clearcoat = extension.clearcoatFactor; @@ -917,7 +914,7 @@ class GLTFMaterialsClearcoatExtension { if ( extension.clearcoatTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) ); } @@ -929,13 +926,13 @@ class GLTFMaterialsClearcoatExtension { if ( extension.clearcoatRoughnessTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) ); } if ( extension.clearcoatNormalTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) ); if ( extension.clearcoatNormalTexture.scale !== undefined ) { @@ -971,27 +968,17 @@ class GLTFMaterialsDispersionExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { - - return Promise.resolve(); + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - } - - const extension = materialDef.extensions[ this.name ]; + if ( extension === null ) return Promise.resolve(); materialParams.dispersion = extension.dispersion !== undefined ? extension.dispersion : 0; @@ -1019,30 +1006,20 @@ class GLTFMaterialsIridescenceExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return Promise.resolve(); - - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - if ( extension.iridescenceFactor !== undefined ) { materialParams.iridescence = extension.iridescenceFactor; @@ -1051,7 +1028,7 @@ class GLTFMaterialsIridescenceExtension { if ( extension.iridescenceTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) ); } @@ -1081,7 +1058,7 @@ class GLTFMaterialsIridescenceExtension { if ( extension.iridescenceThicknessTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) ); } @@ -1109,25 +1086,17 @@ class GLTFMaterialsSheenExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return Promise.resolve(); - - } + if ( extension === null ) return Promise.resolve(); const pending = []; @@ -1135,8 +1104,6 @@ class GLTFMaterialsSheenExtension { materialParams.sheenRoughness = 0; materialParams.sheen = 1; - const extension = materialDef.extensions[ this.name ]; - if ( extension.sheenColorFactor !== undefined ) { const colorFactor = extension.sheenColorFactor; @@ -1152,13 +1119,13 @@ class GLTFMaterialsSheenExtension { if ( extension.sheenColorTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, SRGBColorSpace ) ); + pending.push( this.parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, SRGBColorSpace ) ); } if ( extension.sheenRoughnessTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) ); } @@ -1187,30 +1154,20 @@ class GLTFMaterialsTransmissionExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { - - return Promise.resolve(); + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - if ( extension.transmissionFactor !== undefined ) { materialParams.transmission = extension.transmissionFactor; @@ -1219,7 +1176,7 @@ class GLTFMaterialsTransmissionExtension { if ( extension.transmissionTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) ); } @@ -1247,35 +1204,25 @@ class GLTFMaterialsVolumeExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return Promise.resolve(); - - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - materialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0; if ( extension.thicknessTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) ); } @@ -1308,27 +1255,17 @@ class GLTFMaterialsIorExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { - - return Promise.resolve(); - - } + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - const extension = materialDef.extensions[ this.name ]; + if ( extension === null ) return Promise.resolve(); materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5; @@ -1356,35 +1293,25 @@ class GLTFMaterialsSpecularExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { - - return Promise.resolve(); + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - materialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0; if ( extension.specularTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) ); } @@ -1393,7 +1320,7 @@ class GLTFMaterialsSpecularExtension { if ( extension.specularColorTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, SRGBColorSpace ) ); + pending.push( this.parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, SRGBColorSpace ) ); } @@ -1422,35 +1349,25 @@ class GLTFMaterialsBumpExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return Promise.resolve(); - - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - materialParams.bumpScale = extension.bumpFactor !== undefined ? extension.bumpFactor : 1.0; if ( extension.bumpTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) ); } @@ -1478,30 +1395,20 @@ class GLTFMaterialsAnisotropyExtension { getMaterialType( materialIndex ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return MeshPhysicalMaterial; + return extension !== null ? MeshPhysicalMaterial : null; } extendMaterialParams( materialIndex, materialParams ) { - const parser = this.parser; - const materialDef = parser.json.materials[ materialIndex ]; - - if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + const extension = getMaterialExtension( this.parser, materialIndex, this.name ); - return Promise.resolve(); - - } + if ( extension === null ) return Promise.resolve(); const pending = []; - const extension = materialDef.extensions[ this.name ]; - if ( extension.anisotropyStrength !== undefined ) { materialParams.anisotropy = extension.anisotropyStrength; @@ -1516,7 +1423,7 @@ class GLTFMaterialsAnisotropyExtension { if ( extension.anisotropyTexture !== undefined ) { - pending.push( parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) ); + pending.push( this.parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) ); }