Browse Source

Merge pull request #13831 from donmccurdy/feat-gltfloader-texturetransform

GLTFLoader: Implement KHR_texture_transform extension.
Mr.doob 6 years ago
parent
commit
dab285d9c4
3 changed files with 112 additions and 26 deletions
  1. 18 6
      docs/examples/loaders/GLTFLoader.html
  2. 11 0
      docs/page.css
  3. 83 20
      examples/js/loaders/GLTFLoader.js

+ 18 - 6
docs/examples/loaders/GLTFLoader.html

@@ -32,8 +32,20 @@
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_lights_punctual (experimental)</li>
 			<li>KHR_lights_punctual (experimental)</li>
+			<li>KHR_texture_transform<sup>*</sup></li>
+			<li>MSFT_texture_dds</li>
 		</ul>
 		</ul>
 
 
+		<p><i>
+			<sup>*</sup>UV transforms are supported, with several key limitations. Transforms applied to
+			a texture using the first UV slot (all textures except aoMap and lightMap) must share the same
+			transform, or no transfor at all. The aoMap and lightMap textures cannot be transformed. No
+			more than one transform may be used per material. Each use of a texture with a unique
+			transform will result in an additional GPU texture upload. See
+			#[link:https://github.com/mrdoob/three.js/pull/13831 13831] and
+			#[link:https://github.com/mrdoob/three.js/issues/12788 12788].
+		</i></p>
+
 		<h2>Example</h2>
 		<h2>Example</h2>
 
 
 		<code>
 		<code>
@@ -85,30 +97,30 @@
 		providing a Promise replacement.</p>
 		providing a Promise replacement.</p>
 
 
 		<h2>Textures</h2>
 		<h2>Textures</h2>
-		
+
 		<p>Textures containing color information (.map, .emissiveMap, and .specularMap) always use sRGB colorspace in
 		<p>Textures containing color information (.map, .emissiveMap, and .specularMap) always use sRGB colorspace in
 		glTF, while vertex colors and material properties (.color, .emissive, .specular) use linear colorspace. In a
 		glTF, while vertex colors and material properties (.color, .emissive, .specular) use linear colorspace. In a
 		typical rendering workflow, textures are converted to linear colorspace by the renderer, lighting calculations
 		typical rendering workflow, textures are converted to linear colorspace by the renderer, lighting calculations
 		are made, then final output is converted back to sRGB and displayed on screen. Unless you need post-processing
 		are made, then final output is converted back to sRGB and displayed on screen. Unless you need post-processing
 		in linear colorspace, always configure [page:WebGLRenderer] as follows when using glTF:</p>
 		in linear colorspace, always configure [page:WebGLRenderer] as follows when using glTF:</p>
-			
+
 		<code>
 		<code>
 		renderer.gammaOutput = true;
 		renderer.gammaOutput = true;
 		renderer.gammaFactor = 2.2;
 		renderer.gammaFactor = 2.2;
 		</code>
 		</code>
-		
+
 		<p>GLTFLoader will automatically configure textures referenced from a .gltf or .glb file correctly, with the
 		<p>GLTFLoader will automatically configure textures referenced from a .gltf or .glb file correctly, with the
 		assumption that the renderer is set up as shown above. When loading textures externally (e.g., using
 		assumption that the renderer is set up as shown above. When loading textures externally (e.g., using
 		[page:TextureLoader]) and applying them to a glTF model, colorspace and orientation must be given:</p>
 		[page:TextureLoader]) and applying them to a glTF model, colorspace and orientation must be given:</p>
-		
+
 		<code>
 		<code>
 		// If texture is used for color information, set colorspace.
 		// If texture is used for color information, set colorspace.
 		texture.encoding = THREE.sRGBEncoding;
 		texture.encoding = THREE.sRGBEncoding;
 
 
 		// UVs use the convention that (0, 0) corresponds to the upper left corner of a texture.
 		// UVs use the convention that (0, 0) corresponds to the upper left corner of a texture.
 		texture.flipY = false;
 		texture.flipY = false;
-		</code>		
-		
+		</code>
+
 		<h2>Custom extensions</h2>
 		<h2>Custom extensions</h2>
 
 
 		<p>
 		<p>

+ 11 - 0
docs/page.css

@@ -130,3 +130,14 @@ span.param {
 a.param:hover {
 a.param:hover {
 	color: #777;
 	color: #777;
 }
 }
+
+sup, sub {
+	/* prevent superscript and subscript elements from affecting line-height */
+  vertical-align: baseline;
+  position: relative;
+  top: -0.4em;
+}
+
+sub {
+  top: 0.4em;
+}

+ 83 - 20
examples/js/loaders/GLTFLoader.js

@@ -181,7 +181,7 @@ THREE.GLTFLoader = ( function () {
 							break;
 							break;
 
 
 						case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
 						case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
-							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
+							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension( json );
 							break;
 							break;
 
 
 						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
 						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
@@ -189,7 +189,11 @@ THREE.GLTFLoader = ( function () {
 							break;
 							break;
 
 
 						case EXTENSIONS.MSFT_TEXTURE_DDS:
 						case EXTENSIONS.MSFT_TEXTURE_DDS:
-							extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension();
+							extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension( json );
+							break;
+
+						case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
+							extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] = new GLTFTextureTransformExtension( json );
 							break;
 							break;
 
 
 						default:
 						default:
@@ -282,6 +286,7 @@ THREE.GLTFLoader = ( function () {
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
+		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
 	};
 	};
 
 
@@ -409,7 +414,7 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( metallicRoughness.baseColorTexture !== undefined ) {
 			if ( metallicRoughness.baseColorTexture !== undefined ) {
 
 
-				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture.index ) );
+				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
 
 
 			}
 			}
 
 
@@ -563,6 +568,51 @@ THREE.GLTFLoader = ( function () {
 
 
 	};
 	};
 
 
+	/**
+	 * Texture Transform Extension
+	 *
+	 * Specification:
+	 */
+	function GLTFTextureTransformExtension( json ) {
+
+		this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;
+
+	}
+
+	GLTFTextureTransformExtension.prototype.extendTexture = function ( texture, transform ) {
+
+		texture = texture.clone();
+
+		if ( transform.offset !== undefined ) {
+
+			texture.offset.fromArray( transform.offset );
+
+		}
+
+		if ( transform.rotation !== undefined ) {
+
+			texture.rotation = transform.rotation;
+
+		}
+
+		if ( transform.scale !== undefined ) {
+
+			texture.repeat.fromArray( transform.scale );
+
+		}
+
+		if ( transform.texCoord !== undefined ) {
+
+			console.warn( 'THREE.GLTFLoader: Custom UV sets in "' + this.name + '" extension not yet supported.' );
+
+		}
+
+		texture.needsUpdate = true;
+
+		return texture;
+
+	};
+
 	/**
 	/**
 	 * Specular-Glossiness Extension
 	 * Specular-Glossiness Extension
 	 *
 	 *
@@ -692,7 +742,7 @@ THREE.GLTFLoader = ( function () {
 
 
 				if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
 				if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
 
 
-					pending.push( parser.assignTexture( params, 'map', pbrSpecularGlossiness.diffuseTexture.index ) );
+					pending.push( parser.assignTexture( params, 'map', pbrSpecularGlossiness.diffuseTexture ) );
 
 
 				}
 				}
 
 
@@ -708,9 +758,9 @@ THREE.GLTFLoader = ( function () {
 
 
 				if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
 				if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
 
 
-					var specGlossIndex = pbrSpecularGlossiness.specularGlossinessTexture.index;
-					pending.push( parser.assignTexture( params, 'glossinessMap', specGlossIndex ) );
-					pending.push( parser.assignTexture( params, 'specularMap', specGlossIndex ) );
+					var specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
+					pending.push( parser.assignTexture( params, 'glossinessMap', specGlossMapDef ) );
+					pending.push( parser.assignTexture( params, 'specularMap', specGlossMapDef ) );
 
 
 				}
 				}
 
 
@@ -2146,15 +2196,29 @@ THREE.GLTFLoader = ( function () {
 	/**
 	/**
 	 * Asynchronously assigns a texture to the given material parameters.
 	 * Asynchronously assigns a texture to the given material parameters.
 	 * @param {Object} materialParams
 	 * @param {Object} materialParams
-	 * @param {string} textureName
-	 * @param {number} textureIndex
-	 * @return {Promise<THREE.Texture>}
+	 * @param {string} mapName
+	 * @param {Object} mapDef
+	 * @return {Promise}
 	 */
 	 */
-	GLTFParser.prototype.assignTexture = function ( materialParams, textureName, textureIndex ) {
+	GLTFParser.prototype.assignTexture = function ( materialParams, mapName, mapDef ) {
+
+		var parser = this;
+
+		return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
+
+			if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
+
+				var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;
 
 
-		return this.getDependency( 'texture', textureIndex ).then( function ( texture ) {
+				if ( transform ) {
+
+					texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );
+
+				}
+
+			}
 
 
-			materialParams[ textureName ] = texture;
+			materialParams[ mapName ] = texture;
 
 
 		} );
 		} );
 
 
@@ -2213,7 +2277,7 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( metallicRoughness.baseColorTexture !== undefined ) {
 			if ( metallicRoughness.baseColorTexture !== undefined ) {
 
 
-				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture.index ) );
+				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
 
 
 			}
 			}
 
 
@@ -2222,9 +2286,8 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
 			if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
 
 
-				var textureIndex = metallicRoughness.metallicRoughnessTexture.index;
-				pending.push( parser.assignTexture( materialParams, 'metalnessMap', textureIndex ) );
-				pending.push( parser.assignTexture( materialParams, 'roughnessMap', textureIndex ) );
+				pending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );
+				pending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );
 
 
 			}
 			}
 
 
@@ -2256,7 +2319,7 @@ THREE.GLTFLoader = ( function () {
 
 
 		if ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 		if ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 
 
-			pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture.index ) );
+			pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );
 
 
 			materialParams.normalScale = new THREE.Vector2( 1, 1 );
 			materialParams.normalScale = new THREE.Vector2( 1, 1 );
 
 
@@ -2270,7 +2333,7 @@ THREE.GLTFLoader = ( function () {
 
 
 		if ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 		if ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 
 
-			pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture.index ) );
+			pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );
 
 
 			if ( materialDef.occlusionTexture.strength !== undefined ) {
 			if ( materialDef.occlusionTexture.strength !== undefined ) {
 
 
@@ -2288,7 +2351,7 @@ THREE.GLTFLoader = ( function () {
 
 
 		if ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 		if ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 
 
-			pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture.index ) );
+			pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );
 
 
 		}
 		}