diff --git a/examples/jsm/exporters/GLTFExporter.js b/examples/jsm/exporters/GLTFExporter.js index 45bb14f804950e..5d6ac77e80a4c2 100644 --- a/examples/jsm/exporters/GLTFExporter.js +++ b/examples/jsm/exporters/GLTFExporter.js @@ -135,6 +135,12 @@ class GLTFExporter { } ); + this.register( function ( writer ) { + + return new GLTFMaterialsBumpExtension( writer ); + + } ); + this.register( function ( writer ) { return new GLTFMeshGpuInstancing( writer ); @@ -2971,6 +2977,54 @@ class GLTFMaterialsEmissiveStrengthExtension { } + +/** + * Materials bump Extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/EXT_materials_bump + */ +class GLTFMaterialsBumpExtension { + + constructor( writer ) { + + this.writer = writer; + this.name = 'EXT_materials_bump'; + + } + + writeMaterial( material, materialDef ) { + + if ( ! material.isMeshStandardMaterial || ( + material.bumpScale === 1 && + ! material.bumpMap ) ) return; + + const writer = this.writer; + const extensionsUsed = writer.extensionsUsed; + + const extensionDef = {}; + + if ( material.bumpMap ) { + + const bumpMapDef = { + index: writer.processTexture( material.bumpMap ), + texCoord: material.bumpMap.channel + }; + writer.applyTextureTransform( bumpMapDef, material.bumpMap ); + extensionDef.bumpTexture = bumpMapDef; + + } + + extensionDef.bumpFactor = material.bumpScale; + + materialDef.extensions = materialDef.extensions || {}; + materialDef.extensions[ this.name ] = extensionDef; + + extensionsUsed[ this.name ] = true; + + } + +} + /** * GPU Instancing Extension * diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index 3660eeca50cfcd..1cc15ac3588eb5 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -151,6 +151,12 @@ class GLTFLoader extends Loader { } ); + this.register( function ( parser ) { + + return new GLTFMaterialsBumpExtension( parser ); + + } ); + this.register( function ( parser ) { return new GLTFLightsExtension( parser ); @@ -497,6 +503,7 @@ const EXTENSIONS = { KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', KHR_MATERIALS_EMISSIVE_STRENGTH: 'KHR_materials_emissive_strength', + EXT_MATERIALS_BUMP: 'EXT_materials_bump', EXT_TEXTURE_WEBP: 'EXT_texture_webp', EXT_TEXTURE_AVIF: 'EXT_texture_avif', EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression', @@ -1207,6 +1214,61 @@ class GLTFMaterialsSpecularExtension { } + +/** + * Materials bump Extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/EXT_materials_bump + */ +class GLTFMaterialsBumpExtension { + + constructor( parser ) { + + this.parser = parser; + this.name = EXTENSIONS.EXT_MATERIALS_BUMP; + + } + + getMaterialType( materialIndex ) { + + const parser = this.parser; + const materialDef = parser.json.materials[ materialIndex ]; + + if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null; + + return MeshPhysicalMaterial; + + } + + extendMaterialParams( materialIndex, materialParams ) { + + const parser = this.parser; + const materialDef = parser.json.materials[ materialIndex ]; + + if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) { + + 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 ) ); + + } + + return Promise.all( pending ); + + } + +} + /** * Materials anisotropy Extension * diff --git a/examples/misc_exporter_gltf.html b/examples/misc_exporter_gltf.html index be7d9c68ee055e..d44483e14b817f 100644 --- a/examples/misc_exporter_gltf.html +++ b/examples/misc_exporter_gltf.html @@ -236,9 +236,10 @@ color: 0xffff00, metalness: 0.5, roughness: 1.0, - flatShading: true + flatShading: true, } ); material.map = gradientTexture; + material.bumpMap = mapGrid; sphere = new THREE.Mesh( new THREE.SphereGeometry( 70, 10, 10 ), material ); sphere.position.set( 0, 0, 0 ); sphere.name = 'Sphere';