فهرست منبع

Merge branch 'dev' of https://github.com/mrdoob/three.js into dev

linbingquan 6 سال پیش
والد
کامیت
510468f6f9
47فایلهای تغییر یافته به همراه478 افزوده شده و 129 حذف شده
  1. 0 0
      build/three.js
  2. 28 28
      build/three.min.js
  3. 0 0
      build/three.module.js
  4. 1 0
      examples/files.js
  5. 50 8
      examples/js/controls/FirstPersonControls.js
  6. 11 0
      examples/js/controls/OrbitControls.js
  7. 10 5
      examples/js/exporters/ColladaExporter.js
  8. 4 4
      examples/js/exporters/GLTFExporter.js
  9. 1 1
      examples/js/loaders/ColladaLoader.js
  10. 5 4
      examples/js/loaders/GLTFLoader.js
  11. 2 2
      examples/js/postprocessing/AdaptiveToneMappingPass.js
  12. 1 1
      examples/js/postprocessing/BloomPass.js
  13. 1 1
      examples/js/postprocessing/BokehPass.js
  14. 1 1
      examples/js/postprocessing/ClearPass.js
  15. 1 1
      examples/js/postprocessing/CubeTexturePass.js
  16. 1 1
      examples/js/postprocessing/DotScreenPass.js
  17. 16 4
      examples/js/postprocessing/EffectComposer.js
  18. 2 2
      examples/js/postprocessing/FilmPass.js
  19. 1 1
      examples/js/postprocessing/GlitchPass.js
  20. 1 1
      examples/js/postprocessing/HalftonePass.js
  21. 2 2
      examples/js/postprocessing/MaskPass.js
  22. 1 1
      examples/js/postprocessing/OutlinePass.js
  23. 1 1
      examples/js/postprocessing/RenderPass.js
  24. 1 1
      examples/js/postprocessing/SAOPass.js
  25. 1 1
      examples/js/postprocessing/SMAAPass.js
  26. 1 1
      examples/js/postprocessing/SSAOPass.js
  27. 1 1
      examples/js/postprocessing/ShaderPass.js
  28. 3 3
      examples/js/postprocessing/TAARenderPass.js
  29. 1 1
      examples/js/postprocessing/TexturePass.js
  30. 1 1
      examples/js/postprocessing/UnrealBloomPass.js
  31. 179 0
      examples/webgl_furnace_test.html
  32. 3 0
      examples/webgl_nearestneighbour.html
  33. 8 4
      examples/webgl_postprocessing_fxaa.html
  34. 8 12
      examples/webgl_shadowmap.html
  35. 8 12
      examples/webgl_shadowmap_performance.html
  36. 4 8
      src/audio/Audio.js
  37. 1 0
      src/core/BufferGeometry.d.ts
  38. 2 0
      src/core/Object3D.d.ts
  39. 5 0
      src/core/Object3D.js
  40. 9 2
      src/loaders/ObjectLoader.js
  41. 2 0
      src/materials/MeshPhysicalMaterial.js
  42. 1 0
      src/math/Color.d.ts
  43. 9 0
      src/math/Vector2.d.ts
  44. 17 1
      src/math/Vector3.d.ts
  45. 40 7
      src/renderers/shaders/ShaderChunk/bsdfs.glsl.js
  46. 1 1
      src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js
  47. 31 4
      src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
build/three.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 28 - 28
build/three.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
build/three.module.js


+ 1 - 0
examples/files.js

@@ -19,6 +19,7 @@ var files = {
 		"webgl_effects_peppersghost",
 		"webgl_effects_peppersghost",
 		"webgl_effects_stereo",
 		"webgl_effects_stereo",
 		"webgl_framebuffer_texture",
 		"webgl_framebuffer_texture",
+		"webgl_furnace_test",
 		"webgl_geometries",
 		"webgl_geometries",
 		"webgl_geometries_parametric",
 		"webgl_geometries_parametric",
 		"webgl_geometry_colors",
 		"webgl_geometry_colors",

+ 50 - 8
examples/js/controls/FirstPersonControls.js

@@ -34,9 +34,6 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 	this.mouseX = 0;
 	this.mouseX = 0;
 	this.mouseY = 0;
 	this.mouseY = 0;
 
 
-	this.lat = 0;
-	this.lon = 0;
-
 	this.moveForward = false;
 	this.moveForward = false;
 	this.moveBackward = false;
 	this.moveBackward = false;
 	this.moveLeft = false;
 	this.moveLeft = false;
@@ -47,6 +44,17 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 	this.viewHalfX = 0;
 	this.viewHalfX = 0;
 	this.viewHalfY = 0;
 	this.viewHalfY = 0;
 
 
+	// private variables
+
+	var lat = 0;
+	var lon = 0;
+
+	var lookDirection = new THREE.Vector3();
+	var spherical = new THREE.Spherical();
+	var target = new THREE.Vector3();
+
+	//
+
 	if ( this.domElement !== document ) {
 	if ( this.domElement !== document ) {
 
 
 		this.domElement.setAttribute( 'tabindex', - 1 );
 		this.domElement.setAttribute( 'tabindex', - 1 );
@@ -181,6 +189,26 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 
 	};
 	};
 
 
+	this.lookAt = function ( x, y, z ) {
+
+		if ( x.isVector3 ) {
+
+			target.copy( x );
+
+		} else {
+
+			target.set( x, y, z );
+
+		}
+
+		this.object.lookAt( target );
+
+		setOrientation( this );
+
+		return this;
+
+	};
+
 	this.update = function () {
 	this.update = function () {
 
 
 		var targetPosition = new THREE.Vector3();
 		var targetPosition = new THREE.Vector3();
@@ -229,13 +257,13 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 
 			}
 			}
 
 
-			this.lon -= this.mouseX * actualLookSpeed;
-			if ( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
+			lon -= this.mouseX * actualLookSpeed;
+			if ( this.lookVertical ) lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
 
 
-			this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
+			lat = Math.max( - 85, Math.min( 85, lat ) );
 
 
-			var phi = THREE.Math.degToRad( 90 - this.lat );
-			var theta = THREE.Math.degToRad( this.lon );
+			var phi = THREE.Math.degToRad( 90 - lat );
+			var theta = THREE.Math.degToRad( lon );
 
 
 			if ( this.constrainVertical ) {
 			if ( this.constrainVertical ) {
 
 
@@ -295,6 +323,20 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 
 	}
 	}
 
 
+	function setOrientation( controls ) {
+
+		var quaternion = controls.object.quaternion;
+
+		lookDirection.set( 0, 0, - 1 ).applyQuaternion( quaternion );
+		spherical.setFromVector3( lookDirection );
+
+		lat = 90 - THREE.Math.radToDeg( spherical.phi );
+		lon = THREE.Math.radToDeg( spherical.theta );
+
+	}
+
 	this.handleResize();
 	this.handleResize();
 
 
+	setOrientation( this );
+
 };
 };

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

@@ -539,6 +539,10 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 
 		//console.log( 'handleKeyDown' );
 		//console.log( 'handleKeyDown' );
 
 
+		// prevent the browser from scrolling on cursor up/down
+
+		event.preventDefault();
+
 		switch ( event.keyCode ) {
 		switch ( event.keyCode ) {
 
 
 			case scope.keys.UP:
 			case scope.keys.UP:
@@ -673,8 +677,15 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 
 		if ( scope.enabled === false ) return;
 		if ( scope.enabled === false ) return;
 
 
+		// Prevent the browser from scrolling.
+
 		event.preventDefault();
 		event.preventDefault();
 
 
+		// Manually set the focus since calling preventDefault above
+		// prevents the browser from setting it automatically.
+
+		scope.domElement.focus ? scope.domElement.focus() : window.focus();
+
 		switch ( event.button ) {
 		switch ( event.button ) {
 
 
 			case scope.mouseButtons.LEFT:
 			case scope.mouseButtons.LEFT:

+ 10 - 5
examples/js/exporters/ColladaExporter.js

@@ -413,7 +413,7 @@ THREE.ColladaExporter.prototype = {
 
 
 					(
 					(
 						type !== 'constant' ?
 						type !== 'constant' ?
-						'<diffuse>' +
+							'<diffuse>' +
 
 
 						(
 						(
 							m.map ?
 							m.map ?
@@ -421,12 +421,12 @@ THREE.ColladaExporter.prototype = {
 								`<color sid="diffuse">${ diffuse.r } ${ diffuse.g } ${ diffuse.b } 1</color>`
 								`<color sid="diffuse">${ diffuse.r } ${ diffuse.g } ${ diffuse.b } 1</color>`
 						) +
 						) +
 						'</diffuse>'
 						'</diffuse>'
-						: ''
+							: ''
 					) +
 					) +
 
 
 					(
 					(
 						type === 'phong' ?
 						type === 'phong' ?
-						`<specular><color sid="specular">${ specular.r } ${ specular.g } ${ specular.b } 1</color></specular>` +
+							`<specular><color sid="specular">${ specular.r } ${ specular.g } ${ specular.b } 1</color></specular>` +
 
 
 						'<shininess>' +
 						'<shininess>' +
 
 
@@ -437,7 +437,7 @@ THREE.ColladaExporter.prototype = {
 						) +
 						) +
 
 
 						'</shininess>'
 						'</shininess>'
-						: ''
+							: ''
 					) +
 					) +
 
 
 					`<reflective><color>${ diffuse.r } ${ diffuse.g } ${ diffuse.b } 1</color></reflective>` +
 					`<reflective><color>${ diffuse.r } ${ diffuse.g } ${ diffuse.b } 1</color></reflective>` +
@@ -525,10 +525,15 @@ THREE.ColladaExporter.prototype = {
 				// the materials.
 				// the materials.
 				var mat = o.material || new THREE.MeshBasicMaterial();
 				var mat = o.material || new THREE.MeshBasicMaterial();
 				var materials = Array.isArray( mat ) ? mat : [ mat ];
 				var materials = Array.isArray( mat ) ? mat : [ mat ];
+
 				if ( geometry.groups.length > materials.length ) {
 				if ( geometry.groups.length > materials.length ) {
+
 					matidsArray = new Array( geometry.groups.length );
 					matidsArray = new Array( geometry.groups.length );
+
 				} else {
 				} else {
-					matidsArray = new Array( materials.length )
+
+					matidsArray = new Array( materials.length );
+
 				}
 				}
 				matids = matidsArray.fill()
 				matids = matidsArray.fill()
 					.map( ( v, i ) => processMaterial( materials[ i % materials.length ] ) );
 					.map( ( v, i ) => processMaterial( materials[ i % materials.length ] ) );

+ 4 - 4
examples/js/exporters/GLTFExporter.js

@@ -365,7 +365,7 @@ THREE.GLTFExporter.prototype = {
 		 */
 		 */
 		function applyTextureTransform( mapDef, texture ) {
 		function applyTextureTransform( mapDef, texture ) {
 
 
-			var didTransform = false
+			var didTransform = false;
 			var transformDef = {};
 			var transformDef = {};
 
 
 			if ( texture.offset.x !== 0 || texture.offset.y !== 0 ) {
 			if ( texture.offset.x !== 0 || texture.offset.y !== 0 ) {
@@ -981,7 +981,7 @@ THREE.GLTFExporter.prototype = {
 			// occlusionTexture
 			// occlusionTexture
 			if ( material.aoMap ) {
 			if ( material.aoMap ) {
 
 
-				var occlusionMapDef = { 
+				var occlusionMapDef = {
 					index: processTexture( material.aoMap ),
 					index: processTexture( material.aoMap ),
 					texCoord: 1
 					texCoord: 1
 				};
 				};
@@ -1611,7 +1611,7 @@ THREE.GLTFExporter.prototype = {
 				lightDef.type = 'spot';
 				lightDef.type = 'spot';
 				if ( light.distance > 0 ) lightDef.range = light.distance;
 				if ( light.distance > 0 ) lightDef.range = light.distance;
 				lightDef.spot = {};
 				lightDef.spot = {};
-				lightDef.spot.innerConeAngle = ( light.penumbra - 1.0 ) * light.angle * -1.0;
+				lightDef.spot.innerConeAngle = ( light.penumbra - 1.0 ) * light.angle * - 1.0;
 				lightDef.spot.outerConeAngle = light.angle;
 				lightDef.spot.outerConeAngle = light.angle;
 
 
 			}
 			}
@@ -1627,7 +1627,7 @@ THREE.GLTFExporter.prototype = {
 					&& ( light.target.parent !== light
 					&& ( light.target.parent !== light
 					 || light.target.position.x !== 0
 					 || light.target.position.x !== 0
 					 || light.target.position.y !== 0
 					 || light.target.position.y !== 0
-					 || light.target.position.z !== -1 ) ) {
+					 || light.target.position.z !== - 1 ) ) {
 
 
 				console.warn( 'THREE.GLTFExporter: Light direction may be lost. For best results, '
 				console.warn( 'THREE.GLTFExporter: Light direction may be lost. For best results, '
 					+ 'make light.target a child of the light with position 0,0,-1.' );
 					+ 'make light.target a child of the light with position 0,0,-1.' );

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

@@ -2825,7 +2825,7 @@ THREE.ColladaLoader.prototype = {
 						break;
 						break;
 
 
 					case 'mass':
 					case 'mass':
-						data.mass = parseFloats( child.textContent )[0];
+						data.mass = parseFloats( child.textContent )[ 0 ];
 						break;
 						break;
 
 
 				}
 				}

+ 5 - 4
examples/js/loaders/GLTFLoader.js

@@ -338,7 +338,7 @@ THREE.GLTFLoader = ( function () {
 
 
 			case 'directional':
 			case 'directional':
 				lightNode = new THREE.DirectionalLight( color );
 				lightNode = new THREE.DirectionalLight( color );
-				lightNode.target.position.set( 0, 0, -1 );
+				lightNode.target.position.set( 0, 0, - 1 );
 				lightNode.add( lightNode.target );
 				lightNode.add( lightNode.target );
 				break;
 				break;
 
 
@@ -356,7 +356,7 @@ THREE.GLTFLoader = ( function () {
 				lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
 				lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
 				lightNode.angle = lightDef.spot.outerConeAngle;
 				lightNode.angle = lightDef.spot.outerConeAngle;
 				lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
 				lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
-				lightNode.target.position.set( 0, 0, -1 );
+				lightNode.target.position.set( 0, 0, - 1 );
 				lightNode.add( lightNode.target );
 				lightNode.add( lightNode.target );
 				break;
 				break;
 
 
@@ -968,6 +968,7 @@ THREE.GLTFLoader = ( function () {
 					uniforms.refractionRatio.value = material.refractionRatio;
 					uniforms.refractionRatio.value = material.refractionRatio;
 
 
 					uniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;
 					uniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;
+
 				}
 				}
 
 
 				uniforms.specular.value.copy( material.specular );
 				uniforms.specular.value.copy( material.specular );
@@ -1852,7 +1853,7 @@ THREE.GLTFLoader = ( function () {
 
 
 				case 'light':
 				case 'light':
 					dependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
 					dependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
-					break
+					break;
 
 
 				default:
 				default:
 					throw new Error( 'Unknown type: ' + type );
 					throw new Error( 'Unknown type: ' + type );
@@ -3133,7 +3134,7 @@ THREE.GLTFLoader = ( function () {
 
 
 		var nodeDef = json.nodes[ nodeIndex ];
 		var nodeDef = json.nodes[ nodeIndex ];
 
 
-		return ( function() {
+		return ( function () {
 
 
 			// .isBone isn't in glTF spec. See .markDefs
 			// .isBone isn't in glTF spec. See .markDefs
 			if ( nodeDef.isBone === true ) {
 			if ( nodeDef.isBone === true ) {

+ 2 - 2
examples/js/postprocessing/AdaptiveToneMappingPass.js

@@ -130,7 +130,7 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 
 
 	constructor: THREE.AdaptiveToneMappingPass,
 	constructor: THREE.AdaptiveToneMappingPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		if ( this.needsInit ) {
 		if ( this.needsInit ) {
 
 
@@ -153,7 +153,7 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 			//Use the new luminance values, the previous luminance and the frame delta to
 			//Use the new luminance values, the previous luminance and the frame delta to
 			//adapt the luminance over time.
 			//adapt the luminance over time.
 			this.quad.material = this.materialAdaptiveLum;
 			this.quad.material = this.materialAdaptiveLum;
-			this.materialAdaptiveLum.uniforms.delta.value = delta;
+			this.materialAdaptiveLum.uniforms.delta.value = deltaTime;
 			this.materialAdaptiveLum.uniforms.lastLum.value = this.previousLuminanceRT.texture;
 			this.materialAdaptiveLum.uniforms.lastLum.value = this.previousLuminanceRT.texture;
 			this.materialAdaptiveLum.uniforms.currentLum.value = this.currentLuminanceRT.texture;
 			this.materialAdaptiveLum.uniforms.currentLum.value = this.currentLuminanceRT.texture;
 			renderer.render( this.scene, this.camera, this.luminanceRT );
 			renderer.render( this.scene, this.camera, this.luminanceRT );

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

@@ -80,7 +80,7 @@ THREE.BloomPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 
 	constructor: THREE.BloomPass,
 	constructor: THREE.BloomPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
 		if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
 
 

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

@@ -82,7 +82,7 @@ THREE.BokehPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 
 	constructor: THREE.BokehPass,
 	constructor: THREE.BokehPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		this.quad2.material = this.materialBokeh;
 		this.quad2.material = this.materialBokeh;
 
 

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

@@ -17,7 +17,7 @@ THREE.ClearPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 
 	constructor: THREE.ClearPass,
 	constructor: THREE.ClearPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		var oldClearColor, oldClearAlpha;
 		var oldClearColor, oldClearAlpha;
 
 

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

@@ -36,7 +36,7 @@ THREE.CubeTexturePass.prototype = Object.assign( Object.create( THREE.Pass.proto
 
 
 	constructor: THREE.CubeTexturePass,
 	constructor: THREE.CubeTexturePass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		var oldAutoClear = renderer.autoClear;
 		var oldAutoClear = renderer.autoClear;
 		renderer.autoClear = false;
 		renderer.autoClear = false;

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

@@ -38,7 +38,7 @@ THREE.DotScreenPass.prototype = Object.assign( Object.create( THREE.Pass.prototy
 
 
 	constructor: THREE.DotScreenPass,
 	constructor: THREE.DotScreenPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ "tSize" ].value.set( readBuffer.width, readBuffer.height );
 		this.uniforms[ "tSize" ].value.set( readBuffer.width, readBuffer.height );

+ 16 - 4
examples/js/postprocessing/EffectComposer.js

@@ -46,6 +46,8 @@ THREE.EffectComposer = function ( renderer, renderTarget ) {
 
 
 	this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
 	this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
 
 
+	this._previousFrameTime = Date.now();
+
 };
 };
 
 
 Object.assign( THREE.EffectComposer.prototype, {
 Object.assign( THREE.EffectComposer.prototype, {
@@ -73,7 +75,17 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 
 	},
 	},
 
 
-	render: function ( delta ) {
+	render: function ( deltaTime ) {
+
+		// deltaTime value is in seconds
+
+		if ( deltaTime === undefined ) {
+
+			deltaTime = ( Date.now() - this._previousFrameTime ) * 0.001;
+
+		}
+
+		this._previousFrameTime = Date.now();
 
 
 		var maskActive = false;
 		var maskActive = false;
 
 
@@ -85,7 +97,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 
 			if ( pass.enabled === false ) continue;
 			if ( pass.enabled === false ) continue;
 
 
-			pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );
+			pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );
 
 
 			if ( pass.needsSwap ) {
 			if ( pass.needsSwap ) {
 
 
@@ -95,7 +107,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 
 					context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
 					context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
 
 
-					this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );
+					this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );
 
 
 					context.stencilFunc( context.EQUAL, 1, 0xffffffff );
 					context.stencilFunc( context.EQUAL, 1, 0xffffffff );
 
 
@@ -180,7 +192,7 @@ Object.assign( THREE.Pass.prototype, {
 
 
 	setSize: function ( width, height ) {},
 	setSize: function ( width, height ) {},
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
 		console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
 
 

+ 2 - 2
examples/js/postprocessing/FilmPass.js

@@ -39,10 +39,10 @@ THREE.FilmPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ),
 
 
 	constructor: THREE.FilmPass,
 	constructor: THREE.FilmPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
-		this.uniforms[ "time" ].value += delta;
+		this.uniforms[ "time" ].value += deltaTime;
 
 
 		this.quad.material = this.material;
 		this.quad.material = this.material;
 
 

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

@@ -40,7 +40,7 @@ THREE.GlitchPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 
 	constructor: THREE.GlitchPass,
 	constructor: THREE.GlitchPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ 'seed' ].value = Math.random();//default seeding
 		this.uniforms[ 'seed' ].value = Math.random();//default seeding

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

@@ -48,7 +48,7 @@ THREE.HalftonePass = function ( width, height, params ) {
 
 
 	constructor: THREE.HalftonePass,
 	constructor: THREE.HalftonePass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
  		this.material.uniforms[ "tDiffuse" ].value = readBuffer.texture;
  		this.material.uniforms[ "tDiffuse" ].value = readBuffer.texture;
  		this.quad.material = this.material;
  		this.quad.material = this.material;

+ 2 - 2
examples/js/postprocessing/MaskPass.js

@@ -20,7 +20,7 @@ THREE.MaskPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ),
 
 
 	constructor: THREE.MaskPass,
 	constructor: THREE.MaskPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		var context = renderer.context;
 		var context = renderer.context;
 		var state = renderer.state;
 		var state = renderer.state;
@@ -88,7 +88,7 @@ THREE.ClearMaskPass.prototype = Object.create( THREE.Pass.prototype );
 
 
 Object.assign( THREE.ClearMaskPass.prototype, {
 Object.assign( THREE.ClearMaskPass.prototype, {
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		renderer.state.buffers.stencil.setTest( false );
 		renderer.state.buffers.stencil.setTest( false );
 
 

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

@@ -255,7 +255,7 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 
 	},
 	},
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		if ( this.selectedObjects.length > 0 ) {
 		if ( this.selectedObjects.length > 0 ) {
 
 

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

@@ -24,7 +24,7 @@ THREE.RenderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 
 	constructor: THREE.RenderPass,
 	constructor: THREE.RenderPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		var oldAutoClear = renderer.autoClear;
 		var oldAutoClear = renderer.autoClear;
 		renderer.autoClear = false;
 		renderer.autoClear = false;

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

@@ -178,7 +178,7 @@ THREE.SAOPass.OUTPUT = {
 THREE.SAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
 THREE.SAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), {
 	constructor: THREE.SAOPass,
 	constructor: THREE.SAOPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		// Rendering readBuffer first when rendering to screen
 		// Rendering readBuffer first when rendering to screen
 		if ( this.renderToScreen ) {
 		if ( this.renderToScreen ) {

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

@@ -120,7 +120,7 @@ THREE.SMAAPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ),
 
 
 	constructor: THREE.SMAAPass,
 	constructor: THREE.SMAAPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		// pass 1
 		// pass 1
 
 

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

@@ -173,7 +173,7 @@ THREE.SSAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ),
 
 
 	},
 	},
 
 
-	render: function ( renderer, writeBuffer /*, readBuffer, delta, maskActive */ ) {
+	render: function ( renderer, writeBuffer /*, readBuffer, deltaTime, maskActive */ ) {
 
 
 		// render beauty and depth
 		// render beauty and depth
 
 

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

@@ -42,7 +42,7 @@ THREE.ShaderPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 
 	constructor: THREE.ShaderPass,
 	constructor: THREE.ShaderPass,
 
 
-	render: function( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		if ( this.uniforms[ this.textureID ] ) {
 		if ( this.uniforms[ this.textureID ] ) {
 
 

+ 3 - 3
examples/js/postprocessing/TAARenderPass.js

@@ -33,11 +33,11 @@ THREE.TAARenderPass.prototype = Object.assign( Object.create( THREE.SSAARenderPa
 
 
 	constructor: THREE.TAARenderPass,
 	constructor: THREE.TAARenderPass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime ) {
 
 
 		if ( ! this.accumulate ) {
 		if ( ! this.accumulate ) {
 
 
-			THREE.SSAARenderPass.prototype.render.call( this, renderer, writeBuffer, readBuffer, delta );
+			THREE.SSAARenderPass.prototype.render.call( this, renderer, writeBuffer, readBuffer, deltaTime );
 
 
 			this.accumulateIndex = - 1;
 			this.accumulateIndex = - 1;
 			return;
 			return;
@@ -62,7 +62,7 @@ THREE.TAARenderPass.prototype = Object.assign( Object.create( THREE.SSAARenderPa
 
 
 		if ( this.accumulate && this.accumulateIndex === - 1 ) {
 		if ( this.accumulate && this.accumulateIndex === - 1 ) {
 
 
-			THREE.SSAARenderPass.prototype.render.call( this, renderer, this.holdRenderTarget, readBuffer, delta );
+			THREE.SSAARenderPass.prototype.render.call( this, renderer, this.holdRenderTarget, readBuffer, deltaTime );
 
 
 			this.accumulateIndex = 0;
 			this.accumulateIndex = 0;
 
 

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

@@ -41,7 +41,7 @@ THREE.TexturePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 
 	constructor: THREE.TexturePass,
 	constructor: THREE.TexturePass,
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		var oldAutoClear = renderer.autoClear;
 		var oldAutoClear = renderer.autoClear;
 		renderer.autoClear = false;
 		renderer.autoClear = false;

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

@@ -185,7 +185,7 @@ THREE.UnrealBloomPass.prototype = Object.assign( Object.create( THREE.Pass.proto
 
 
 	},
 	},
 
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 
 		this.oldClearColor.copy( renderer.getClearColor() );
 		this.oldClearColor.copy( renderer.getClearColor() );
 		this.oldClearAlpha = renderer.getClearAlpha();
 		this.oldClearAlpha = renderer.getClearAlpha();

+ 179 - 0
examples/webgl_furnace_test.html

@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js white furnace test</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				background:#777;
+				padding:0;
+				margin:0;
+				font-weight: bold;
+				overflow:hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px;
+				min-width: 60%;
+				margin: 0 20%;
+				color: #ffffff;
+				padding: 15px;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+				background-color: black;
+				color: white;
+			}
+
+			a {
+				color: #ffffff;
+			}
+		</style>
+
+		<script src="../build/three.js"></script>
+		<script src="js/WebGL.js"></script>
+		<script src="js/loaders/EquirectangularToCubeGenerator.js"></script>
+		<script src="js/pmrem/PMREMGenerator.js"></script>
+		<script src="js/pmrem/PMREMCubeUVPacker.js"></script>
+
+	</head>
+	<body>
+
+		<div id="container">
+			<div id="info">
+				<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> -
+				<a href="https://google.github.io/filament/Filament.md.html#toc4.7.2" target="_blank" rel="noopener">White Furnace</a> energy conservation test.<br />
+				There are 11 fully metal spheres with full white specular color and increasing roughness values rendered here. A metal object, no matter how rough, fully reflects all energy. If uniformly lit, the spheres should be indistinguishable from the environment. If spheres are visible, then some energy has been lost or gained after reflection.<br />
+				<a href="https://jsantell.com/" target="_blank" rel="noopener">by Jordan Santell</a><br/><br/></div>
+		</div>
+
+		<script>
+
+if ( WEBGL.isWebGLAvailable() === false ) {
+
+	document.body.appendChild( WEBGL.getWebGLErrorMessage() );
+
+}
+
+var scene, camera, renderer, envMap, radianceMap, gui;
+var right = 6;
+var config = {
+	preserveEnergy: true,
+};
+
+function init() {
+
+	var width = window.innerWidth;
+	var height = window.innerHeight;
+	var aspect = width / height;
+
+	// renderer
+
+	renderer = new THREE.WebGLRenderer( { antialias: true } );
+	renderer.setSize( width, height );
+	renderer.setPixelRatio( window.devicePixelRatio );
+	document.body.appendChild( renderer.domElement );
+
+	window.addEventListener( 'resize', onResize, false );
+
+	// scene
+
+	scene = new THREE.Scene();
+
+	// camera
+
+	camera = new THREE.OrthographicCamera( - right, right, right / aspect, - right / aspect, 1, 30 );
+	camera.position.set( 0, 0, 9 );
+
+}
+
+function createObjects() {
+
+	var geo = new THREE.SphereBufferGeometry( 0.4, 32, 32 );
+	var count = 10;
+	for ( var x = 0; x <= count; x ++ ) {
+
+		var mesh = new THREE.Mesh( geo, new THREE.MeshPhysicalMaterial( {
+			roughness: x / count,
+			metalness: 1,
+			color: 0xffffff,
+			envMap: radianceMap,
+			envMapIntensity: 1,
+			reflectivity: 1,
+		} ) );
+		mesh.position.x = x - ( Math.floor( count / 2 ) );
+		scene.add( mesh );
+
+	}
+
+}
+
+function createEnvironment() {
+
+	var color = new THREE.Color( 0xcccccc );
+	var sky = new THREE.Mesh( new THREE.SphereBufferGeometry( 1, 32, 32 ), new THREE.MeshBasicMaterial( {
+		color: color,
+		side: THREE.DoubleSide,
+	} ) );
+	sky.scale.setScalar( 100 );
+
+	var envScene = new THREE.Scene();
+	envScene.add( sky );
+	envScene.background = color;
+	var cubeCamera = new THREE.CubeCamera( 1, 100, 256, 256 );
+	cubeCamera.update( renderer, envScene );
+
+	envMap = cubeCamera.renderTarget.texture;
+
+	scene.background = color;
+
+}
+
+function getRadiance() {
+
+	return new Promise( function ( resolve, reject ) {
+
+		var pmremGenerator = new THREE.PMREMGenerator( envMap );
+		pmremGenerator.update( renderer );
+		var pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
+		pmremCubeUVPacker.update( renderer );
+		var cubeRenderTarget = pmremCubeUVPacker.CubeUVRenderTarget;
+
+		pmremGenerator.dispose();
+		pmremCubeUVPacker.dispose();
+		radianceMap = cubeRenderTarget.texture;
+		resolve();
+
+	} );
+
+}
+
+function onResize() {
+
+	var aspect = window.innerWidth / window.innerHeight;
+	camera.top = right / aspect;
+	camera.bottom = - camera.top;
+	camera.updateProjectionMatrix();
+	renderer.setSize( window.innerWidth, window.innerHeight );
+	render();
+
+}
+
+function render() {
+
+	renderer.render( scene, camera );
+
+}
+
+Promise.resolve()
+	.then( init )
+	.then( createEnvironment )
+	.then( getRadiance )
+	.then( createObjects )
+	.then( render );
+
+		</script>
+	</body>
+</html>

+ 3 - 0
examples/webgl_nearestneighbour.html

@@ -90,6 +90,9 @@
 				controls.movementSpeed = 100;
 				controls.movementSpeed = 100;
 				controls.lookSpeed = 0.1;
 				controls.lookSpeed = 0.1;
 
 
+				controls.lookAt( 500, 500, 500 );
+
+
 				// add a skybox background
 				// add a skybox background
 				var cubeTextureLoader = new THREE.CubeTextureLoader();
 				var cubeTextureLoader = new THREE.CubeTextureLoader();
 
 

+ 8 - 4
examples/webgl_postprocessing_fxaa.html

@@ -138,8 +138,10 @@
 				fxaaPass = new THREE.ShaderPass( THREE.FXAAShader );
 				fxaaPass = new THREE.ShaderPass( THREE.FXAAShader );
 				fxaaPass.renderToScreen = true;
 				fxaaPass.renderToScreen = true;
 
 
-				fxaaPass.material.uniforms[ "resolution" ].value.x = 1 / window.innerWidth;
-				fxaaPass.material.uniforms[ "resolution" ].value.y = 1 / window.innerHeight;
+				var pixelRatio = renderer.getPixelRatio();
+
+				fxaaPass.material.uniforms[ 'resolution' ].value.x = 1 / ( window.innerWidth * pixelRatio );
+				fxaaPass.material.uniforms[ 'resolution' ].value.y = 1 / ( window.innerHeight * pixelRatio );
 
 
 				composer1 = new THREE.EffectComposer( renderer );
 				composer1 = new THREE.EffectComposer( renderer );
 				composer1.addPass( renderPass );
 				composer1.addPass( renderPass );
@@ -169,8 +171,10 @@
 				composer1.setSize( window.innerWidth, window.innerHeight );
 				composer1.setSize( window.innerWidth, window.innerHeight );
 				composer2.setSize( window.innerWidth, window.innerHeight );
 				composer2.setSize( window.innerWidth, window.innerHeight );
 
 
-				fxaaPass.material.uniforms[ 'resolution' ].value.x = 1 / window.innerWidth;
-				fxaaPass.material.uniforms[ 'resolution' ].value.y = 1 / window.innerHeight;
+				var pixelRatio = renderer.getPixelRatio();
+
+				fxaaPass.material.uniforms[ 'resolution' ].value.x = 1 / ( window.innerWidth * pixelRatio );
+				fxaaPass.material.uniforms[ 'resolution' ].value.y = 1 / ( window.innerHeight * pixelRatio );
 
 
 			}
 			}
 
 

+ 8 - 12
examples/webgl_shadowmap.html

@@ -85,29 +85,25 @@
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				// SCENE CAMERA
+				// CAMERA
 
 
 				camera = new THREE.PerspectiveCamera( 23, SCREEN_WIDTH / SCREEN_HEIGHT, NEAR, FAR );
 				camera = new THREE.PerspectiveCamera( 23, SCREEN_WIDTH / SCREEN_HEIGHT, NEAR, FAR );
 				camera.position.set( 700, 50, 1900 );
 				camera.position.set( 700, 50, 1900 );
 
 
+				// SCENE
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x59472b );
+				scene.fog = new THREE.Fog( 0x59472b, 1000, FAR );
+
 				controls = new THREE.FirstPersonControls( camera );
 				controls = new THREE.FirstPersonControls( camera );
 
 
 				controls.lookSpeed = 0.0125;
 				controls.lookSpeed = 0.0125;
 				controls.movementSpeed = 500;
 				controls.movementSpeed = 500;
 				controls.noFly = false;
 				controls.noFly = false;
 				controls.lookVertical = true;
 				controls.lookVertical = true;
-				controls.constrainVertical = true;
-				controls.verticalMin = 1.5;
-				controls.verticalMax = 2.0;
 
 
-				controls.lon = 250;
-				controls.lat = 30;
-
-				// SCENE
-
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x59472b );
-				scene.fog = new THREE.Fog( 0x59472b, 1000, FAR );
+				controls.lookAt( scene.position );
 
 
 				// LIGHTS
 				// LIGHTS
 
 

+ 8 - 12
examples/webgl_shadowmap_performance.html

@@ -81,29 +81,25 @@
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				// SCENE CAMERA
+				// CAMERA
 
 
 				camera = new THREE.PerspectiveCamera( 23, SCREEN_WIDTH / SCREEN_HEIGHT, NEAR, FAR );
 				camera = new THREE.PerspectiveCamera( 23, SCREEN_WIDTH / SCREEN_HEIGHT, NEAR, FAR );
 				camera.position.set( 700, 50, 1900 );
 				camera.position.set( 700, 50, 1900 );
 
 
+				// SCENE
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x59472b );
+				scene.fog = new THREE.Fog( 0x59472b, 1000, FAR );
+
 				controls = new THREE.FirstPersonControls( camera );
 				controls = new THREE.FirstPersonControls( camera );
 
 
 				controls.lookSpeed = 0.0125;
 				controls.lookSpeed = 0.0125;
 				controls.movementSpeed = 500;
 				controls.movementSpeed = 500;
 				controls.noFly = false;
 				controls.noFly = false;
 				controls.lookVertical = true;
 				controls.lookVertical = true;
-				controls.constrainVertical = true;
-				controls.verticalMin = 1.5;
-				controls.verticalMax = 2.0;
 
 
-				controls.lon = 250;
-				controls.lat = 30;
-
-				// SCENE
-
-				scene = new THREE.Scene();
-				scene.background = new THREE.Color( 0x59472b );
-				scene.fog = new THREE.Fog( 0x59472b, 1000, FAR );
+				controls.lookAt( scene.position );
 
 
 				// LIGHTS
 				// LIGHTS
 
 

+ 4 - 8
src/audio/Audio.js

@@ -95,10 +95,8 @@ Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
 		var source = this.context.createBufferSource();
 		var source = this.context.createBufferSource();
 
 
 		source.buffer = this.buffer;
 		source.buffer = this.buffer;
-		this.setDetune( this.detune );
 		source.loop = this.loop;
 		source.loop = this.loop;
 		source.onended = this.onEnded.bind( this );
 		source.onended = this.onEnded.bind( this );
-		source.playbackRate.setValueAtTime( this.playbackRate, this.startTime );
 		this.startTime = this.context.currentTime;
 		this.startTime = this.context.currentTime;
 		source.start( this.startTime, this.offset );
 		source.start( this.startTime, this.offset );
 
 
@@ -106,6 +104,9 @@ Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 
 		this.source = source;
 		this.source = source;
 
 
+		this.setDetune( this.detune );
+		this.setPlaybackRate( this.playbackRate );
+
 		return this.connect();
 		return this.connect();
 
 
 	},
 	},
@@ -228,12 +229,7 @@ Audio.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 
 		this.detune = value;
 		this.detune = value;
 
 
-		if ( this.source.detune === undefined ) {
-
-			console.warn( 'THREE.Audio: AudioBufferSourceNode.detune not supported by the browser.' );
-			return;
-
-		}
+		if ( this.source.detune === undefined ) return; // only set detune when available
 
 
 		if ( this.isPlaying === true ) {
 		if ( this.isPlaying === true ) {
 
 

+ 1 - 0
src/core/BufferGeometry.d.ts

@@ -44,6 +44,7 @@ export class BufferGeometry extends EventDispatcher {
   boundingBox: Box3;
   boundingBox: Box3;
   boundingSphere: Sphere;
   boundingSphere: Sphere;
   drawRange: { start: number; count: number };
   drawRange: { start: number; count: number };
+  userData: {[key: string]: any};
 
 
   getIndex(): BufferAttribute;
   getIndex(): BufferAttribute;
   setIndex(index: BufferAttribute | number[]): void;
   setIndex(index: BufferAttribute | number[]): void;

+ 2 - 0
src/core/Object3D.d.ts

@@ -308,6 +308,8 @@ export class Object3D extends EventDispatcher {
    */
    */
   updateMatrixWorld(force: boolean): void;
   updateMatrixWorld(force: boolean): void;
 
 
+  updateWorldMatrix(updateParents: boolean, updateChildren: boolean): void;
+
   toJSON(meta?: {
   toJSON(meta?: {
     geometries: any;
     geometries: any;
     materials: any;
     materials: any;

+ 5 - 0
src/core/Object3D.js

@@ -6,6 +6,7 @@ import { Euler } from '../math/Euler.js';
 import { Layers } from './Layers.js';
 import { Layers } from './Layers.js';
 import { Matrix3 } from '../math/Matrix3.js';
 import { Matrix3 } from '../math/Matrix3.js';
 import { _Math } from '../math/Math.js';
 import { _Math } from '../math/Math.js';
+import { TrianglesDrawMode } from '../constants.js';
 
 
 /**
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
@@ -718,6 +719,10 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 
 		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
 		if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;
 
 
+		// object specific properties
+
+		if ( this.isMesh && this.drawMode !== TrianglesDrawMode ) object.drawMode = this.drawMode;
+
 		//
 		//
 
 
 		function serialize( library, element ) {
 		function serialize( library, element ) {

+ 9 - 2
src/loaders/ObjectLoader.js

@@ -497,8 +497,13 @@ Object.assign( ObjectLoader.prototype, {
 
 
 				} else {
 				} else {
 
 
-					materials[ data.uuid ] = loader.parse( data );
-					cache[ data.uuid ] = materials[ data.uuid ];
+					if ( cache[ data.uuid ] === undefined ) {
+
+						cache[ data.uuid ] = loader.parse( data );
+
+					}
+
+					materials[ data.uuid ] = cache[ data.uuid ];
 
 
 				}
 				}
 
 
@@ -845,6 +850,8 @@ Object.assign( ObjectLoader.prototype, {
 
 
 				}
 				}
 
 
+				if ( data.drawMode !== undefined ) object.setDrawMode( data.drawMode );
+
 				break;
 				break;
 
 
 			case 'LOD':
 			case 'LOD':

+ 2 - 0
src/materials/MeshPhysicalMaterial.js

@@ -5,6 +5,8 @@ import { MeshStandardMaterial } from './MeshStandardMaterial.js';
  *
  *
  * parameters = {
  * parameters = {
  *  reflectivity: <float>
  *  reflectivity: <float>
+ *  clearCoat: <float>
+ *  clearCoatRoughness: <float>
  * }
  * }
  */
  */
 
 

+ 1 - 0
src/math/Color.d.ts

@@ -125,4 +125,5 @@ export class Color {
   equals(color: Color): boolean;
   equals(color: Color): boolean;
   fromArray(rgb: number[], offset?: number): this;
   fromArray(rgb: number[], offset?: number): this;
   toArray(array?: number[], offset?: number): number[];
   toArray(array?: number[], offset?: number): number[];
+  toArray(xyz: ArrayLike<number>, offset?: number): ArrayLike<number>;
 }
 }

+ 9 - 0
src/math/Vector2.d.ts

@@ -401,9 +401,18 @@ export class Vector2 implements Vector {
    * Returns an array [x, y], or copies x and y into the provided array.
    * Returns an array [x, y], or copies x and y into the provided array.
    * @param array (optional) array to store the vector to. If this is not provided, a new array will be created.
    * @param array (optional) array to store the vector to. If this is not provided, a new array will be created.
    * @param offset (optional) optional offset into the array.
    * @param offset (optional) optional offset into the array.
+   * @return The created or provided array.
    */
    */
   toArray(array?: number[], offset?: number): number[];
   toArray(array?: number[], offset?: number): number[];
 
 
+  /**
+   * Copies x and y into the provided array-like.
+   * @param array array-like to store the vector to.
+   * @param offset (optional) optional offset into the array.
+   * @return The provided array-like.
+   */
+  toArray(array: ArrayLike<number>, offset?: number): ArrayLike<number>;
+
   /**
   /**
    * Sets this vector's x and y values from the attribute.
    * Sets this vector's x and y values from the attribute.
    * @param attribute the source attribute.
    * @param attribute the source attribute.

+ 17 - 1
src/math/Vector3.d.ts

@@ -112,7 +112,7 @@ export class Vector3 implements Vector {
 
 
   applyQuaternion(q: Quaternion): this;
   applyQuaternion(q: Quaternion): this;
 
 
-  project(camrea: Camera): this;
+  project(camera: Camera): this;
 
 
   unproject(camera: Camera): this;
   unproject(camera: Camera): this;
 
 
@@ -246,7 +246,23 @@ export class Vector3 implements Vector {
   equals(v: Vector3): boolean;
   equals(v: Vector3): boolean;
 
 
   fromArray(xyz: number[], offset?: number): Vector3;
   fromArray(xyz: number[], offset?: number): Vector3;
+
+  /**
+   * Returns an array [x, y, z], or copies x, y and z into the provided array.
+   * @param array (optional) array to store the vector to. If this is not provided, a new array will be created.
+   * @param offset (optional) optional offset into the array.
+   * @return The created or provided array.
+   */
   toArray(xyz?: number[], offset?: number): number[];
   toArray(xyz?: number[], offset?: number): number[];
+
+  /**
+   * Copies x, y and z into the provided array-like.
+   * @param array array-like to store the vector to.
+   * @param offset (optional) optional offset into the array.
+   * @return The provided array-like.
+   */
+  toArray(xyz: ArrayLike<number>, offset?: number): ArrayLike<number>;
+
   fromBufferAttribute(
   fromBufferAttribute(
     attribute: BufferAttribute,
     attribute: BufferAttribute,
     index: number,
     index: number,

+ 40 - 7
src/renderers/shaders/ShaderChunk/bsdfs.glsl.js

@@ -1,4 +1,22 @@
 export default /* glsl */`
 export default /* glsl */`
+
+// Analytical approximation of the DFG LUT, one half of the
+// split-sum approximation used in indirect specular lighting.
+// via 'environmentBRDF' from "Physically Based Shading on Mobile"
+// https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
+vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {
+	const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
+
+	const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );
+
+	vec4 r = roughness * c0 + c1;
+
+	float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
+
+	return vec2( -1.04, 1.04 ) * a004 + r.zw;
+
+}
+
 float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
 float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {
 
 
 #if defined ( PHYSICALLY_CORRECT_LIGHTS )
 #if defined ( PHYSICALLY_CORRECT_LIGHTS )
@@ -239,20 +257,35 @@ vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in
 
 
 	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 
 
-	const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
+	vec2 brdf = integrateSpecularBRDF( dotNV, roughness );
 
 
-	const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );
+	return specularColor * brdf.x + brdf.y;
 
 
-	vec4 r = roughness * c0 + c1;
+} // validated
 
 
-	float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
+// Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting"
+// Approximates multiscattering in order to preserve energy.
+// http://www.jcgt.org/published/0008/01/03/
+void BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {
 
 
-	vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
+	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 
 
-	return specularColor * AB.x + AB.y;
+	vec3 F = F_Schlick( specularColor, dotNV );
+	vec2 brdf = integrateSpecularBRDF( dotNV, roughness );
+	vec3 FssEss = F * brdf.x + brdf.y;
 
 
-} // validated
+	float Ess = brdf.x + brdf.y;
+	float Ems = 1.0 - Ess;
+
+	// Paper incorrect indicates coefficient is PI/21, and will
+	// be corrected to 1/21 in future updates.
+	vec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619; // 1/21
+	vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );
 
 
+	singleScatter += FssEss;
+	multiScatter += Fms * Ems;
+
+}
 
 
 float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {
 float G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {
 
 

+ 1 - 1
src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js

@@ -7,7 +7,7 @@ export default /* glsl */`
 
 
 #if defined( RE_IndirectSpecular )
 #if defined( RE_IndirectSpecular )
 
 
-	RE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );
+	RE_IndirectSpecular( radiance, irradiance, clearCoatRadiance, geometry, material, reflectedLight );
 
 
 #endif
 #endif
 `;
 `;

+ 31 - 4
src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js

@@ -96,11 +96,17 @@ void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricC
 
 
 void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
 void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
 
 
-	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
+	// Defer to the IndirectSpecular function to compute
+	// the indirectDiffuse if energy preservation is enabled.
+	#ifndef ENVMAP_TYPE_CUBE_UV
+
+		reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+	#endif
 
 
 }
 }
 
 
-void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
+void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {
 
 
 	#ifndef STANDARD
 	#ifndef STANDARD
 		float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
 		float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
@@ -110,14 +116,35 @@ void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCo
 		float clearCoatDHR = 0.0;
 		float clearCoatDHR = 0.0;
 	#endif
 	#endif
 
 
-	reflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );
+	float clearCoatInv = 1.0 - clearCoatDHR;
+
+	// Both indirect specular and diffuse light accumulate here
+	// if energy preservation enabled, and PMREM provided.
+	#if defined( ENVMAP_TYPE_CUBE_UV )
+
+		vec3 singleScattering = vec3( 0.0 );
+		vec3 multiScattering = vec3( 0.0 );
+		vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;
+
+		BRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );
+
+		vec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );
+
+		reflectedLight.indirectSpecular += clearCoatInv * radiance * singleScattering;
+		reflectedLight.indirectDiffuse += multiScattering * cosineWeightedIrradiance;
+		reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;
+
+	#else
+
+		reflectedLight.indirectSpecular += clearCoatInv * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );
+
+	#endif
 
 
 	#ifndef STANDARD
 	#ifndef STANDARD
 
 
 		reflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );
 		reflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );
 
 
 	#endif
 	#endif
-
 }
 }
 
 
 #define RE_Direct				RE_Direct_Physical
 #define RE_Direct				RE_Direct_Physical

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است