Browse Source

Updated examples builds.

Mr.doob 3 years ago
parent
commit
4bbcaacc4f
40 changed files with 1439 additions and 320 deletions
  1. 1 16
      examples/js/animation/MMDPhysics.js
  2. 0 7
      examples/js/controls/FirstPersonControls.js
  3. 0 8
      examples/js/controls/FlyControls.js
  4. 0 2
      examples/js/controls/OrbitControls.js
  5. 0 8
      examples/js/controls/PointerLockControls.js
  6. 0 2
      examples/js/controls/TrackballControls.js
  7. 9 15
      examples/js/controls/TransformControls.js
  8. 1 21
      examples/js/effects/OutlineEffect.js
  9. 4 13
      examples/js/exporters/ColladaExporter.js
  10. 0 12
      examples/js/exporters/DRACOExporter.js
  11. 0 13
      examples/js/exporters/GLTFExporter.js
  12. 2 23
      examples/js/exporters/OBJExporter.js
  13. 12 24
      examples/js/exporters/PLYExporter.js
  14. 0 7
      examples/js/exporters/STLExporter.js
  15. 1 1
      examples/js/geometries/ConvexGeometry.js
  16. 1 8
      examples/js/geometries/ParametricGeometry.js
  17. 2 0
      examples/js/interactive/SelectionHelper.js
  18. 1 0
      examples/js/loaders/ColladaLoader.js
  19. 2 25
      examples/js/loaders/DRACOLoader.js
  20. 7 0
      examples/js/loaders/FBXLoader.js
  21. 2 15
      examples/js/loaders/FontLoader.js
  22. 25 8
      examples/js/loaders/GLTFLoader.js
  23. 0 11
      examples/js/loaders/HDRCubeTextureLoader.js
  24. 666 0
      examples/js/loaders/KTX2Loader.js
  25. 43 5
      examples/js/loaders/PCDLoader.js
  26. 2 2
      examples/js/loaders/SVGLoader.js
  27. 31 0
      examples/js/loaders/TIFFLoader.js
  28. 385 0
      examples/js/materials/MeshGouraudMaterial.js
  29. 0 23
      examples/js/math/ColorConverter.js
  30. 23 0
      examples/js/misc/GPUComputationRenderer.js
  31. 193 0
      examples/js/objects/GroundProjectedEnv.js
  32. 9 2
      examples/js/objects/Reflector.js
  33. 3 4
      examples/js/objects/ReflectorForSSRPass.js
  34. 10 4
      examples/js/objects/Refractor.js
  35. 1 1
      examples/js/postprocessing/OutlinePass.js
  36. 0 21
      examples/js/renderers/Projector.js
  37. 1 1
      examples/js/shaders/LuminosityShader.js
  38. 1 1
      examples/js/shaders/ToneMapShader.js
  39. 1 1
      examples/js/utils/PackedPhongMaterial.js
  40. 0 16
      examples/js/utils/SceneUtils.js

+ 1 - 16
examples/js/animation/MMDPhysics.js

@@ -1213,7 +1213,7 @@
 						return new THREE.BoxGeometry( param.width * 2, param.height * 2, param.depth * 2, 8, 8, 8 );
 
 					case 2:
-						return new createCapsuleGeometry( param.width, param.height, 16, 8 );
+						return new THREE.CapsuleGeometry( param.width, param.height, 8, 16 );
 
 					default:
 						return null;
@@ -1222,21 +1222,6 @@
 
 			}
 
-			function createCapsuleGeometry( radius, cylinderHeight, segmentsRadius, segmentsHeight ) {
-
-				var geometry = new THREE.CylinderGeometry( radius, radius, cylinderHeight, segmentsRadius, segmentsHeight, true );
-				var upperSphere = new THREE.Mesh( new THREE.SphereGeometry( radius, segmentsRadius, segmentsHeight, 0, Math.PI * 2, 0, Math.PI / 2 ) );
-				var lowerSphere = new THREE.Mesh( new THREE.SphereGeometry( radius, segmentsRadius, segmentsHeight, 0, Math.PI * 2, Math.PI / 2, Math.PI / 2 ) );
-				upperSphere.position.set( 0, cylinderHeight / 2, 0 );
-				lowerSphere.position.set( 0, - cylinderHeight / 2, 0 );
-				upperSphere.updateMatrix();
-				lowerSphere.updateMatrix();
-				geometry.merge( upperSphere.geometry, upperSphere.matrix );
-				geometry.merge( lowerSphere.geometry, lowerSphere.matrix );
-				return geometry;
-
-			}
-
 			for ( var i = 0, il = bodies.length; i < il; i ++ ) {
 
 				var param = bodies[ i ].params;

+ 0 - 7
examples/js/controls/FirstPersonControls.js

@@ -10,13 +10,6 @@
 
 		constructor( object, domElement ) {
 
-			if ( domElement === undefined ) {
-
-				console.warn( 'THREE.FirstPersonControls: The second parameter "domElement" is now mandatory.' );
-				domElement = document;
-
-			}
-
 			this.object = object;
 			this.domElement = domElement; // API
 

+ 0 - 8
examples/js/controls/FlyControls.js

@@ -9,14 +9,6 @@
 		constructor( object, domElement ) {
 
 			super();
-
-			if ( domElement === undefined ) {
-
-				console.warn( 'THREE.FlyControls: The second parameter "domElement" is now mandatory.' );
-				domElement = document;
-
-			}
-
 			this.object = object;
 			this.domElement = domElement; // API
 

+ 0 - 2
examples/js/controls/OrbitControls.js

@@ -21,8 +21,6 @@
 		constructor( object, domElement ) {
 
 			super();
-			if ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter "domElement" is now mandatory.' );
-			if ( domElement === document ) console.error( 'THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
 			this.object = object;
 			this.domElement = domElement;
 			this.domElement.style.touchAction = 'none'; // disable touch scroll

+ 0 - 8
examples/js/controls/PointerLockControls.js

@@ -21,14 +21,6 @@
 		constructor( camera, domElement ) {
 
 			super();
-
-			if ( domElement === undefined ) {
-
-				console.warn( 'THREE.PointerLockControls: The second parameter "domElement" is now mandatory.' );
-				domElement = document.body;
-
-			}
-
 			this.domElement = domElement;
 			this.isLocked = false; // Set to constrain the pitch of the camera
 			// Range is 0 to Math.PI radians

+ 0 - 2
examples/js/controls/TrackballControls.js

@@ -15,8 +15,6 @@
 		constructor( object, domElement ) {
 
 			super();
-			if ( domElement === undefined ) console.warn( 'THREE.TrackballControls: The second parameter "domElement" is now mandatory.' );
-			if ( domElement === document ) console.error( 'THREE.TrackballControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.' );
 			const scope = this;
 			const STATE = {
 				NONE: - 1,

+ 9 - 15
examples/js/controls/TransformControls.js

@@ -531,7 +531,7 @@
 			this.visible = true;
 			return this;
 
-		} // Detatch from object
+		} // Detach from object
 
 
 		detach() {
@@ -609,12 +609,6 @@
 
 		}
 
-		update() {
-
-			console.warn( 'THREE.TransformControls: update function has no more functionality and therefore has been deprecated.' );
-
-		}
-
 	} // mouse / touch event handlers
 
 
@@ -1119,12 +1113,12 @@
 				if ( this.mode === 'translate' || this.mode === 'scale' ) {
 
 					// Hide translate and scale axis facing the camera
-					const AXIS_HIDE_TRESHOLD = 0.99;
-					const PLANE_HIDE_TRESHOLD = 0.2;
+					const AXIS_HIDE_THRESHOLD = 0.99;
+					const PLANE_HIDE_THRESHOLD = 0.2;
 
 					if ( handle.name === 'X' ) {
 
-						if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
+						if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
 
 							handle.scale.set( 1e-10, 1e-10, 1e-10 );
 							handle.visible = false;
@@ -1135,7 +1129,7 @@
 
 					if ( handle.name === 'Y' ) {
 
-						if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
+						if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
 
 							handle.scale.set( 1e-10, 1e-10, 1e-10 );
 							handle.visible = false;
@@ -1146,7 +1140,7 @@
 
 					if ( handle.name === 'Z' ) {
 
-						if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_TRESHOLD ) {
+						if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) > AXIS_HIDE_THRESHOLD ) {
 
 							handle.scale.set( 1e-10, 1e-10, 1e-10 );
 							handle.visible = false;
@@ -1157,7 +1151,7 @@
 
 					if ( handle.name === 'XY' ) {
 
-						if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
+						if ( Math.abs( _alignVector.copy( _unitZ ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
 
 							handle.scale.set( 1e-10, 1e-10, 1e-10 );
 							handle.visible = false;
@@ -1168,7 +1162,7 @@
 
 					if ( handle.name === 'YZ' ) {
 
-						if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
+						if ( Math.abs( _alignVector.copy( _unitX ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
 
 							handle.scale.set( 1e-10, 1e-10, 1e-10 );
 							handle.visible = false;
@@ -1179,7 +1173,7 @@
 
 					if ( handle.name === 'XZ' ) {
 
-						if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_TRESHOLD ) {
+						if ( Math.abs( _alignVector.copy( _unitY ).applyQuaternion( quaternion ).dot( this.eye ) ) < PLANE_HIDE_THRESHOLD ) {
 
 							handle.scale.set( 1e-10, 1e-10, 1e-10 );
 							handle.visible = false;

+ 1 - 21
examples/js/effects/OutlineEffect.js

@@ -49,7 +49,7 @@
  * // How to set outline parameters for each material
  * material.userData.outlineParameters = {
  * 	thickness: 0.01,
- * 	color: [ 0, 0, 0 ]
+ * 	color: [ 0, 0, 0 ],
  * 	alpha: 0.8,
  * 	visible: true,
  * 	keepAlive: true
@@ -336,26 +336,6 @@
 
 			this.render = function ( scene, camera ) {
 
-				let renderTarget;
-				let forceClear = false;
-
-				if ( arguments[ 2 ] !== undefined ) {
-
-					console.warn( 'THREE.OutlineEffect.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
-					renderTarget = arguments[ 2 ];
-
-				}
-
-				if ( arguments[ 3 ] !== undefined ) {
-
-					console.warn( 'THREE.OutlineEffect.render(): the forceClear argument has been removed. Use .clear() instead.' );
-					forceClear = arguments[ 3 ];
-
-				}
-
-				if ( renderTarget !== undefined ) renderer.setRenderTarget( renderTarget );
-				if ( forceClear ) renderer.clear();
-
 				if ( this.enabled === false ) {
 
 					renderer.render( scene, camera );

+ 4 - 13
examples/js/exporters/ColladaExporter.js

@@ -208,21 +208,12 @@
 			// Returns the mesh id
 
 
-			function processGeometry( g ) {
+			function processGeometry( bufferGeometry ) {
 
-				let info = geometryInfo.get( g );
+				let info = geometryInfo.get( bufferGeometry );
 
 				if ( ! info ) {
 
-					// convert the geometry to bufferGeometry if it isn't already
-					const bufferGeometry = g;
-
-					if ( bufferGeometry.isBufferGeometry !== true ) {
-
-						throw new Error( 'THREE.ColladaExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-					}
-
 					const meshid = `Mesh${libraryGeometries.length + 1}`;
 					const indexCount = bufferGeometry.index ? bufferGeometry.index.count * bufferGeometry.index.itemSize : bufferGeometry.attributes.position.count;
 					const groups = bufferGeometry.groups != null && bufferGeometry.groups.length !== 0 ? bufferGeometry.groups : [ {
@@ -230,7 +221,7 @@
 						count: indexCount,
 						materialIndex: 0
 					} ];
-					const gname = g.name ? ` name="${g.name}"` : '';
+					const gname = bufferGeometry.name ? ` name="${bufferGeometry.name}"` : '';
 					let gnode = `<geometry id="${meshid}"${gname}><mesh>`; // define the geometry node and the vertices for the geometry
 
 					const posName = `${meshid}-position`;
@@ -312,7 +303,7 @@
 						meshid: meshid,
 						bufferGeometry: bufferGeometry
 					};
-					geometryInfo.set( g, info );
+					geometryInfo.set( bufferGeometry, info );
 
 				}
 

+ 0 - 12
examples/js/exporters/DRACOExporter.js

@@ -27,12 +27,6 @@
 			exportColor: false
 		} ) {
 
-			if ( object.isBufferGeometry === true ) {
-
-				throw new Error( 'DRACOExporter: The first parameter of parse() is now an instance of Mesh or Points.' );
-
-			}
-
 			if ( DracoEncoderModule === undefined ) {
 
 				throw new Error( 'THREE.DRACOExporter: required the draco_encoder to work.' );
@@ -45,12 +39,6 @@
 			let builder;
 			let dracoObject;
 
-			if ( geometry.isBufferGeometry !== true ) {
-
-				throw new Error( 'THREE.DRACOExporter.parse(geometry, options): geometry is not a THREE.BufferGeometry instance.' );
-
-			}
-
 			if ( object.isMesh === true ) {
 
 				builder = new dracoEncoder.MeshBuilder();

+ 0 - 13
examples/js/exporters/GLTFExporter.js

@@ -77,13 +77,6 @@
 
 		parse( input, onDone, onError, options ) {
 
-			if ( typeof onError === 'object' ) {
-
-				console.warn( 'THREE.GLTFExporter: parse() expects options as the fourth argument now.' );
-				options = onError;
-
-			}
-
 			const writer = new GLTFWriter();
 			const plugins = [];
 
@@ -1360,12 +1353,6 @@
 
 			}
 
-			if ( geometry.isBufferGeometry !== true ) {
-
-				throw new Error( 'THREE.GLTFExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-			}
-
 			const meshDef = {};
 			const attributes = {};
 			const primitives = [];

+ 2 - 23
examples/js/exporters/OBJExporter.js

@@ -20,14 +20,7 @@
 				let nbNormals = 0;
 				let nbVertexUvs = 0;
 				const geometry = mesh.geometry;
-				const normalMatrixWorld = new THREE.Matrix3();
-
-				if ( geometry.isBufferGeometry !== true ) {
-
-					throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-				} // shortcuts
-
+				const normalMatrixWorld = new THREE.Matrix3(); // shortcuts
 
 				const vertices = geometry.getAttribute( 'position' );
 				const normals = geometry.getAttribute( 'normal' );
@@ -133,14 +126,7 @@
 
 				let nbVertex = 0;
 				const geometry = line.geometry;
-				const type = line.type;
-
-				if ( geometry.isBufferGeometry !== true ) {
-
-					throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-				} // shortcuts
-
+				const type = line.type; // shortcuts
 
 				const vertices = geometry.getAttribute( 'position' ); // name of the line object
 
@@ -193,13 +179,6 @@
 
 				let nbVertex = 0;
 				const geometry = points.geometry;
-
-				if ( geometry.isBufferGeometry !== true ) {
-
-					throw new Error( 'THREE.OBJExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-				}
-
 				const vertices = geometry.getAttribute( 'position' );
 				const colors = geometry.getAttribute( 'color' );
 				output += 'o ' + points.name + '\n';

+ 12 - 24
examples/js/exporters/PLYExporter.js

@@ -17,30 +17,16 @@
 
 		parse( object, onDone, options ) {
 
-			if ( onDone && typeof onDone === 'object' ) {
-
-				console.warn( 'THREE.PLYExporter: The options parameter is now the third argument to the "parse" function. See the documentation for the new API.' );
-				options = onDone;
-				onDone = undefined;
-
-			} // Iterate over the valid meshes in the object
-
-
+			// Iterate over the valid meshes in the object
 			function traverseMeshes( cb ) {
 
 				object.traverse( function ( child ) {
 
-					if ( child.isMesh === true ) {
+					if ( child.isMesh === true || child.isPoints ) {
 
 						const mesh = child;
 						const geometry = mesh.geometry;
 
-						if ( geometry.isBufferGeometry !== true ) {
-
-							throw new Error( 'THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-						}
-
 						if ( geometry.hasAttribute( 'position' ) === true ) {
 
 							cb( mesh, geometry );
@@ -62,6 +48,7 @@
 			};
 			options = Object.assign( defaultOptions, options );
 			const excludeAttributes = options.excludeAttributes;
+			let includeIndices = true;
 			let includeNormals = false;
 			let includeColors = false;
 			let includeUVs = false; // count the vertices, check which properties are used,
@@ -75,13 +62,6 @@
 
 					const mesh = child;
 					const geometry = mesh.geometry;
-
-					if ( geometry.isBufferGeometry !== true ) {
-
-						throw new Error( 'THREE.PLYExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-					}
-
 					const vertices = geometry.getAttribute( 'position' );
 					const normals = geometry.getAttribute( 'normal' );
 					const uvs = geometry.getAttribute( 'uv' );
@@ -100,11 +80,19 @@
 					if ( uvs !== undefined ) includeUVs = true;
 					if ( colors !== undefined ) includeColors = true;
 
+				} else if ( child.isPoints ) {
+
+					const mesh = child;
+					const geometry = mesh.geometry;
+					const vertices = geometry.getAttribute( 'position' );
+					vertexCount += vertices.count;
+					includeIndices = false;
+
 				}
 
 			} );
 			const tempColor = new THREE.Color();
-			const includeIndices = excludeAttributes.indexOf( 'index' ) === - 1;
+			includeIndices = includeIndices && excludeAttributes.indexOf( 'index' ) === - 1;
 			includeNormals = includeNormals && excludeAttributes.indexOf( 'normal' ) === - 1;
 			includeColors = includeColors && excludeAttributes.indexOf( 'color' ) === - 1;
 			includeUVs = includeUVs && excludeAttributes.indexOf( 'uv' ) === - 1;

+ 0 - 7
examples/js/exporters/STLExporter.js

@@ -22,13 +22,6 @@
 				if ( object.isMesh ) {
 
 					const geometry = object.geometry;
-
-					if ( geometry.isBufferGeometry !== true ) {
-
-						throw new Error( 'THREE.STLExporter: Geometry is not of type THREE.BufferGeometry.' );
-
-					}
-
 					const index = geometry.index;
 					const positionAttribute = geometry.getAttribute( 'position' );
 					triangles += index !== null ? index.count / 3 : positionAttribute.count / 3;

+ 1 - 1
examples/js/geometries/ConvexGeometry.js

@@ -11,7 +11,7 @@
 
 			if ( THREE.ConvexHull === undefined ) {
 
-				console.error( 'THREE.ConvexBufferGeometry: ConvexBufferGeometry relies on THREE.ConvexHull' );
+				console.error( 'THREE.ConvexGeometry: ConvexGeometry relies on THREE.ConvexHull' );
 
 			}
 

+ 1 - 8
examples/js/geometries/ParametricGeometry.js

@@ -26,14 +26,7 @@
 			const p0 = new THREE.Vector3(),
 				p1 = new THREE.Vector3();
 			const pu = new THREE.Vector3(),
-				pv = new THREE.Vector3();
-
-			if ( func.length < 3 ) {
-
-				console.error( 'THREE.ParametricGeometry: Function must now modify a THREE.Vector3 as third parameter.' );
-
-			} // generate vertices, normals and uvs
-
+				pv = new THREE.Vector3(); // generate vertices, normals and uvs
 
 			const sliceCount = slices + 1;
 

+ 2 - 0
examples/js/interactive/SelectionHelper.js

@@ -53,6 +53,7 @@
 
 		onSelectStart( event ) {
 
+			this.element.style.display = 'none';
 			this.renderer.domElement.parentElement.appendChild( this.element );
 			this.element.style.left = event.clientX + 'px';
 			this.element.style.top = event.clientY + 'px';
@@ -65,6 +66,7 @@
 
 		onSelectMove( event ) {
 
+			this.element.style.display = 'block';
 			this.pointBottomRight.x = Math.max( this.startPoint.x, event.clientX );
 			this.pointBottomRight.y = Math.max( this.startPoint.y, event.clientY );
 			this.pointTopLeft.x = Math.min( this.startPoint.x, event.clientX );

+ 1 - 0
examples/js/loaders/ColladaLoader.js

@@ -3793,6 +3793,7 @@
 
 			if ( asset.upAxis === 'Z_UP' ) {
 
+				console.warn( 'THREE.ColladaLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted, see #24289.' );
 				scene.quaternion.setFromEuler( new THREE.Euler( - Math.PI / 2, 0, 0 ) );
 
 			}

+ 2 - 25
examples/js/loaders/DRACOLoader.js

@@ -60,18 +60,11 @@
 			loader.setWithCredentials( this.withCredentials );
 			loader.load( url, buffer => {
 
-				const taskConfig = {
-					attributeIDs: this.defaultAttributeIDs,
-					attributeTypes: this.defaultAttributeTypes,
-					useUniqueIDs: false
-				};
-				this.decodeGeometry( buffer, taskConfig ).then( onLoad ).catch( onError );
+				this.decodeDracoFile( buffer, onLoad ).catch( onError );
 
 			}, onProgress, onError );
 
 		}
-		/** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */
-
 
 		decodeDracoFile( buffer, callback, attributeIDs, attributeTypes ) {
 
@@ -80,28 +73,12 @@
 				attributeTypes: attributeTypes || this.defaultAttributeTypes,
 				useUniqueIDs: !! attributeIDs
 			};
-			this.decodeGeometry( buffer, taskConfig ).then( callback );
+			return this.decodeGeometry( buffer, taskConfig ).then( callback );
 
 		}
 
 		decodeGeometry( buffer, taskConfig ) {
 
-			// TODO: For backward-compatibility, support 'attributeTypes' objects containing
-			// references (rather than names) to typed array constructors. These must be
-			// serialized before sending them to the worker.
-			for ( const attribute in taskConfig.attributeTypes ) {
-
-				const type = taskConfig.attributeTypes[ attribute ];
-
-				if ( type.BYTES_PER_ELEMENT !== undefined ) {
-
-					taskConfig.attributeTypes[ attribute ] = type.name;
-
-				}
-
-			} //
-
-
 			const taskKey = JSON.stringify( taskConfig ); // Check for an existing task using this buffer. A transferred buffer cannot be transferred
 			// again from this thread.
 

+ 7 - 0
examples/js/loaders/FBXLoader.js

@@ -1744,6 +1744,13 @@
 
 					materialIndex = getData( polygonVertexIndex, polygonIndex, vertexIndex, geoInfo.material )[ 0 ];
 
+					if ( materialIndex < 0 ) {
+
+						console.warn( 'THREE.FBXLoader: Invalid material index:', materialIndex );
+						materialIndex = 0;
+
+					}
+
 				}
 
 				if ( geoInfo.uv ) {

+ 2 - 15
examples/js/loaders/FontLoader.js

@@ -14,23 +14,10 @@
 			const loader = new THREE.FileLoader( this.manager );
 			loader.setPath( this.path );
 			loader.setRequestHeader( this.requestHeader );
-			loader.setWithCredentials( scope.withCredentials );
+			loader.setWithCredentials( this.withCredentials );
 			loader.load( url, function ( text ) {
 
-				let json;
-
-				try {
-
-					json = JSON.parse( text );
-
-				} catch ( e ) {
-
-					console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );
-					json = JSON.parse( text.substring( 65, text.length - 2 ) );
-
-				}
-
-				const font = scope.parse( json );
+				const font = scope.parse( JSON.parse( text ) );
 				if ( onLoad ) onLoad( font );
 
 			}, onProgress, onError );

+ 25 - 8
examples/js/loaders/GLTFLoader.js

@@ -1210,16 +1210,34 @@
 
 				}
 
-				return Promise.all( [ buffer, decoder.ready ] ).then( function ( res ) {
+				return buffer.then( function ( res ) {
 
 					const byteOffset = extensionDef.byteOffset || 0;
 					const byteLength = extensionDef.byteLength || 0;
 					const count = extensionDef.count;
 					const stride = extensionDef.byteStride;
-					const result = new ArrayBuffer( count * stride );
-					const source = new Uint8Array( res[ 0 ], byteOffset, byteLength );
-					decoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );
-					return result;
+					const source = new Uint8Array( res, byteOffset, byteLength );
+
+					if ( decoder.decodeGltfBufferAsync ) {
+
+						return decoder.decodeGltfBufferAsync( count, stride, source, extensionDef.mode, extensionDef.filter ).then( function ( res ) {
+
+							return res.buffer;
+
+						} );
+
+					} else {
+
+						// Support for MeshoptDecoder 0.18 or earlier, without decodeGltfBufferAsync
+						return decoder.ready.then( function () {
+
+							const result = new ArrayBuffer( count * stride );
+							decoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );
+							return result;
+
+						} );
+
+					}
 
 				} );
 
@@ -1352,7 +1370,7 @@
 
 					const accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
 					const componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
-					attributeTypeMap[ threeAttributeName ] = componentType;
+					attributeTypeMap[ threeAttributeName ] = componentType.name;
 					attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;
 
 				}
@@ -3451,8 +3469,7 @@
 				const channel = animationDef.channels[ i ];
 				const sampler = animationDef.samplers[ channel.sampler ];
 				const target = channel.target;
-				const name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated.
-
+				const name = target.node;
 				const input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;
 				const output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;
 				pendingNodes.push( this.getDependency( 'node', name ) );

+ 0 - 11
examples/js/loaders/HDRCubeTextureLoader.js

@@ -12,17 +12,6 @@
 
 		load( urls, onLoad, onProgress, onError ) {
 
-			if ( ! Array.isArray( urls ) ) {
-
-				console.warn( 'THREE.HDRCubeTextureLoader signature has changed. Use .setDataType() instead.' );
-				this.setDataType( urls );
-				urls = onLoad;
-				onLoad = onProgress;
-				onProgress = onError;
-				onError = arguments[ 4 ];
-
-			}
-
 			const texture = new THREE.CubeTexture();
 			texture.type = this.type;
 

+ 666 - 0
examples/js/loaders/KTX2Loader.js

@@ -0,0 +1,666 @@
+( function () {
+
+	/**
+ * THREE.Loader for KTX 2.0 GPU Texture containers.
+ *
+ * KTX 2.0 is a container format for various GPU texture formats. The loader
+ * supports Basis Universal GPU textures, which can be quickly transcoded to
+ * a wide variety of GPU texture compression formats, as well as some
+ * uncompressed THREE.DataTexture and THREE.Data3DTexture formats.
+ *
+ * References:
+ * - KTX: http://github.khronos.org/KTX-Specification/
+ * - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor
+ */
+
+	const _taskCache = new WeakMap();
+
+	let _activeLoaders = 0;
+
+	let _zstd;
+
+	class KTX2Loader extends THREE.Loader {
+
+		constructor( manager ) {
+
+			super( manager );
+			this.transcoderPath = '';
+			this.transcoderBinary = null;
+			this.transcoderPending = null;
+			this.workerPool = new THREE.WorkerPool();
+			this.workerSourceURL = '';
+			this.workerConfig = null;
+
+			if ( typeof MSC_TRANSCODER !== 'undefined' ) {
+
+				console.warn( 'THREE.KTX2Loader: Please update to latest "basis_transcoder".' + ' "msc_basis_transcoder" is no longer supported in three.js r125+.' );
+
+			}
+
+		}
+
+		setTranscoderPath( path ) {
+
+			this.transcoderPath = path;
+			return this;
+
+		}
+
+		setWorkerLimit( num ) {
+
+			this.workerPool.setWorkerLimit( num );
+			return this;
+
+		}
+
+		detectSupport( renderer ) {
+
+			this.workerConfig = {
+				astcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_astc' ),
+				etc1Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc1' ),
+				etc2Supported: renderer.extensions.has( 'WEBGL_compressed_texture_etc' ),
+				dxtSupported: renderer.extensions.has( 'WEBGL_compressed_texture_s3tc' ),
+				bptcSupported: renderer.extensions.has( 'EXT_texture_compression_bptc' ),
+				pvrtcSupported: renderer.extensions.has( 'WEBGL_compressed_texture_pvrtc' ) || renderer.extensions.has( 'WEBKIT_WEBGL_compressed_texture_pvrtc' )
+			};
+
+			if ( renderer.capabilities.isWebGL2 ) {
+
+				// https://github.com/mrdoob/three.js/pull/22928
+				this.workerConfig.etc1Supported = false;
+
+			}
+
+			return this;
+
+		}
+
+		init() {
+
+			if ( ! this.transcoderPending ) {
+
+				// Load transcoder wrapper.
+				const jsLoader = new THREE.FileLoader( this.manager );
+				jsLoader.setPath( this.transcoderPath );
+				jsLoader.setWithCredentials( this.withCredentials );
+				const jsContent = jsLoader.loadAsync( 'basis_transcoder.js' ); // Load transcoder WASM binary.
+
+				const binaryLoader = new THREE.FileLoader( this.manager );
+				binaryLoader.setPath( this.transcoderPath );
+				binaryLoader.setResponseType( 'arraybuffer' );
+				binaryLoader.setWithCredentials( this.withCredentials );
+				const binaryContent = binaryLoader.loadAsync( 'basis_transcoder.wasm' );
+				this.transcoderPending = Promise.all( [ jsContent, binaryContent ] ).then( ( [ jsContent, binaryContent ] ) => {
+
+					const fn = KTX2Loader.BasisWorker.toString();
+					const body = [ '/* constants */', 'let _EngineFormat = ' + JSON.stringify( KTX2Loader.EngineFormat ), 'let _TranscoderFormat = ' + JSON.stringify( KTX2Loader.TranscoderFormat ), 'let _BasisFormat = ' + JSON.stringify( KTX2Loader.BasisFormat ), '/* basis_transcoder.js */', jsContent, '/* worker */', fn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) ) ].join( '\n' );
+					this.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );
+					this.transcoderBinary = binaryContent;
+					this.workerPool.setWorkerCreator( () => {
+
+						const worker = new Worker( this.workerSourceURL );
+						const transcoderBinary = this.transcoderBinary.slice( 0 );
+						worker.postMessage( {
+							type: 'init',
+							config: this.workerConfig,
+							transcoderBinary
+						}, [ transcoderBinary ] );
+						return worker;
+
+					} );
+
+				} );
+
+				if ( _activeLoaders > 0 ) {
+
+					// Each instance loads a transcoder and allocates workers, increasing network and memory cost.
+					console.warn( 'THREE.KTX2Loader: Multiple active KTX2 loaders may cause performance issues.' + ' Use a single KTX2Loader instance, or call .dispose() on old instances.' );
+
+				}
+
+				_activeLoaders ++;
+
+			}
+
+			return this.transcoderPending;
+
+		}
+
+		load( url, onLoad, onProgress, onError ) {
+
+			if ( this.workerConfig === null ) {
+
+				throw new Error( 'THREE.KTX2Loader: Missing initialization with `.detectSupport( renderer )`.' );
+
+			}
+
+			const loader = new THREE.FileLoader( this.manager );
+			loader.setResponseType( 'arraybuffer' );
+			loader.setWithCredentials( this.withCredentials );
+			loader.load( url, buffer => {
+
+				// Check for an existing task using this buffer. A transferred buffer cannot be transferred
+				// again from this thread.
+				if ( _taskCache.has( buffer ) ) {
+
+					const cachedTask = _taskCache.get( buffer );
+
+					return cachedTask.promise.then( onLoad ).catch( onError );
+
+				}
+
+				this._createTexture( buffer ).then( texture => onLoad ? onLoad( texture ) : null ).catch( onError );
+
+			}, onProgress, onError );
+
+		}
+
+		_createTextureFrom( transcodeResult ) {
+
+			const {
+				mipmaps,
+				width,
+				height,
+				format,
+				type,
+				error,
+				dfdTransferFn,
+				dfdFlags
+			} = transcodeResult;
+			if ( type === 'error' ) return Promise.reject( error );
+			const texture = new THREE.CompressedTexture( mipmaps, width, height, format, THREE.UnsignedByteType );
+			texture.minFilter = mipmaps.length === 1 ? THREE.LinearFilter : THREE.LinearMipmapLinearFilter;
+			texture.magFilter = THREE.LinearFilter;
+			texture.generateMipmaps = false;
+			texture.needsUpdate = true;
+			texture.encoding = dfdTransferFn === KHR_DF_TRANSFER_SRGB ? THREE.sRGBEncoding : THREE.LinearEncoding;
+			texture.premultiplyAlpha = !! ( dfdFlags & KHR_DF_FLAG_ALPHA_PREMULTIPLIED );
+			return texture;
+
+		}
+		/**
+   * @param {ArrayBuffer} buffer
+   * @param {object?} config
+   * @return {Promise<CompressedTexture|DataTexture|Data3DTexture>}
+   */
+
+
+		_createTexture( buffer, config = {} ) {
+
+			const container = read( new Uint8Array( buffer ) );
+
+			if ( container.vkFormat !== VK_FORMAT_UNDEFINED ) {
+
+				return createDataTexture( container );
+
+			} //
+
+
+			const taskConfig = config;
+			const texturePending = this.init().then( () => {
+
+				return this.workerPool.postMessage( {
+					type: 'transcode',
+					buffer,
+					taskConfig: taskConfig
+				}, [ buffer ] );
+
+			} ).then( e => this._createTextureFrom( e.data ) ); // Cache the task result.
+
+			_taskCache.set( buffer, {
+				promise: texturePending
+			} );
+
+			return texturePending;
+
+		}
+
+		dispose() {
+
+			this.workerPool.dispose();
+			if ( this.workerSourceURL ) URL.revokeObjectURL( this.workerSourceURL );
+			_activeLoaders --;
+			return this;
+
+		}
+
+	}
+	/* CONSTANTS */
+
+
+	KTX2Loader.BasisFormat = {
+		ETC1S: 0,
+		UASTC_4x4: 1
+	};
+	KTX2Loader.TranscoderFormat = {
+		ETC1: 0,
+		ETC2: 1,
+		BC1: 2,
+		BC3: 3,
+		BC4: 4,
+		BC5: 5,
+		BC7_M6_OPAQUE_ONLY: 6,
+		BC7_M5: 7,
+		PVRTC1_4_RGB: 8,
+		PVRTC1_4_RGBA: 9,
+		ASTC_4x4: 10,
+		ATC_RGB: 11,
+		ATC_RGBA_INTERPOLATED_ALPHA: 12,
+		RGBA32: 13,
+		RGB565: 14,
+		BGR565: 15,
+		RGBA4444: 16
+	};
+	KTX2Loader.EngineFormat = {
+		RGBAFormat: THREE.RGBAFormat,
+		RGBA_ASTC_4x4_Format: THREE.RGBA_ASTC_4x4_Format,
+		RGBA_BPTC_Format: THREE.RGBA_BPTC_Format,
+		RGBA_ETC2_EAC_Format: THREE.RGBA_ETC2_EAC_Format,
+		RGBA_PVRTC_4BPPV1_Format: THREE.RGBA_PVRTC_4BPPV1_Format,
+		RGBA_S3TC_DXT5_Format: THREE.RGBA_S3TC_DXT5_Format,
+		RGB_ETC1_Format: THREE.RGB_ETC1_Format,
+		RGB_ETC2_Format: THREE.RGB_ETC2_Format,
+		RGB_PVRTC_4BPPV1_Format: THREE.RGB_PVRTC_4BPPV1_Format,
+		RGB_S3TC_DXT1_Format: THREE.RGB_S3TC_DXT1_Format
+	};
+	/* WEB WORKER */
+
+	KTX2Loader.BasisWorker = function () {
+
+		let config;
+		let transcoderPending;
+		let BasisModule;
+		const EngineFormat = _EngineFormat; // eslint-disable-line no-undef
+
+		const TranscoderFormat = _TranscoderFormat; // eslint-disable-line no-undef
+
+		const BasisFormat = _BasisFormat; // eslint-disable-line no-undef
+
+		self.addEventListener( 'message', function ( e ) {
+
+			const message = e.data;
+
+			switch ( message.type ) {
+
+				case 'init':
+					config = message.config;
+					init( message.transcoderBinary );
+					break;
+
+				case 'transcode':
+					transcoderPending.then( () => {
+
+						try {
+
+							const {
+								width,
+								height,
+								hasAlpha,
+								mipmaps,
+								format,
+								dfdTransferFn,
+								dfdFlags
+							} = transcode( message.buffer );
+							const buffers = [];
+
+							for ( let i = 0; i < mipmaps.length; ++ i ) {
+
+								buffers.push( mipmaps[ i ].data.buffer );
+
+							}
+
+							self.postMessage( {
+								type: 'transcode',
+								id: message.id,
+								width,
+								height,
+								hasAlpha,
+								mipmaps,
+								format,
+								dfdTransferFn,
+								dfdFlags
+							}, buffers );
+
+						} catch ( error ) {
+
+							console.error( error );
+							self.postMessage( {
+								type: 'error',
+								id: message.id,
+								error: error.message
+							} );
+
+						}
+
+					} );
+					break;
+
+			}
+
+		} );
+
+		function init( wasmBinary ) {
+
+			transcoderPending = new Promise( resolve => {
+
+				BasisModule = {
+					wasmBinary,
+					onRuntimeInitialized: resolve
+				};
+				BASIS( BasisModule ); // eslint-disable-line no-undef
+
+			} ).then( () => {
+
+				BasisModule.initializeBasis();
+
+				if ( BasisModule.KTX2File === undefined ) {
+
+					console.warn( 'THREE.KTX2Loader: Please update Basis Universal transcoder.' );
+
+				}
+
+			} );
+
+		}
+
+		function transcode( buffer ) {
+
+			const ktx2File = new BasisModule.KTX2File( new Uint8Array( buffer ) );
+
+			function cleanup() {
+
+				ktx2File.close();
+				ktx2File.delete();
+
+			}
+
+			if ( ! ktx2File.isValid() ) {
+
+				cleanup();
+				throw new Error( 'THREE.KTX2Loader:	Invalid or unsupported .ktx2 file' );
+
+			}
+
+			const basisFormat = ktx2File.isUASTC() ? BasisFormat.UASTC_4x4 : BasisFormat.ETC1S;
+			const width = ktx2File.getWidth();
+			const height = ktx2File.getHeight();
+			const levels = ktx2File.getLevels();
+			const hasAlpha = ktx2File.getHasAlpha();
+			const dfdTransferFn = ktx2File.getDFDTransferFunc();
+			const dfdFlags = ktx2File.getDFDFlags();
+			const {
+				transcoderFormat,
+				engineFormat
+			} = getTranscoderFormat( basisFormat, width, height, hasAlpha );
+
+			if ( ! width || ! height || ! levels ) {
+
+				cleanup();
+				throw new Error( 'THREE.KTX2Loader:	Invalid texture' );
+
+			}
+
+			if ( ! ktx2File.startTranscoding() ) {
+
+				cleanup();
+				throw new Error( 'THREE.KTX2Loader: .startTranscoding failed' );
+
+			}
+
+			const mipmaps = [];
+
+			for ( let mip = 0; mip < levels; mip ++ ) {
+
+				const levelInfo = ktx2File.getImageLevelInfo( mip, 0, 0 );
+				const mipWidth = levelInfo.origWidth;
+				const mipHeight = levelInfo.origHeight;
+				const dst = new Uint8Array( ktx2File.getImageTranscodedSizeInBytes( mip, 0, 0, transcoderFormat ) );
+				const status = ktx2File.transcodeImage( dst, mip, 0, 0, transcoderFormat, 0, - 1, - 1 );
+
+				if ( ! status ) {
+
+					cleanup();
+					throw new Error( 'THREE.KTX2Loader: .transcodeImage failed.' );
+
+				}
+
+				mipmaps.push( {
+					data: dst,
+					width: mipWidth,
+					height: mipHeight
+				} );
+
+			}
+
+			cleanup();
+			return {
+				width,
+				height,
+				hasAlpha,
+				mipmaps,
+				format: engineFormat,
+				dfdTransferFn,
+				dfdFlags
+			};
+
+		} //
+		// Optimal choice of a transcoder target format depends on the Basis format (ETC1S or UASTC),
+		// device capabilities, and texture dimensions. The list below ranks the formats separately
+		// for ETC1S and UASTC.
+		//
+		// In some cases, transcoding UASTC to RGBA32 might be preferred for higher quality (at
+		// significant memory cost) compared to ETC1/2, BC1/3, and PVRTC. The transcoder currently
+		// chooses RGBA32 only as a last resort and does not expose that option to the caller.
+
+
+		const FORMAT_OPTIONS = [ {
+			if: 'astcSupported',
+			basisFormat: [ BasisFormat.UASTC_4x4 ],
+			transcoderFormat: [ TranscoderFormat.ASTC_4x4, TranscoderFormat.ASTC_4x4 ],
+			engineFormat: [ EngineFormat.RGBA_ASTC_4x4_Format, EngineFormat.RGBA_ASTC_4x4_Format ],
+			priorityETC1S: Infinity,
+			priorityUASTC: 1,
+			needsPowerOfTwo: false
+		}, {
+			if: 'bptcSupported',
+			basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
+			transcoderFormat: [ TranscoderFormat.BC7_M5, TranscoderFormat.BC7_M5 ],
+			engineFormat: [ EngineFormat.RGBA_BPTC_Format, EngineFormat.RGBA_BPTC_Format ],
+			priorityETC1S: 3,
+			priorityUASTC: 2,
+			needsPowerOfTwo: false
+		}, {
+			if: 'dxtSupported',
+			basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
+			transcoderFormat: [ TranscoderFormat.BC1, TranscoderFormat.BC3 ],
+			engineFormat: [ EngineFormat.RGB_S3TC_DXT1_Format, EngineFormat.RGBA_S3TC_DXT5_Format ],
+			priorityETC1S: 4,
+			priorityUASTC: 5,
+			needsPowerOfTwo: false
+		}, {
+			if: 'etc2Supported',
+			basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
+			transcoderFormat: [ TranscoderFormat.ETC1, TranscoderFormat.ETC2 ],
+			engineFormat: [ EngineFormat.RGB_ETC2_Format, EngineFormat.RGBA_ETC2_EAC_Format ],
+			priorityETC1S: 1,
+			priorityUASTC: 3,
+			needsPowerOfTwo: false
+		}, {
+			if: 'etc1Supported',
+			basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
+			transcoderFormat: [ TranscoderFormat.ETC1 ],
+			engineFormat: [ EngineFormat.RGB_ETC1_Format ],
+			priorityETC1S: 2,
+			priorityUASTC: 4,
+			needsPowerOfTwo: false
+		}, {
+			if: 'pvrtcSupported',
+			basisFormat: [ BasisFormat.ETC1S, BasisFormat.UASTC_4x4 ],
+			transcoderFormat: [ TranscoderFormat.PVRTC1_4_RGB, TranscoderFormat.PVRTC1_4_RGBA ],
+			engineFormat: [ EngineFormat.RGB_PVRTC_4BPPV1_Format, EngineFormat.RGBA_PVRTC_4BPPV1_Format ],
+			priorityETC1S: 5,
+			priorityUASTC: 6,
+			needsPowerOfTwo: true
+		} ];
+		const ETC1S_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) {
+
+			return a.priorityETC1S - b.priorityETC1S;
+
+		} );
+		const UASTC_OPTIONS = FORMAT_OPTIONS.sort( function ( a, b ) {
+
+			return a.priorityUASTC - b.priorityUASTC;
+
+		} );
+
+		function getTranscoderFormat( basisFormat, width, height, hasAlpha ) {
+
+			let transcoderFormat;
+			let engineFormat;
+			const options = basisFormat === BasisFormat.ETC1S ? ETC1S_OPTIONS : UASTC_OPTIONS;
+
+			for ( let i = 0; i < options.length; i ++ ) {
+
+				const opt = options[ i ];
+				if ( ! config[ opt.if ] ) continue;
+				if ( ! opt.basisFormat.includes( basisFormat ) ) continue;
+				if ( hasAlpha && opt.transcoderFormat.length < 2 ) continue;
+				if ( opt.needsPowerOfTwo && ! ( isPowerOfTwo( width ) && isPowerOfTwo( height ) ) ) continue;
+				transcoderFormat = opt.transcoderFormat[ hasAlpha ? 1 : 0 ];
+				engineFormat = opt.engineFormat[ hasAlpha ? 1 : 0 ];
+				return {
+					transcoderFormat,
+					engineFormat
+				};
+
+			}
+
+			console.warn( 'THREE.KTX2Loader: No suitable compressed texture format found. Decoding to RGBA32.' );
+			transcoderFormat = TranscoderFormat.RGBA32;
+			engineFormat = EngineFormat.RGBAFormat;
+			return {
+				transcoderFormat,
+				engineFormat
+			};
+
+		}
+
+		function isPowerOfTwo( value ) {
+
+			if ( value <= 2 ) return true;
+			return ( value & value - 1 ) === 0 && value !== 0;
+
+		}
+
+	}; //
+	// THREE.DataTexture and THREE.Data3DTexture parsing.
+
+
+	const FORMAT_MAP = {
+		[ VK_FORMAT_R32G32B32A32_SFLOAT ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R16G16B16A16_SFLOAT ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R8G8B8A8_UNORM ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R8G8B8A8_SRGB ]: THREE.RGBAFormat,
+		[ VK_FORMAT_R32G32_SFLOAT ]: THREE.RGFormat,
+		[ VK_FORMAT_R16G16_SFLOAT ]: THREE.RGFormat,
+		[ VK_FORMAT_R8G8_UNORM ]: THREE.RGFormat,
+		[ VK_FORMAT_R8G8_SRGB ]: THREE.RGFormat,
+		[ VK_FORMAT_R32_SFLOAT ]: THREE.RedFormat,
+		[ VK_FORMAT_R16_SFLOAT ]: THREE.RedFormat,
+		[ VK_FORMAT_R8_SRGB ]: THREE.RedFormat,
+		[ VK_FORMAT_R8_UNORM ]: THREE.RedFormat
+	};
+	const TYPE_MAP = {
+		[ VK_FORMAT_R32G32B32A32_SFLOAT ]: THREE.FloatType,
+		[ VK_FORMAT_R16G16B16A16_SFLOAT ]: THREE.HalfFloatType,
+		[ VK_FORMAT_R8G8B8A8_UNORM ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R8G8B8A8_SRGB ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R32G32_SFLOAT ]: THREE.FloatType,
+		[ VK_FORMAT_R16G16_SFLOAT ]: THREE.HalfFloatType,
+		[ VK_FORMAT_R8G8_UNORM ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R8G8_SRGB ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R32_SFLOAT ]: THREE.FloatType,
+		[ VK_FORMAT_R16_SFLOAT ]: THREE.HalfFloatType,
+		[ VK_FORMAT_R8_SRGB ]: THREE.UnsignedByteType,
+		[ VK_FORMAT_R8_UNORM ]: THREE.UnsignedByteType
+	};
+	const ENCODING_MAP = {
+		[ VK_FORMAT_R8G8B8A8_SRGB ]: THREE.sRGBEncoding,
+		[ VK_FORMAT_R8G8_SRGB ]: THREE.sRGBEncoding,
+		[ VK_FORMAT_R8_SRGB ]: THREE.sRGBEncoding
+	};
+
+	async function createDataTexture( container ) {
+
+		const {
+			vkFormat,
+			pixelWidth,
+			pixelHeight,
+			pixelDepth
+		} = container;
+
+		if ( FORMAT_MAP[ vkFormat ] === undefined ) {
+
+			throw new Error( 'THREE.KTX2Loader: Unsupported vkFormat.' );
+
+		} //
+
+
+		const level = container.levels[ 0 ];
+		let levelData;
+		let view;
+
+		if ( container.supercompressionScheme === KHR_SUPERCOMPRESSION_NONE ) {
+
+			levelData = level.levelData;
+
+		} else if ( container.supercompressionScheme === KHR_SUPERCOMPRESSION_ZSTD ) {
+
+			if ( ! _zstd ) {
+
+				_zstd = new Promise( async resolve => {
+
+					const zstd = new ZSTDDecoder();
+					await zstd.init();
+					resolve( zstd );
+
+				} );
+
+			}
+
+			levelData = ( await _zstd ).decode( level.levelData, level.uncompressedByteLength );
+
+		} else {
+
+			throw new Error( 'THREE.KTX2Loader: Unsupported supercompressionScheme.' );
+
+		}
+
+		if ( TYPE_MAP[ vkFormat ] === THREE.FloatType ) {
+
+			view = new Float32Array( levelData.buffer, levelData.byteOffset, levelData.byteLength / Float32Array.BYTES_PER_ELEMENT );
+
+		} else if ( TYPE_MAP[ vkFormat ] === THREE.HalfFloatType ) {
+
+			view = new Uint16Array( levelData.buffer, levelData.byteOffset, levelData.byteLength / Uint16Array.BYTES_PER_ELEMENT );
+
+		} else {
+
+			view = levelData;
+
+		} //
+
+
+		const texture = pixelDepth === 0 ? new THREE.DataTexture( view, pixelWidth, pixelHeight ) : new THREE.Data3DTexture( view, pixelWidth, pixelHeight, pixelDepth );
+		texture.type = TYPE_MAP[ vkFormat ];
+		texture.format = FORMAT_MAP[ vkFormat ];
+		texture.encoding = ENCODING_MAP[ vkFormat ] || THREE.LinearEncoding;
+		texture.needsUpdate = true; //
+
+		return Promise.resolve( texture );
+
+	}
+
+	THREE.KTX2Loader = KTX2Loader;
+
+} )();

+ 43 - 5
examples/js/loaders/PCDLoader.js

@@ -194,7 +194,9 @@
 
 			const position = [];
 			const normal = [];
-			const color = []; // ascii
+			const color = [];
+			const intensity = [];
+			const label = []; // ascii
 
 			if ( PCDheader.data === 'ascii' ) {
 
@@ -247,6 +249,18 @@
 
 					}
 
+					if ( offset.intensity !== undefined ) {
+
+						intensity.push( parseFloat( line[ offset.intensity ] ) );
+
+					}
+
+					if ( offset.label !== undefined ) {
+
+						label.push( parseInt( line[ offset.label ] ) );
+
+					}
+
 				}
 
 			} // binary-compressed
@@ -297,6 +311,20 @@
 
 					}
 
+					if ( offset.intensity !== undefined ) {
+
+						const intensityIndex = PCDheader.fields.indexOf( 'intensity' );
+						intensity.push( dataview.getFloat32( PCDheader.points * offset.intensity + PCDheader.size[ intensityIndex ] * i, this.littleEndian ) );
+
+					}
+
+					if ( offset.label !== undefined ) {
+
+						const labelIndex = PCDheader.fields.indexOf( 'label' );
+						label.push( dataview.getInt32( PCDheader.points * offset.label + PCDheader.size[ labelIndex ] * i, this.littleEndian ) );
+
+					}
+
 				}
 
 			} // binary
@@ -333,6 +361,18 @@
 
 					}
 
+					if ( offset.intensity !== undefined ) {
+
+						intensity.push( dataview.getFloat32( row + offset.intensity, this.littleEndian ) );
+
+					}
+
+					if ( offset.label !== undefined ) {
+
+						label.push( dataview.getInt32( row + offset.label, this.littleEndian ) );
+
+					}
+
 				}
 
 			} // build geometry
@@ -342,6 +382,8 @@
 			if ( position.length > 0 ) geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) );
 			if ( normal.length > 0 ) geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( normal, 3 ) );
 			if ( color.length > 0 ) geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( color, 3 ) );
+			if ( intensity.length > 0 ) geometry.setAttribute( 'intensity', new THREE.Float32BufferAttribute( intensity, 1 ) );
+			if ( label.length > 0 ) geometry.setAttribute( 'label', new THREE.Int32BufferAttribute( label, 1 ) );
 			geometry.computeBoundingSphere(); // build material
 
 			const material = new THREE.PointsMaterial( {
@@ -352,10 +394,6 @@
 
 				material.vertexColors = true;
 
-			} else {
-
-				material.color.setHex( Math.random() * 0xffffff );
-
 			} // build point cloud
 
 

+ 2 - 2
examples/js/loaders/SVGLoader.js

@@ -1279,7 +1279,7 @@
 									if ( array.length >= 1 ) {
 
 										const tx = array[ 0 ];
-										let ty = tx;
+										let ty = 0;
 
 										if ( array.length >= 2 ) {
 
@@ -1908,7 +1908,7 @@
 			} );
 			simplePaths = simplePaths.filter( sp => sp.points.length > 1 ); // check if path is solid or a hole
 
-			const isAHole = simplePaths.map( p => isHoleTo( p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData.style.fillRule ) );
+			const isAHole = simplePaths.map( p => isHoleTo( p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData?.style.fillRule ) );
 			const shapesToReturn = [];
 			simplePaths.forEach( p => {
 

+ 31 - 0
examples/js/loaders/TIFFLoader.js

@@ -0,0 +1,31 @@
+( function () {
+
+	class TIFFLoader extends THREE.DataTextureLoader {
+
+		constructor( manager ) {
+
+			super( manager );
+
+		}
+
+		parse( buffer ) {
+
+			const ifds = UTIF.decode( buffer );
+			UTIF.decodeImage( buffer, ifds[ 0 ] );
+			const rgba = UTIF.toRGBA8( ifds[ 0 ] );
+			return {
+				width: ifds[ 0 ].width,
+				height: ifds[ 0 ].height,
+				data: rgba,
+				flipY: true,
+				magFilter: THREE.LinearFilter,
+				minFilter: THREE.LinearMipmapLinearFilter
+			};
+
+		}
+
+	}
+
+	THREE.TIFFLoader = TIFFLoader;
+
+} )();

+ 385 - 0
examples/js/materials/MeshGouraudMaterial.js

@@ -0,0 +1,385 @@
+( function () {
+
+	/**
+ * MeshGouraudMaterial
+ *
+ * Lambert illumination model with Gouraud (per-vertex) shading
+ *
+ */
+	const GouraudShader = {
+		uniforms: /*@__PURE__*/UniformsUtils.merge( [ THREE.UniformsLib.common, THREE.UniformsLib.specularmap, THREE.UniformsLib.envmap, THREE.UniformsLib.aomap, THREE.UniformsLib.lightmap, THREE.UniformsLib.emissivemap, THREE.UniformsLib.fog, THREE.UniformsLib.lights, {
+			emissive: {
+				value: /*@__PURE__*/new THREE.Color( 0x000000 )
+			}
+		} ] ),
+		vertexShader:
+  /* glsl */
+  `
+
+		#define GOURAUD
+
+		varying vec3 vLightFront;
+		varying vec3 vIndirectFront;
+
+		#ifdef DOUBLE_SIDED
+			varying vec3 vLightBack;
+			varying vec3 vIndirectBack;
+		#endif
+
+		#include <common>
+		#include <uv_pars_vertex>
+		#include <uv2_pars_vertex>
+		#include <envmap_pars_vertex>
+		#include <bsdfs>
+		#include <lights_pars_begin>
+		#include <color_pars_vertex>
+		#include <fog_pars_vertex>
+		#include <morphtarget_pars_vertex>
+		#include <skinning_pars_vertex>
+		#include <shadowmap_pars_vertex>
+		#include <logdepthbuf_pars_vertex>
+		#include <clipping_planes_pars_vertex>
+
+		void main() {
+
+			#include <uv_vertex>
+			#include <uv2_vertex>
+			#include <color_vertex>
+			#include <morphcolor_vertex>
+
+			#include <beginnormal_vertex>
+			#include <morphnormal_vertex>
+			#include <skinbase_vertex>
+			#include <skinnormal_vertex>
+			#include <defaultnormal_vertex>
+
+			#include <begin_vertex>
+			#include <morphtarget_vertex>
+			#include <skinning_vertex>
+			#include <project_vertex>
+			#include <logdepthbuf_vertex>
+			#include <clipping_planes_vertex>
+
+			#include <worldpos_vertex>
+			#include <envmap_vertex>
+
+			// inlining legacy <lights_lambert_vertex>
+
+			vec3 diffuse = vec3( 1.0 );
+
+			GeometricContext geometry;
+			geometry.position = mvPosition.xyz;
+			geometry.normal = normalize( transformedNormal );
+			geometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );
+
+			GeometricContext backGeometry;
+			backGeometry.position = geometry.position;
+			backGeometry.normal = -geometry.normal;
+			backGeometry.viewDir = geometry.viewDir;
+
+			vLightFront = vec3( 0.0 );
+			vIndirectFront = vec3( 0.0 );
+			#ifdef DOUBLE_SIDED
+				vLightBack = vec3( 0.0 );
+				vIndirectBack = vec3( 0.0 );
+			#endif
+
+			IncidentLight directLight;
+			float dotNL;
+			vec3 directLightColor_Diffuse;
+
+			vIndirectFront += getAmbientLightIrradiance( ambientLightColor );
+
+			vIndirectFront += getLightProbeIrradiance( lightProbe, geometry.normal );
+
+			#ifdef DOUBLE_SIDED
+
+				vIndirectBack += getAmbientLightIrradiance( ambientLightColor );
+
+				vIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry.normal );
+
+			#endif
+
+			#if NUM_POINT_LIGHTS > 0
+
+				#pragma unroll_loop_start
+				for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
+
+					getPointLightInfo( pointLights[ i ], geometry, directLight );
+
+					dotNL = dot( geometry.normal, directLight.direction );
+					directLightColor_Diffuse = directLight.color;
+
+					vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
+
+					#ifdef DOUBLE_SIDED
+
+						vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;
+
+					#endif
+
+				}
+				#pragma unroll_loop_end
+
+			#endif
+
+			#if NUM_SPOT_LIGHTS > 0
+
+				#pragma unroll_loop_start
+				for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {
+
+					getSpotLightInfo( spotLights[ i ], geometry, directLight );
+
+					dotNL = dot( geometry.normal, directLight.direction );
+					directLightColor_Diffuse = directLight.color;
+
+					vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
+
+					#ifdef DOUBLE_SIDED
+
+						vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;
+
+					#endif
+				}
+				#pragma unroll_loop_end
+
+			#endif
+
+			#if NUM_DIR_LIGHTS > 0
+
+				#pragma unroll_loop_start
+				for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {
+
+					getDirectionalLightInfo( directionalLights[ i ], geometry, directLight );
+
+					dotNL = dot( geometry.normal, directLight.direction );
+					directLightColor_Diffuse = directLight.color;
+
+					vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
+
+					#ifdef DOUBLE_SIDED
+
+						vLightBack += saturate( - dotNL ) * directLightColor_Diffuse;
+
+					#endif
+
+				}
+				#pragma unroll_loop_end
+
+			#endif
+
+			#if NUM_HEMI_LIGHTS > 0
+
+				#pragma unroll_loop_start
+				for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {
+
+					vIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry.normal );
+
+					#ifdef DOUBLE_SIDED
+
+						vIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry.normal );
+
+					#endif
+
+				}
+				#pragma unroll_loop_end
+
+			#endif
+
+			#include <shadowmap_vertex>
+			#include <fog_vertex>
+
+		}`,
+		fragmentShader:
+  /* glsl */
+  `
+
+		#define GOURAUD
+
+		uniform vec3 diffuse;
+		uniform vec3 emissive;
+		uniform float opacity;
+
+		varying vec3 vLightFront;
+		varying vec3 vIndirectFront;
+
+		#ifdef DOUBLE_SIDED
+			varying vec3 vLightBack;
+			varying vec3 vIndirectBack;
+		#endif
+
+		#include <common>
+		#include <packing>
+		#include <dithering_pars_fragment>
+		#include <color_pars_fragment>
+		#include <uv_pars_fragment>
+		#include <uv2_pars_fragment>
+		#include <map_pars_fragment>
+		#include <alphamap_pars_fragment>
+		#include <alphatest_pars_fragment>
+		#include <aomap_pars_fragment>
+		#include <lightmap_pars_fragment>
+		#include <emissivemap_pars_fragment>
+		#include <envmap_common_pars_fragment>
+		#include <envmap_pars_fragment>
+		#include <bsdfs>
+		#include <lights_pars_begin>
+		#include <fog_pars_fragment>
+		#include <shadowmap_pars_fragment>
+		#include <shadowmask_pars_fragment>
+		#include <specularmap_pars_fragment>
+		#include <logdepthbuf_pars_fragment>
+		#include <clipping_planes_pars_fragment>
+
+		void main() {
+
+			#include <clipping_planes_fragment>
+
+			vec4 diffuseColor = vec4( diffuse, opacity );
+			ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );
+			vec3 totalEmissiveRadiance = emissive;
+
+			#include <logdepthbuf_fragment>
+			#include <map_fragment>
+			#include <color_fragment>
+			#include <alphamap_fragment>
+			#include <alphatest_fragment>
+			#include <specularmap_fragment>
+			#include <emissivemap_fragment>
+
+			// accumulation
+
+			#ifdef DOUBLE_SIDED
+
+				reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;
+
+			#else
+
+				reflectedLight.indirectDiffuse += vIndirectFront;
+
+			#endif
+
+			#include <lightmap_fragment>
+
+			reflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );
+
+			#ifdef DOUBLE_SIDED
+
+				reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;
+
+			#else
+
+				reflectedLight.directDiffuse = vLightFront;
+
+			#endif
+
+			reflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();
+
+			// modulation
+
+			#include <aomap_fragment>
+
+			vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;
+
+			#include <envmap_fragment>
+
+			#include <output_fragment>
+			#include <tonemapping_fragment>
+			#include <encodings_fragment>
+			#include <fog_fragment>
+			#include <premultiplied_alpha_fragment>
+			#include <dithering_fragment>
+
+		}`
+	}; //
+
+	class MeshGouraudMaterial extends THREE.ShaderMaterial {
+
+		constructor( parameters ) {
+
+			super();
+			this.isMeshGouraudMaterial = true;
+			this.type = 'MeshGouraudMaterial'; //this.color = new THREE.Color( 0xffffff ); // diffuse
+			//this.map = null;
+			//this.lightMap = null;
+			//this.lightMapIntensity = 1.0;
+			//this.aoMap = null;
+			//this.aoMapIntensity = 1.0;
+			//this.emissive = new THREE.Color( 0x000000 );
+			//this.emissiveIntensity = 1.0;
+			//this.emissiveMap = null;
+			//this.specularMap = null;
+			//this.alphaMap = null;
+			//this.envMap = null;
+
+			this.combine = THREE.MultiplyOperation; // combine has no uniform
+			//this.reflectivity = 1;
+			//this.refractionRatio = 0.98;
+
+			this.fog = false; // set to use scene fog
+
+			this.lights = true; // set to use scene lights
+
+			this.clipping = false; // set to use user-defined clipping planes
+
+			const shader = GouraudShader;
+			this.defines = Object.assign( {}, shader.defines );
+			this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+			this.vertexShader = shader.vertexShader;
+			this.fragmentShader = shader.fragmentShader;
+			const exposePropertyNames = [ 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'specularMap', 'alphaMap', 'envMap', 'reflectivity', 'refractionRatio', 'opacity', 'diffuse' ];
+
+			for ( const propertyName of exposePropertyNames ) {
+
+				Object.defineProperty( this, propertyName, {
+					get: function () {
+
+						return this.uniforms[ propertyName ].value;
+
+					},
+					set: function ( value ) {
+
+						this.uniforms[ propertyName ].value = value;
+
+					}
+				} );
+
+			}
+
+			Object.defineProperty( this, 'color', Object.getOwnPropertyDescriptor( this, 'diffuse' ) );
+			this.setValues( parameters );
+
+		}
+
+		copy( source ) {
+
+			super.copy( source );
+			this.color.copy( source.color );
+			this.map = source.map;
+			this.lightMap = source.lightMap;
+			this.lightMapIntensity = source.lightMapIntensity;
+			this.aoMap = source.aoMap;
+			this.aoMapIntensity = source.aoMapIntensity;
+			this.emissive.copy( source.emissive );
+			this.emissiveMap = source.emissiveMap;
+			this.emissiveIntensity = source.emissiveIntensity;
+			this.specularMap = source.specularMap;
+			this.alphaMap = source.alphaMap;
+			this.envMap = source.envMap;
+			this.combine = source.combine;
+			this.reflectivity = source.reflectivity;
+			this.refractionRatio = source.refractionRatio;
+			this.wireframe = source.wireframe;
+			this.wireframeLinewidth = source.wireframeLinewidth;
+			this.wireframeLinecap = source.wireframeLinecap;
+			this.wireframeLinejoin = source.wireframeLinejoin;
+			this.fog = source.fog;
+			return this;
+
+		}
+
+	}
+
+	THREE.MeshGouraudMaterial = MeshGouraudMaterial;
+
+} )();

+ 0 - 23
examples/js/math/ColorConverter.js

@@ -16,17 +16,6 @@
 
 		static getHSV( color, target ) {
 
-			if ( target === undefined ) {
-
-				console.warn( 'THREE.ColorConverter: .getHSV() target is now required' );
-				target = {
-					h: 0,
-					s: 0,
-					l: 0
-				};
-
-			}
-
 			color.getHSL( _hsl ); // based on https://gist.github.com/xpansive/1337890#file-index-js
 
 			_hsl.s *= _hsl.l < 0.5 ? _hsl.l : 1 - _hsl.l;
@@ -49,18 +38,6 @@
 
 		static getCMYK( color, target ) {
 
-			if ( target === undefined ) {
-
-				console.warn( 'THREE.ColorConverter: .getCMYK() target is now required' );
-				target = {
-					c: 0,
-					m: 0,
-					y: 0,
-					k: 0
-				};
-
-			}
-
 			const r = color.r;
 			const g = color.g;
 			const b = color.b;

+ 23 - 0
examples/js/misc/GPUComputationRenderer.js

@@ -263,6 +263,29 @@
 
 			};
 
+			this.dispose = function () {
+
+				mesh.geometry.dispose();
+				mesh.material.dispose();
+				const variables = this.variables;
+
+				for ( let i = 0; i < variables.length; i ++ ) {
+
+					const variable = variables[ i ];
+					variable.initialValueTexture?.dispose();
+					const renderTargets = variable.renderTargets;
+
+					for ( let j = 0; j < renderTargets.length; j ++ ) {
+
+						const renderTarget = renderTargets[ j ];
+						renderTarget.dispose();
+
+					}
+
+				}
+
+			};
+
 			function addResolutionDefine( materialShader ) {
 
 				materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + ' )';

+ 193 - 0
examples/js/objects/GroundProjectedEnv.js

@@ -0,0 +1,193 @@
+( function () {
+
+	/**
+ * Ground projected env map adapted from @react-three/drei.
+ * https://github.com/pmndrs/drei/blob/master/src/core/Environment.tsx
+ */
+
+	class GroundProjectedEnv extends THREE.Mesh {
+
+		constructor( texture, options ) {
+
+			const isCubeMap = texture.isCubeTexture;
+			const w = ( isCubeMap ? texture.image[ 0 ]?.width : texture.image.width ) ?? 1024;
+			const cubeSize = w / 4;
+
+			const _lodMax = Math.floor( Math.log2( cubeSize ) );
+
+			const _cubeSize = Math.pow( 2, _lodMax );
+
+			const width = 3 * Math.max( _cubeSize, 16 * 7 );
+			const height = 4 * _cubeSize;
+			const defines = [ isCubeMap ? '#define ENVMAP_TYPE_CUBE' : '', `#define CUBEUV_TEXEL_WIDTH ${1.0 / width}`, `#define CUBEUV_TEXEL_HEIGHT ${1.0 / height}`, `#define CUBEUV_MAX_MIP ${_lodMax}.0` ];
+			const vertexShader =
+    /* glsl */
+    `
+        varying vec3 vWorldPosition;
+
+        void main() 
+        {
+
+            vec4 worldPosition = ( modelMatrix * vec4( position, 1.0 ) );
+            vWorldPosition = worldPosition.xyz;
+            
+            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+
+        }
+        `;
+			const fragmentShader = defines.join( '\n' ) +
+    /* glsl */
+    `
+        #define ENVMAP_TYPE_CUBE_UV
+
+        varying vec3 vWorldPosition;
+
+        uniform float radius;
+        uniform float height;
+        uniform float angle;
+
+        #ifdef ENVMAP_TYPE_CUBE
+
+            uniform samplerCube map;
+
+        #else
+
+            uniform sampler2D map;
+
+        #endif
+
+        // From: https://www.shadertoy.com/view/4tsBD7
+        float diskIntersectWithBackFaceCulling( vec3 ro, vec3 rd, vec3 c, vec3 n, float r ) 
+        {
+
+            float d = dot ( rd, n );
+            
+            if( d > 0.0 ) { return 1e6; }
+            
+            vec3  o = ro - c;
+            float t = - dot( n, o ) / d;
+            vec3  q = o + rd * t;
+            
+            return ( dot( q, q ) < r * r ) ? t : 1e6;
+
+        }
+
+        // From: https://www.iquilezles.org/www/articles/intersectors/intersectors.htm
+        float sphereIntersect( vec3 ro, vec3 rd, vec3 ce, float ra ) 
+        {
+
+            vec3 oc = ro - ce;
+            float b = dot( oc, rd );
+            float c = dot( oc, oc ) - ra * ra;
+            float h = b * b - c;
+            
+            if( h < 0.0 ) { return -1.0; }
+            
+            h = sqrt( h );
+            
+            return - b + h;
+
+        }
+
+        vec3 project() 
+        {
+
+            vec3 p = normalize( vWorldPosition );
+            vec3 camPos = cameraPosition;
+            camPos.y -= height;
+
+            float intersection = sphereIntersect( camPos, p, vec3( 0.0 ), radius );
+            if( intersection > 0.0 ) {
+                
+                vec3 h = vec3( 0.0, - height, 0.0 );
+                float intersection2 = diskIntersectWithBackFaceCulling( camPos, p, h, vec3( 0.0, 1.0, 0.0 ), radius );
+                p = ( camPos + min( intersection, intersection2 ) * p ) / radius;
+
+            } else {
+
+                p = vec3( 0.0, 1.0, 0.0 );
+
+            }
+
+            return p;
+
+        }
+
+        #include <common>
+        #include <cube_uv_reflection_fragment>
+
+        void main() 
+        {
+
+            vec3 projectedWorldPosition = project();
+            
+            #ifdef ENVMAP_TYPE_CUBE
+
+                vec3 outcolor = textureCube( map, projectedWorldPosition ).rgb;
+
+            #else
+
+                vec3 direction = normalize( projectedWorldPosition );
+                vec2 uv = equirectUv( direction );
+                vec3 outcolor = texture2D( map, uv ).rgb;
+
+            #endif
+
+            gl_FragColor = vec4( outcolor, 1.0 );
+
+            #include <tonemapping_fragment>
+            #include <encodings_fragment>
+
+        }
+        `;
+			const uniforms = {
+				map: {
+					value: texture
+				},
+				height: {
+					value: options?.height || 15
+				},
+				radius: {
+					value: options?.radius || 100
+				}
+			};
+			const geometry = new THREE.IcosahedronGeometry( 1, 16 );
+			const material = new THREE.ShaderMaterial( {
+				uniforms,
+				fragmentShader,
+				vertexShader,
+				side: THREE.DoubleSide
+			} );
+			super( geometry, material );
+
+		}
+
+		set radius( radius ) {
+
+			this.material.uniforms.radius.value = radius;
+
+		}
+
+		get radius() {
+
+			return this.material.uniforms.radius.value;
+
+		}
+
+		set height( height ) {
+
+			this.material.uniforms.height.value = height;
+
+		}
+
+		get height() {
+
+			return this.material.uniforms.height.value;
+
+		}
+
+	}
+
+	THREE.GroundProjectedEnv = GroundProjectedEnv;
+
+} )();

+ 9 - 2
examples/js/objects/Reflector.js

@@ -29,7 +29,8 @@
 			const textureMatrix = new THREE.Matrix4();
 			const virtualCamera = this.camera;
 			const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, {
-				samples: multisample
+				samples: multisample,
+				type: THREE.HalfFloatType
 			} );
 			const material = new THREE.ShaderMaterial( {
 				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
@@ -92,15 +93,18 @@
 				projectionMatrix.elements[ 10 ] = clipPlane.z + 1.0 - clipBias;
 				projectionMatrix.elements[ 14 ] = clipPlane.w; // Render
 
-				renderTarget.texture.encoding = renderer.outputEncoding;
 				scope.visible = false;
 				const currentRenderTarget = renderer.getRenderTarget();
 				const currentXrEnabled = renderer.xr.enabled;
 				const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+				const currentOutputEncoding = renderer.outputEncoding;
+				const currentToneMapping = renderer.toneMapping;
 				renderer.xr.enabled = false; // Avoid camera modification
 
 				renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
+				renderer.outputEncoding = THREE.LinearEncoding;
+				renderer.toneMapping = THREE.NoToneMapping;
 				renderer.setRenderTarget( renderTarget );
 				renderer.state.buffers.depth.setMask( true ); // make sure the depth buffer is writable so it can be properly cleared, see #18897
 
@@ -108,6 +112,8 @@
 				renderer.render( scene, virtualCamera );
 				renderer.xr.enabled = currentXrEnabled;
 				renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+				renderer.outputEncoding = currentOutputEncoding;
+				renderer.toneMapping = currentToneMapping;
 				renderer.setRenderTarget( currentRenderTarget ); // Restore viewport
 
 				const viewport = camera.viewport;
@@ -197,6 +203,7 @@
 			vec4 base = texture2DProj( tDiffuse, vUv );
 			gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
 
+			#include <tonemapping_fragment>
 			#include <encodings_fragment>
 
 		}`

+ 3 - 4
examples/js/objects/ReflectorForSSRPass.js

@@ -80,7 +80,8 @@
 			}
 
 			const parameters = {
-				depthTexture: useDepthTexture ? depthTexture : null
+				depthTexture: useDepthTexture ? depthTexture : null,
+				type: THREE.HalfFloatType
 			};
 			const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, parameters );
 			const material = new THREE.ShaderMaterial( {
@@ -151,9 +152,7 @@
 				textureMatrix.set( 0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0 );
 				textureMatrix.multiply( virtualCamera.projectionMatrix );
 				textureMatrix.multiply( virtualCamera.matrixWorldInverse );
-				textureMatrix.multiply( scope.matrixWorld ); // Render
-
-				renderTarget.texture.encoding = renderer.outputEncoding; // scope.visible = false;
+				textureMatrix.multiply( scope.matrixWorld ); // scope.visible = false;
 
 				const currentRenderTarget = renderer.getRenderTarget();
 				const currentXrEnabled = renderer.xr.enabled;

+ 10 - 4
examples/js/objects/Refractor.js

@@ -24,7 +24,8 @@
 			const textureMatrix = new THREE.Matrix4(); // render target
 
 			const renderTarget = new THREE.WebGLRenderTarget( textureWidth, textureHeight, {
-				samples: multisample
+				samples: multisample,
+				type: THREE.HalfFloatType
 			} ); // material
 
 			this.material = new THREE.ShaderMaterial( {
@@ -136,15 +137,21 @@
 				const currentRenderTarget = renderer.getRenderTarget();
 				const currentXrEnabled = renderer.xr.enabled;
 				const currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
+				const currentOutputEncoding = renderer.outputEncoding;
+				const currentToneMapping = renderer.toneMapping;
 				renderer.xr.enabled = false; // avoid camera modification
 
 				renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
 
+				renderer.outputEncoding = THREE.LinearEncoding;
+				renderer.toneMapping = THREE.NoToneMapping;
 				renderer.setRenderTarget( renderTarget );
 				if ( renderer.autoClear === false ) renderer.clear();
 				renderer.render( scene, virtualCamera );
 				renderer.xr.enabled = currentXrEnabled;
 				renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
+				renderer.outputEncoding = currentOutputEncoding;
+				renderer.toneMapping = currentToneMapping;
 				renderer.setRenderTarget( currentRenderTarget ); // restore viewport
 
 				const viewport = camera.viewport;
@@ -162,9 +169,7 @@
 
 			this.onBeforeRender = function ( renderer, scene, camera ) {
 
-				// Render
-				renderTarget.texture.encoding = renderer.outputEncoding; // ensure refractors are rendered only once per frame
-
+				// ensure refractors are rendered only once per frame
 				if ( camera.userData.refractor === true ) return; // avoid rendering when the refractor is viewed from behind
 
 				if ( ! visible( camera ) === true ) return; // update
@@ -245,6 +250,7 @@
 			vec4 base = texture2DProj( tDiffuse, vUv );
 			gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
 
+			#include <tonemapping_fragment>
 			#include <encodings_fragment>
 
 		}`

+ 1 - 1
examples/js/postprocessing/OutlinePass.js

@@ -384,9 +384,9 @@
 					#include <morphtarget_vertex>
 					#include <skinning_vertex>
 					#include <project_vertex>
+					#include <worldpos_vertex>
 
 					vPosition = mvPosition;
-					vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
 					projTexCoord = textureMatrix * worldPosition;
 
 				}`,

+ 0 - 21
examples/js/renderers/Projector.js

@@ -135,27 +135,6 @@
 				_spritePool = []; //
 
 
-			this.projectVector = function ( vector, camera ) {
-
-				console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );
-				vector.project( camera );
-
-			};
-
-			this.unprojectVector = function ( vector, camera ) {
-
-				console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );
-				vector.unproject( camera );
-
-			};
-
-			this.pickingRay = function () {
-
-				console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
-
-			}; //
-
-
 			function RenderList() {
 
 				const normals = [];

+ 1 - 1
examples/js/shaders/LuminosityShader.js

@@ -37,7 +37,7 @@
 
 			vec4 texel = texture2D( tDiffuse, vUv );
 
-			float l = linearToRelativeLuminance( texel.rgb );
+			float l = luminance( texel.rgb );
 
 			gl_FragColor = vec4( l, l, l, texel.w );
 

+ 1 - 1
examples/js/shaders/ToneMapShader.js

@@ -64,7 +64,7 @@
 			#endif
 
 			// Calculate the luminance of the current pixel
-			float fLumPixel = linearToRelativeLuminance( vColor );
+			float fLumPixel = luminance( vColor );
 
 			// Apply the modified operator (Eq. 4)
 			float fLumScaled = (fLumPixel * middleGrey) / max( minLuminance, fLumAvg );

+ 1 - 1
examples/js/utils/PackedPhongMaterial.js

@@ -93,7 +93,7 @@
 					#endif
 				#endif`, THREE.ShaderChunk.morphtarget_vertex, THREE.ShaderChunk.skinning_vertex, THREE.ShaderChunk.displacementmap_vertex, THREE.ShaderChunk.project_vertex, THREE.ShaderChunk.logdepthbuf_vertex, THREE.ShaderChunk.clipping_planes_vertex, 'vViewPosition = - mvPosition.xyz;', THREE.ShaderChunk.worldpos_vertex, THREE.ShaderChunk.envmap_vertex, THREE.ShaderChunk.shadowmap_vertex, THREE.ShaderChunk.fog_vertex, '}' ].join( '\n' ); // Use the original THREE.MeshPhongMaterial's fragmentShader.
 
-			this.fragmentShader = [ '#define PHONG', 'uniform vec3 diffuse;', 'uniform vec3 emissive;', 'uniform vec3 specular;', 'uniform float shininess;', 'uniform float opacity;', THREE.ShaderChunk.common, THREE.ShaderChunk.packing, THREE.ShaderChunk.dithering_pars_fragment, THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.uv_pars_fragment, THREE.ShaderChunk.uv2_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.alphamap_pars_fragment, THREE.ShaderChunk.aomap_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.emissivemap_pars_fragment, THREE.ShaderChunk.envmap_common_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.cube_uv_reflection_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.bsdfs, THREE.ShaderChunk.lights_pars_begin, THREE.ShaderChunk.normal_pars_fragment, THREE.ShaderChunk.lights_phong_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.bumpmap_pars_fragment, THREE.ShaderChunk.normalmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, THREE.ShaderChunk.logdepthbuf_pars_fragment, THREE.ShaderChunk.clipping_planes_pars_fragment, 'void main() {', THREE.ShaderChunk.clipping_planes_fragment, 'vec4 diffuseColor = vec4( diffuse, opacity );', 'ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );', 'vec3 totalEmissiveRadiance = emissive;', THREE.ShaderChunk.logdepthbuf_fragment, THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.alphamap_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, THREE.ShaderChunk.normal_fragment_begin, THREE.ShaderChunk.normal_fragment_maps, THREE.ShaderChunk.emissivemap_fragment, // accumulation
+			this.fragmentShader = [ '#define PHONG', 'uniform vec3 diffuse;', 'uniform vec3 emissive;', 'uniform vec3 specular;', 'uniform float shininess;', 'uniform float opacity;', THREE.ShaderChunk.common, THREE.ShaderChunk.packing, THREE.ShaderChunk.dithering_pars_fragment, THREE.ShaderChunk.color_pars_fragment, THREE.ShaderChunk.uv_pars_fragment, THREE.ShaderChunk.uv2_pars_fragment, THREE.ShaderChunk.map_pars_fragment, THREE.ShaderChunk.alphamap_pars_fragment, THREE.ShaderChunk.aomap_pars_fragment, THREE.ShaderChunk.lightmap_pars_fragment, THREE.ShaderChunk.emissivemap_pars_fragment, THREE.ShaderChunk.envmap_common_pars_fragment, THREE.ShaderChunk.envmap_pars_fragment, THREE.ShaderChunk.fog_pars_fragment, THREE.ShaderChunk.bsdfs, THREE.ShaderChunk.lights_pars_begin, THREE.ShaderChunk.normal_pars_fragment, THREE.ShaderChunk.lights_phong_pars_fragment, THREE.ShaderChunk.shadowmap_pars_fragment, THREE.ShaderChunk.bumpmap_pars_fragment, THREE.ShaderChunk.normalmap_pars_fragment, THREE.ShaderChunk.specularmap_pars_fragment, THREE.ShaderChunk.logdepthbuf_pars_fragment, THREE.ShaderChunk.clipping_planes_pars_fragment, 'void main() {', THREE.ShaderChunk.clipping_planes_fragment, 'vec4 diffuseColor = vec4( diffuse, opacity );', 'ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );', 'vec3 totalEmissiveRadiance = emissive;', THREE.ShaderChunk.logdepthbuf_fragment, THREE.ShaderChunk.map_fragment, THREE.ShaderChunk.color_fragment, THREE.ShaderChunk.alphamap_fragment, THREE.ShaderChunk.alphatest_fragment, THREE.ShaderChunk.specularmap_fragment, THREE.ShaderChunk.normal_fragment_begin, THREE.ShaderChunk.normal_fragment_maps, THREE.ShaderChunk.emissivemap_fragment, // accumulation
 				THREE.ShaderChunk.lights_phong_fragment, THREE.ShaderChunk.lights_fragment_begin, THREE.ShaderChunk.lights_fragment_maps, THREE.ShaderChunk.lights_fragment_end, // modulation
 				THREE.ShaderChunk.aomap_fragment, 'vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;', THREE.ShaderChunk.envmap_fragment, 'gl_FragColor = vec4( outgoingLight, diffuseColor.a );', THREE.ShaderChunk.tonemapping_fragment, THREE.ShaderChunk.encodings_fragment, THREE.ShaderChunk.fog_fragment, THREE.ShaderChunk.premultiplied_alpha_fragment, THREE.ShaderChunk.dithering_fragment, '}' ].join( '\n' );
 			this.setValues( parameters );

+ 0 - 16
examples/js/utils/SceneUtils.js

@@ -95,25 +95,9 @@
 
 	}
 
-	function detach( child, parent, scene ) {
-
-		console.warn( 'THREE.SceneUtils: detach() has been deprecated. Use scene.attach( child ) instead.' );
-		scene.attach( child );
-
-	}
-
-	function attach( child, scene, parent ) {
-
-		console.warn( 'THREE.SceneUtils: attach() has been deprecated. Use parent.attach( child ) instead.' );
-		parent.attach( child );
-
-	}
-
 	THREE.SceneUtils = {};
-	THREE.SceneUtils.attach = attach;
 	THREE.SceneUtils.createMeshesFromInstancedMesh = createMeshesFromInstancedMesh;
 	THREE.SceneUtils.createMeshesFromMultiMaterialMesh = createMeshesFromMultiMaterialMesh;
 	THREE.SceneUtils.createMultiMaterialObject = createMultiMaterialObject;
-	THREE.SceneUtils.detach = detach;
 
 } )();