Selaa lähdekoodia

GLTFLoader: Implement KHR_texture_transform.

Don McCurdy 7 vuotta sitten
vanhempi
commit
951ab07daa
2 muutettua tiedostoa jossa 91 lisäystä ja 26 poistoa
  1. 16 6
      docs/examples/loaders/GLTFLoader.html
  2. 75 20
      examples/js/loaders/GLTFLoader.js

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

@@ -32,8 +32,18 @@
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_lights_punctual (experimental)</li>
+			<li>KHR_texture_transform<sup>*</sup></li>
+			<li>MSFT_texture_dds</li>
 		</ul>
 
+		<p><i>
+			<sup>*</sup>UV transforms are supported, with several key limitations in comparison to the
+			glTF specification. A transform is applied to all textures using that UV set on the current
+			material, and no more than one transform may be used per material. Each 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>
 
 		<code>
@@ -85,30 +95,30 @@
 		providing a Promise replacement.</p>
 
 		<h2>Textures</h2>
-		
+
 		<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
 		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
 		in linear colorspace, always configure [page:WebGLRenderer] as follows when using glTF:</p>
-			
+
 		<code>
 		renderer.gammaOutput = true;
 		renderer.gammaFactor = 2.2;
 		</code>
-		
+
 		<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
 		[page:TextureLoader]) and applying them to a glTF model, colorspace and orientation must be given:</p>
-		
+
 		<code>
 		// If texture is used for color information, set colorspace.
 		texture.encoding = THREE.sRGBEncoding;
 
 		// UVs use the convention that (0, 0) corresponds to the upper left corner of a texture.
 		texture.flipY = false;
-		</code>		
-		
+		</code>
+
 		<h2>Custom extensions</h2>
 
 		<p>

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

@@ -181,7 +181,7 @@ THREE.GLTFLoader = ( function () {
 							break;
 
 						case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
-							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
+							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension( json );
 							break;
 
 						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
@@ -189,7 +189,11 @@ THREE.GLTFLoader = ( function () {
 							break;
 
 						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;
 
 						default:
@@ -282,6 +286,7 @@ THREE.GLTFLoader = ( function () {
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
+		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
 	};
 
@@ -409,7 +414,7 @@ THREE.GLTFLoader = ( function () {
 
 			if ( metallicRoughness.baseColorTexture !== undefined ) {
 
-				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture.index ) );
+				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
 
 			}
 
@@ -563,6 +568,49 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
+	/**
+	 * Texture Transform Extension
+	 *
+	 * Specification:
+	 */
+	function GLTFTextureTransformExtension( json ) {
+
+		this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;
+
+	}
+
+	GLTFTextureTransformExtension.prototype.extendTexture = function ( texture, mapDef ) {
+
+		var transform = mapDef.extensions !== undefined ? mapDef.extensions[ this.name ] : undefined;
+
+		if ( transform === undefined ) return texture;
+
+		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 );
+
+		}
+
+		texture.needsUpdate = true;
+
+		return texture;
+
+	};
+
 	/**
 	 * Specular-Glossiness Extension
 	 *
@@ -692,7 +740,7 @@ THREE.GLTFLoader = ( function () {
 
 				if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
 
-					pending.push( parser.assignTexture( params, 'map', pbrSpecularGlossiness.diffuseTexture.index ) );
+					pending.push( parser.assignTexture( params, 'map', pbrSpecularGlossiness.diffuseTexture ) );
 
 				}
 
@@ -708,9 +756,9 @@ THREE.GLTFLoader = ( function () {
 
 				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 +2194,23 @@ THREE.GLTFLoader = ( function () {
 	/**
 	 * Asynchronously assigns a texture to the given material parameters.
 	 * @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', textureIndex ).then( function ( texture ) {
+		return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
+
+			if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
+
+				texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, mapDef );
+
+			}
 
-			materialParams[ textureName ] = texture;
+			materialParams[ mapName ] = texture;
 
 		} );
 
@@ -2213,7 +2269,7 @@ THREE.GLTFLoader = ( function () {
 
 			if ( metallicRoughness.baseColorTexture !== undefined ) {
 
-				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture.index ) );
+				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
 
 			}
 
@@ -2222,9 +2278,8 @@ THREE.GLTFLoader = ( function () {
 
 			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 +2311,7 @@ THREE.GLTFLoader = ( function () {
 
 		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 );
 
@@ -2270,7 +2325,7 @@ THREE.GLTFLoader = ( function () {
 
 		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 ) {
 
@@ -2288,7 +2343,7 @@ THREE.GLTFLoader = ( function () {
 
 		if ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
 
-			pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture.index ) );
+			pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );
 
 		}