Selaa lähdekoodia

Merge pull request #11 from mrdoob/dev

merge upstream
gogoend 6 vuotta sitten
vanhempi
commit
404006e10b
100 muutettua tiedostoa jossa 2055 lisäystä ja 1336 poistoa
  1. 366 390
      build/three.js
  2. 173 306
      build/three.min.js
  3. 366 390
      build/three.module.js
  4. 0 4
      docs/list.js
  5. 0 22
      docs/manual/en/introduction/Code-style-guide.html
  6. 6 1
      docs/manual/en/introduction/How-to-run-things-locally.html
  7. 0 20
      docs/manual/en/introduction/Migration-guide.html
  8. 0 22
      docs/manual/zh/introduction/Code-style-guide.html
  9. 0 19
      docs/manual/zh/introduction/Migration-guide.html
  10. 2 1
      editor/index.html
  11. 82 0
      editor/js/Sidebar.Material.js
  12. 2 0
      editor/js/Strings.js
  13. 72 0
      editor/js/commands/SetMaterialVectorCommand.js
  14. 3 10
      editor/js/libs/ui.three.js
  15. 2 1
      editor/sw.js
  16. 2 0
      examples/files.js
  17. 1 0
      examples/js/loaders/GLTFLoader.js
  18. 4 2
      examples/js/objects/Reflector.js
  19. 4 2
      examples/js/objects/Refractor.js
  20. 4 4
      examples/js/objects/Sky.js
  21. 1 1
      examples/jsm/loaders/obj2/bridge/MtlObjBridge.d.ts
  22. 1 0
      examples/jsm/nodes/Nodes.js
  23. 6 0
      examples/jsm/nodes/core/NodeBuilder.js
  24. 43 6
      examples/jsm/nodes/materials/nodes/StandardNode.js
  25. 14 4
      examples/jsm/nodes/misc/TextureCubeNode.js
  26. 11 0
      examples/jsm/nodes/utils/SubSlot.d.ts
  27. 79 0
      examples/jsm/nodes/utils/SubSlotNode.js
  28. 4 2
      examples/jsm/objects/Reflector.js
  29. 4 2
      examples/jsm/objects/Refractor.js
  30. 4 4
      examples/jsm/objects/Sky.js
  31. BIN
      examples/textures/carbon/Carbon.png
  32. BIN
      examples/textures/carbon/Carbon_Normal.png
  33. BIN
      examples/textures/cube/angus/cube_m00_c00.jpg
  34. BIN
      examples/textures/cube/angus/cube_m00_c01.jpg
  35. BIN
      examples/textures/cube/angus/cube_m00_c02.jpg
  36. BIN
      examples/textures/cube/angus/cube_m00_c03.jpg
  37. BIN
      examples/textures/cube/angus/cube_m00_c04.jpg
  38. BIN
      examples/textures/cube/angus/cube_m00_c05.jpg
  39. BIN
      examples/textures/cube/angus/cube_m01_c00.jpg
  40. BIN
      examples/textures/cube/angus/cube_m01_c01.jpg
  41. BIN
      examples/textures/cube/angus/cube_m01_c02.jpg
  42. BIN
      examples/textures/cube/angus/cube_m01_c03.jpg
  43. BIN
      examples/textures/cube/angus/cube_m01_c04.jpg
  44. BIN
      examples/textures/cube/angus/cube_m01_c05.jpg
  45. BIN
      examples/textures/cube/angus/cube_m02_c00.jpg
  46. BIN
      examples/textures/cube/angus/cube_m02_c01.jpg
  47. BIN
      examples/textures/cube/angus/cube_m02_c02.jpg
  48. BIN
      examples/textures/cube/angus/cube_m02_c03.jpg
  49. BIN
      examples/textures/cube/angus/cube_m02_c04.jpg
  50. BIN
      examples/textures/cube/angus/cube_m02_c05.jpg
  51. BIN
      examples/textures/cube/angus/cube_m03_c00.jpg
  52. BIN
      examples/textures/cube/angus/cube_m03_c01.jpg
  53. BIN
      examples/textures/cube/angus/cube_m03_c02.jpg
  54. BIN
      examples/textures/cube/angus/cube_m03_c03.jpg
  55. BIN
      examples/textures/cube/angus/cube_m03_c04.jpg
  56. BIN
      examples/textures/cube/angus/cube_m03_c05.jpg
  57. BIN
      examples/textures/cube/angus/cube_m04_c00.jpg
  58. BIN
      examples/textures/cube/angus/cube_m04_c01.jpg
  59. BIN
      examples/textures/cube/angus/cube_m04_c02.jpg
  60. BIN
      examples/textures/cube/angus/cube_m04_c03.jpg
  61. BIN
      examples/textures/cube/angus/cube_m04_c04.jpg
  62. BIN
      examples/textures/cube/angus/cube_m04_c05.jpg
  63. BIN
      examples/textures/cube/angus/cube_m05_c00.jpg
  64. BIN
      examples/textures/cube/angus/cube_m05_c01.jpg
  65. BIN
      examples/textures/cube/angus/cube_m05_c02.jpg
  66. BIN
      examples/textures/cube/angus/cube_m05_c03.jpg
  67. BIN
      examples/textures/cube/angus/cube_m05_c04.jpg
  68. BIN
      examples/textures/cube/angus/cube_m05_c05.jpg
  69. BIN
      examples/textures/cube/angus/cube_m06_c00.jpg
  70. BIN
      examples/textures/cube/angus/cube_m06_c01.jpg
  71. BIN
      examples/textures/cube/angus/cube_m06_c02.jpg
  72. BIN
      examples/textures/cube/angus/cube_m06_c03.jpg
  73. BIN
      examples/textures/cube/angus/cube_m06_c04.jpg
  74. BIN
      examples/textures/cube/angus/cube_m06_c05.jpg
  75. BIN
      examples/textures/cube/angus/cube_m07_c00.jpg
  76. BIN
      examples/textures/cube/angus/cube_m07_c01.jpg
  77. BIN
      examples/textures/cube/angus/cube_m07_c02.jpg
  78. BIN
      examples/textures/cube/angus/cube_m07_c03.jpg
  79. BIN
      examples/textures/cube/angus/cube_m07_c04.jpg
  80. BIN
      examples/textures/cube/angus/cube_m07_c05.jpg
  81. BIN
      examples/textures/cube/angus/cube_m08_c00.jpg
  82. BIN
      examples/textures/cube/angus/cube_m08_c01.jpg
  83. BIN
      examples/textures/cube/angus/cube_m08_c02.jpg
  84. BIN
      examples/textures/cube/angus/cube_m08_c03.jpg
  85. BIN
      examples/textures/cube/angus/cube_m08_c04.jpg
  86. BIN
      examples/textures/cube/angus/cube_m08_c05.jpg
  87. BIN
      examples/textures/nvidia_tentacle/tentacle_object_space.png
  88. BIN
      examples/textures/nvidia_tentacle/tentacle_tangent_space.png
  89. 239 0
      examples/webgl_materials_clearcoat_normalmap.html
  90. 162 0
      examples/webgl_materials_cubemap_mipmaps.html
  91. 3 3
      examples/webgl_materials_envmaps_parallax.html
  92. 8 2
      examples/webgl_materials_envmaps_pmrem_nodes.html
  93. 248 7
      examples/webgl_materials_nodes.html
  94. 10 3
      examples/webgl_shadowmap_pcss.html
  95. 5 5
      src/audio/AudioContext.js
  96. 37 32
      src/audio/AudioListener.js
  97. 29 28
      src/audio/PositionalAudio.js
  98. 55 43
      src/cameras/StereoCamera.js
  99. 1 0
      src/core/BufferGeometry.d.ts
  100. 2 0
      src/core/Geometry.d.ts

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 366 - 390
build/three.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 173 - 306
build/three.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 366 - 390
build/three.module.js


+ 0 - 4
docs/list.js

@@ -14,8 +14,6 @@ var list = {
 				"Drawing lines": "manual/en/introduction/Drawing-lines",
 				"Creating text": "manual/en/introduction/Creating-text",
 				"Loading 3D models": "manual/en/introduction/Loading-3D-models",
-				"Migration guide": "manual/en/introduction/Migration-guide",
-				"Code style guide": "manual/en/introduction/Code-style-guide",
 				"FAQ": "manual/en/introduction/FAQ",
 				"Useful links": "manual/en/introduction/Useful-links"
 			},
@@ -452,8 +450,6 @@ var list = {
 				"画线": "manual/zh/introduction/Drawing-lines",
 				"创建文字": "manual/zh/introduction/Creating-text",
 				"载入3D模型": "manual/zh/introduction/Loading-3D-models",
-				"迁移指南": "manual/zh/introduction/Migration-guide",
-				"代码风格指南": "manual/zh/introduction/Code-style-guide",
 				"常见问题": "manual/zh/introduction/FAQ",
 				"一些有用的链接": "manual/zh/introduction/Useful-links"
 			},

+ 0 - 22
docs/manual/en/introduction/Code-style-guide.html

@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8">
-		<base href="../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>[name]</a></h1>
-
-		<p class="desc">
-			All code and examples in three.js are written using Mr.doob's Code Style.
-			Of course you are free to use whatever style you prefer for your own work, but
-			if you are adding code to the library or examples then you must follow this guide.<br /><br />
-
-			You can find details
-			<a href="https://github.com/mrdoob/three.js/wiki/Mr.doob%27s-Code-Style%E2%84%A2" target="_blank">here</a>.
-		</p>
-	</body>
-</html>

+ 6 - 1
docs/manual/en/introduction/How-to-run-things-locally.html

@@ -121,7 +121,12 @@ ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot =>
 					</li>
 				</ol>
 			</div>
-
+			<h3>IIS</h3>
+			<div>
+				<p>If you are using Microsoft IIS as web server. Please add a MIME type settings regarding .fbx externsion before loading.</p>
+				<code>File name externsion: fbx        MIME Type: text/plain</code>
+				<p>By default, IIS blocks .fbx, .obj files downloads. You have to configure IIS to enable these kind of files can be download.</p>
+			</div>
 			<p>
 				Other simple alternatives are [link:http://stackoverflow.com/q/12905426/24874 discussed here]
 				on Stack Overflow.

+ 0 - 20
docs/manual/en/introduction/Migration-guide.html

@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8">
-		<base href="../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>[name]</h1>
-
-		<p class="desc">
-			The migration guide is maintained on the [link:https://github.com/mrdoob/three.js/wiki wiki].
-			It contains a list of changes for each version of three.js going back to r45.<br /><br />
-
-			You can find it [link:https://github.com/mrdoob/three.js/wiki/Migration-Guide here].
-		</p>
-	</body>
-</html>

+ 0 - 22
docs/manual/zh/introduction/Code-style-guide.html

@@ -1,22 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8">
-		<base href="../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>代码风格指南([name])</a></h1>
-
-		<p class="desc">
-			在three.js中的所有文档和示例使用的是Mr.doob的代码风格。
-			当然,你也可以自由选择你更加喜欢的风格来为你工作,
-			但是,如果你希望添加代码或者添加示例到three.js的库中,你将必须遵守这个指南。
-			<br /><br />
-			有关代码风格的详细信息,请
-			<a href="https://github.com/mrdoob/three.js/wiki/Mr.doob%27s-Code-Style%E2%84%A2" target="_blank">点击此处</a>进行浏览。
-		</p>
-	</body>
-</html>

+ 0 - 19
docs/manual/zh/introduction/Migration-guide.html

@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8">
-		<base href="../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>迁移指南([name])</h1>
-		<p class="desc">
-			迁移指南保留在[link:https://github.com/mrdoob/three.js/wiki wiki]中。
-			它包含了从r45起,直到当前版本的每一个版本的更改列表。
-			<br /><br />
-			你可以在这里找到:[link:https://github.com/mrdoob/three.js/wiki/Migration-Guide here]。
-		</p>
-	</body>
-</html>

+ 2 - 1
editor/index.html

@@ -170,9 +170,10 @@
 		<script src="js/commands/RemoveScriptCommand.js"></script>
 		<script src="js/commands/SetScriptValueCommand.js"></script>
 		<script src="js/commands/SetMaterialCommand.js"></script>
-		<script src="js/commands/SetMaterialValueCommand.js"></script>
 		<script src="js/commands/SetMaterialColorCommand.js"></script>
 		<script src="js/commands/SetMaterialMapCommand.js"></script>
+		<script src="js/commands/SetMaterialValueCommand.js"></script>
+		<script src="js/commands/SetMaterialVectorCommand.js"></script>
 		<script src="js/commands/SetSceneCommand.js"></script>
 
 		<script>

+ 82 - 0
editor/js/Sidebar.Material.js

@@ -340,13 +340,33 @@ Sidebar.Material = function ( editor ) {
 	var materialNormalMapRow = new UI.Row();
 	var materialNormalMapEnabled = new UI.Checkbox( false ).onChange( update );
 	var materialNormalMap = new UI.Texture().onChange( update );
+	var materialNormalScaleX = new UI.Number( 1 ).setWidth( '30px' ).onChange( update );
+	var materialNormalScaleY = new UI.Number( 1 ).setWidth( '30px' ).onChange( update );
 
 	materialNormalMapRow.add( new UI.Text( strings.getKey( 'sidebar/material/normalmap' ) ).setWidth( '90px' ) );
 	materialNormalMapRow.add( materialNormalMapEnabled );
 	materialNormalMapRow.add( materialNormalMap );
+	materialNormalMapRow.add( materialNormalScaleX );
+	materialNormalMapRow.add( materialNormalScaleY );
 
 	container.add( materialNormalMapRow );
 
+	// clearcoat normal map
+
+	var materialClearCoatNormalMapRow = new UI.Row();
+	var materialClearCoatNormalMapEnabled = new UI.Checkbox( false ).onChange( update );
+	var materialClearCoatNormalMap = new UI.Texture().onChange( update );
+	var materialClearCoatNormalScaleX = new UI.Number( 1 ).setWidth( '30px' ).onChange( update );
+	var materialClearCoatNormalScaleY = new UI.Number( 1 ).setWidth( '30px' ).onChange( update );
+
+	materialClearCoatNormalMapRow.add( new UI.Text( strings.getKey( 'sidebar/material/clearcoatnormalmap' ) ).setWidth( '90px' ) );
+	materialClearCoatNormalMapRow.add( materialClearCoatNormalMapEnabled );
+	materialClearCoatNormalMapRow.add( materialClearCoatNormalMap );
+	materialClearCoatNormalMapRow.add( materialClearCoatNormalScaleX );
+	materialClearCoatNormalMapRow.add( materialClearCoatNormalScaleY );
+
+	container.add( materialClearCoatNormalMapRow );
+
 	// displacement map
 
 	var materialDisplacementMapRow = new UI.Row();
@@ -778,6 +798,17 @@ Sidebar.Material = function ( editor ) {
 
 					}
 
+					if ( material.normalScale.x !== materialNormalScaleX.getValue() ||
+						material.normalScale.y !== materialNormalScaleY.getValue() ) {
+
+						var value = [
+							materialNormalScaleX.getValue(),
+							materialNormalScaleY.getValue()
+						];
+						editor.execute( new SetMaterialVectorCommand( editor, currentObject, 'normalScale', value, currentMaterialSlot ) );
+
+					}
+
 				} else {
 
 					if ( normalMapEnabled ) textureWarning = true;
@@ -786,6 +817,39 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.clearCoatNormalMap !== undefined ) {
+
+				var clearCoatNormalMapEnabled = materialClearCoatNormalMapEnabled.getValue() === true;
+
+				if ( objectHasUvs ) {
+
+					var clearCoatNormalMap = clearCoatNormalMapEnabled ? materialClearCoatNormalMap.getValue() : null;
+
+					if ( material.clearCoatNormalMap !== clearCoatNormalMap ) {
+
+						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'clearCoatNormalMap', clearCoatNormalMap, currentMaterialSlot ) );
+
+					}
+
+					if ( material.clearCoatNormalScale.x !== materialClearCoatNormalScaleX.getValue() ||
+						material.clearCoatNormalScale.y !== materialClearCoatNormalScaleY.getValue() ) {
+
+						var value = [
+							materialClearCoatNormalScaleX.getValue(),
+							materialClearCoatNormalScaleY.getValue()
+						];
+						editor.execute( new SetMaterialVectorCommand( editor, currentObject, 'clearCoatNormalScale', value, currentMaterialSlot ) );
+
+					}
+
+				} else {
+
+					if ( clearCoatNormalMapEnabled ) textureWarning = true;
+
+				}
+
+			}
+
 			if ( material.displacementMap !== undefined ) {
 
 				var displacementMapEnabled = materialDisplacementMapEnabled.getValue() === true;
@@ -1313,6 +1377,24 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			materialNormalScaleX.setValue( material.normalScale.x );
+			materialNormalScaleY.setValue( material.normalScale.y );
+
+		}
+
+		if ( material.clearCoatNormalMap !== undefined ) {
+
+			materialClearCoatNormalMapEnabled.setValue( material.clearCoatNormalMap !== null );
+
+			if ( material.clearCoatNormalMap !== null || resetTextureSelectors ) {
+
+				materialClearCoatNormalMap.setValue( material.clearCoatNormalMap );
+
+			}
+
+			materialClearCoatNormalScaleX.setValue( material.clearCoatNormalScale.x );
+			materialClearCoatNormalScaleY.setValue( material.clearCoatNormalScale.y );
+
 		}
 
 		if ( material.displacementMap !== undefined ) {

+ 2 - 0
editor/js/Strings.js

@@ -236,6 +236,7 @@ var Strings = function ( config ) {
 			'sidebar/material/alphamap': 'Alpha Map',
 			'sidebar/material/bumpmap': 'Bump Map',
 			'sidebar/material/normalmap': 'Normal Map',
+			'sidebar/material/clearcoatnormalmap': 'ClearCoat Normal Map',
 			'sidebar/material/displacemap': 'Displace Map',
 			'sidebar/material/roughmap': 'Rough. Map',
 			'sidebar/material/metalmap': 'Metal. Map',
@@ -507,6 +508,7 @@ var Strings = function ( config ) {
 			'sidebar/material/alphamap': '透明贴图',
 			'sidebar/material/bumpmap': '凹凸贴图',
 			'sidebar/material/normalmap': '法线贴图',
+			'sidebar/material/clearcoatnormalmap': 'ClearCoat Normal Map',
 			'sidebar/material/displacemap': '置换贴图',
 			'sidebar/material/roughmap': '粗糙贴图',
 			'sidebar/material/metalmap': '金属贴图',

+ 72 - 0
editor/js/commands/SetMaterialVectorCommand.js

@@ -0,0 +1,72 @@
+/**
+ * @author dforrer / https://github.com/dforrer
+ * Developed as part of a project at University of Applied Sciences and Arts Northwestern Switzerland (www.fhnw.ch)
+ */
+
+var SetMaterialVectorCommand = function ( editor, object, attributeName, newValue, materialSlot ) {
+
+	Command.call( this, editor );
+
+	this.type = 'SetMaterialColorCommand';
+	this.name = 'Set Material.' + attributeName;
+	this.updatable = true;
+
+	this.object = object;
+	this.material = this.editor.getObjectMaterial( object, materialSlot );
+
+	this.oldValue = ( this.material !== undefined ) ? this.material[ attributeName ].toArray() : undefined;
+	this.newValue = newValue;
+
+	this.attributeName = attributeName;
+
+};
+
+SetMaterialVectorCommand.prototype = {
+
+	execute: function () {
+
+		this.material[ this.attributeName ].fromArray( this.newValue );
+
+		this.editor.signals.materialChanged.dispatch( this.material );
+
+	},
+
+	undo: function () {
+
+		this.material[ this.attributeName ].fromArray( this.oldValue );
+
+		this.editor.signals.materialChanged.dispatch( this.material );
+
+	},
+
+	update: function ( cmd ) {
+
+		this.newValue = cmd.newValue;
+
+	},
+
+	toJSON: function () {
+
+		var output = Command.prototype.toJSON.call( this );
+
+		output.objectUuid = this.object.uuid;
+		output.attributeName = this.attributeName;
+		output.oldValue = this.oldValue;
+		output.newValue = this.newValue;
+
+		return output;
+
+	},
+
+	fromJSON: function ( json ) {
+
+		Command.prototype.fromJSON.call( this, json );
+
+		this.object = this.editor.objectByUuid( json.objectUuid );
+		this.attributeName = json.attributeName;
+		this.oldValue = json.oldValue;
+		this.newValue = json.newValue;
+
+	}
+
+};

+ 3 - 10
editor/js/libs/ui.three.js

@@ -41,12 +41,6 @@ UI.Texture = function ( mapping ) {
 	}, false );
 	dom.appendChild( canvas );
 
-	var name = document.createElement( 'input' );
-	name.disabled = true;
-	name.style.width = '64px';
-	name.style.border = '1px solid #ccc';
-	dom.appendChild( name );
-
 	function loadFile( file ) {
 
 		if ( file.type.match( 'image.*' ) ) {
@@ -122,7 +116,6 @@ UI.Texture.prototype.getValue = function () {
 UI.Texture.prototype.setValue = function ( texture ) {
 
 	var canvas = this.dom.children[ 0 ];
-	var name = this.dom.children[ 1 ];
 	var context = canvas.getContext( '2d' );
 
 	if ( texture !== null ) {
@@ -131,21 +124,21 @@ UI.Texture.prototype.setValue = function ( texture ) {
 
 		if ( image !== undefined && image.width > 0 ) {
 
-			name.value = texture.sourceFile;
+			canvas.title = texture.sourceFile;
 
 			var scale = canvas.width / image.width;
 			context.drawImage( image, 0, 0, image.width * scale, image.height * scale );
 
 		} else {
 
-			name.value = texture.sourceFile + ' (error)';
+			canvas.title = texture.sourceFile + ' (error)';
 			context.clearRect( 0, 0, canvas.width, canvas.height );
 
 		}
 
 	} else {
 
-		name.value = '';
+		canvas.title = 'empty';
 
 		if ( context !== null ) {
 

+ 2 - 1
editor/sw.js

@@ -169,9 +169,10 @@ const staticAssets = [
 	'./js/commands/RemoveScriptCommand.js',
 	'./js/commands/SetScriptValueCommand.js',
 	'./js/commands/SetMaterialCommand.js',
-	'./js/commands/SetMaterialValueCommand.js',
 	'./js/commands/SetMaterialColorCommand.js',
 	'./js/commands/SetMaterialMapCommand.js',
+	'./js/commands/SetMaterialValueCommand.js',
+	'./js/commands/SetMaterialVectorCommand.js',
 	'./js/commands/SetSceneCommand.js',
 
 	//

+ 2 - 0
examples/files.js

@@ -147,12 +147,14 @@ var files = {
 		"webgl_materials_bumpmap_skin",
 		"webgl_materials_cars",
 		"webgl_materials_channels",
+		"webgl_materials_clearcoat_normalmap",
 		"webgl_materials_compile",
 		"webgl_materials_cubemap",
 		"webgl_materials_cubemap_balls_reflection",
 		"webgl_materials_cubemap_balls_refraction",
 		"webgl_materials_cubemap_dynamic",
 		"webgl_materials_cubemap_refraction",
+		"webgl_materials_cubemap_mipmaps",
 		"webgl_materials_curvature",
 		"webgl_materials_displacementmap",
 		"webgl_materials_envmaps",

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

@@ -2140,6 +2140,7 @@ THREE.GLTFLoader = ( function () {
 				pointsMaterial.color.copy( material.color );
 				pointsMaterial.map = material.map;
 				pointsMaterial.lights = false; // PointsMaterial doesn't support lights yet
+				pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
 
 				this.cache.add( cacheKey, pointsMaterial );
 

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

@@ -170,9 +170,11 @@ THREE.Reflector = function ( geometry, options ) {
 
 		// Restore viewport
 
-		if ( camera.isArrayCamera ) {
+		var viewport = camera.viewport;
 
-			renderer.state.viewport( camera.viewport );
+		if ( viewport !== undefined ) {
+
+			renderer.state.viewport( viewport );
 
 		}
 

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

@@ -205,9 +205,11 @@ THREE.Refractor = function ( geometry, options ) {
 
 		// restore viewport
 
-		if ( camera.isArrayCamera ) {
+		var viewport = camera.viewport;
 
-			renderer.state.viewport( camera.viewport );
+		if ( viewport !== undefined ) {
+
+			renderer.state.viewport( viewport );
 
 		}
 

+ 4 - 4
examples/js/objects/Sky.js

@@ -39,7 +39,8 @@ THREE.Sky.SkyShader = {
 		"rayleigh": { value: 1 },
 		"mieCoefficient": { value: 0.005 },
 		"mieDirectionalG": { value: 0.8 },
-		"sunPosition": { value: new THREE.Vector3() }
+		"sunPosition": { value: new THREE.Vector3() },
+		"up": { value: new THREE.Vector3( 0, 1, 0 ) }
 	},
 
 	vertexShader: [
@@ -47,6 +48,7 @@ THREE.Sky.SkyShader = {
 		'uniform float rayleigh;',
 		'uniform float turbidity;',
 		'uniform float mieCoefficient;',
+		'uniform vec3 up;',
 
 		'varying vec3 vWorldPosition;',
 		'varying vec3 vSunDirection;',
@@ -55,8 +57,6 @@ THREE.Sky.SkyShader = {
 		'varying vec3 vBetaM;',
 		'varying float vSunE;',
 
-		'const vec3 up = vec3( 0.0, 1.0, 0.0 );',
-
 		// constants for atmospheric scattering
 		'const float e = 2.71828182845904523536028747135266249775724709369995957;',
 		'const float pi = 3.141592653589793238462643383279502884197169;',
@@ -126,6 +126,7 @@ THREE.Sky.SkyShader = {
 
 		'uniform float luminance;',
 		'uniform float mieDirectionalG;',
+		'uniform vec3 up;',
 
 		'const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );',
 
@@ -138,7 +139,6 @@ THREE.Sky.SkyShader = {
 		// optical length at zenith for molecules
 		'const float rayleighZenithLength = 8.4E3;',
 		'const float mieZenithLength = 1.25E3;',
-		'const vec3 up = vec3( 0.0, 1.0, 0.0 );',
 		// 66 arc seconds -> degrees, and the cosine of that
 		'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;',
 

+ 1 - 1
examples/jsm/loaders/obj2/bridge/MtlObjBridge.d.ts

@@ -4,5 +4,5 @@ import {
 
 export namespace MtlObjBridge {
   export function link(processResult: object, assetLoader: object): void;
-  export function addMaterialsFromMtlLoader(materialCreator: MaterialCreator): void;
+  export function addMaterialsFromMtlLoader(materialCreator: MaterialCreator): object;
 }

+ 1 - 0
examples/jsm/nodes/Nodes.js

@@ -82,6 +82,7 @@ export { VelocityNode } from './utils/VelocityNode.js';
 export { UVTransformNode } from './utils/UVTransformNode.js';
 export { MaxMIPLevelNode } from './utils/MaxMIPLevelNode.js';
 export { ColorSpaceNode } from './utils/ColorSpaceNode.js';
+export { SubSlotNode } from './utils/SubSlotNode.js';
 
 // effects
 

+ 6 - 0
examples/jsm/nodes/core/NodeBuilder.js

@@ -449,6 +449,12 @@ NodeBuilder.prototype = {
 
 	},
 
+	require: function ( name ) {
+
+		this.requires[ name ] = true;
+
+	},
+
 	isDefined: function ( name ) {
 
 		return this.defines[ name ] !== undefined;

+ 43 - 6
examples/jsm/nodes/materials/nodes/StandardNode.js

@@ -20,6 +20,8 @@ function StandardNode() {
 	this.roughness = new FloatNode( 0.5 );
 	this.metalness = new FloatNode( 0.5 );
 
+	this.energyPreservation = true;
+
 }
 
 StandardNode.prototype = Object.create( Node.prototype );
@@ -32,6 +34,8 @@ StandardNode.prototype.build = function ( builder ) {
 
 	builder.define( this.clearCoat || this.clearCoatRoughness ? 'PHYSICAL' : 'STANDARD' );
 
+	if ( this.energyPreservation ) builder.define( 'ENERGY_PRESERVATION' );
+
 	builder.requires.lights = true;
 
 	builder.extensions.shaderTextureLOD = true;
@@ -153,7 +157,20 @@ StandardNode.prototype.build = function ( builder ) {
 		if ( this.shadow ) this.shadow.analyze( builder );
 		if ( this.emissive ) this.emissive.analyze( builder, { slot: 'emissive' } );
 
-		if ( this.environment ) this.environment.analyze( builder, { cache: 'env', context: contextEnvironment, slot: 'environment' } ); // isolate environment from others inputs ( see TextureNode, CubeTextureNode )
+		if ( this.environment ) {
+
+			// isolate environment from others inputs ( see TextureNode, CubeTextureNode )
+			// environment.analyze will detect if there is a need of calculate irradiance
+
+			this.environment.analyze( builder, { cache: 'radiance', context: contextEnvironment, slot: 'radiance' } ); 
+
+			if ( builder.requires.irradiance ) {
+
+				this.environment.analyze( builder, { cache: 'irradiance', context: contextEnvironment, slot: 'irradiance' } ); 
+
+			}
+
+		}
 
 		// build code
 
@@ -179,7 +196,21 @@ StandardNode.prototype.build = function ( builder ) {
 		var shadow = this.shadow ? this.shadow.flow( builder, 'c' ) : undefined;
 		var emissive = this.emissive ? this.emissive.flow( builder, 'c', { slot: 'emissive' } ) : undefined;
 
-		var environment = this.environment ? this.environment.flow( builder, 'c', { cache: 'env', context: contextEnvironment, slot: 'environment' } ) : undefined;
+		var environment;
+
+		if ( this.environment ) {
+
+			environment = {
+				radiance: this.environment.flow( builder, 'c', { cache: 'radiance', context: contextEnvironment, slot: 'radiance' } )
+			};
+
+			if ( builder.requires.irradiance ) {
+
+				environment.irradiance = this.environment.flow( builder, 'c', { cache: 'irradiance', context: contextEnvironment, slot: 'irradiance' } );
+
+			}
+
+		}
 
 		var clearCoatEnv = useClearCoat && environment ? this.environment.flow( builder, 'c', { cache: 'clearCoat', context: contextEnvironment, slot: 'environment' } ) : undefined;
 
@@ -371,7 +402,13 @@ StandardNode.prototype.build = function ( builder ) {
 
 		if ( environment ) {
 
-			output.push( environment.code );
+			output.push( environment.radiance.code );
+
+			if ( builder.requires.irradiance ) {
+
+				output.push( environment.irradiance.code );
+
+			}
 
 			if ( clearCoatEnv ) {
 
@@ -382,11 +419,11 @@ StandardNode.prototype.build = function ( builder ) {
 
 			}
 
-			output.push( "radiance += " + environment.result + ";" );
+			output.push( "radiance += " + environment.radiance.result + ";" );
 
-			if ( environment.extra.irradiance ) {
+			if ( builder.requires.irradiance ) {
 
-				output.push( "irradiance += PI * " + environment.extra.irradiance + ";" );
+				output.push( "irradiance += PI * " + environment.irradiance.result + ";" );
 
 			}
 

+ 14 - 4
examples/jsm/nodes/misc/TextureCubeNode.js

@@ -79,12 +79,12 @@ TextureCubeNode.prototype.generate = function ( builder, output ) {
 
 	if ( builder.isShader( 'fragment' ) ) {
 
-		var radiance = this.generateTextureCubeUV( builder, this.radianceCache );
-		var irradiance = this.generateTextureCubeUV( builder, this.irradianceCache );
+		builder.require( 'irradiance' );
 
-		builder.context.extra.irradiance = irradiance;
+		var cache = builder.slot === 'irradiance' ? this.irradianceCache : this.radianceCache;
+		var result = this.generateTextureCubeUV( builder, cache );
 
-		return builder.format( 'vec4( ' + radiance + ', 1.0 )', this.getType( builder ), output );
+		return builder.format( 'vec4( ' + result + ', 1.0 )', this.getType( builder ), output );
 
 	} else {
 
@@ -96,6 +96,16 @@ TextureCubeNode.prototype.generate = function ( builder, output ) {
 
 };
 
+TextureCubeNode.prototype.copy = function ( source ) {
+
+	TempNode.prototype.copy.call( this, source );
+
+	this.value = source.value;
+
+	return this;
+
+};
+
 TextureCubeNode.prototype.toJSON = function ( meta ) {
 
 	var data = this.getJSONNode( meta );

+ 11 - 0
examples/jsm/nodes/utils/SubSlot.d.ts

@@ -0,0 +1,11 @@
+import { TempNode } from '../core/TempNode';
+import { NodeBuilder } from '../core/NodeBuilder';
+
+export class SubSlots extends TempNode {
+  constructor(slots?: object);
+
+  slots: Node[];
+
+  generate(builder: NodeBuilder, output: string): string;
+  copy(source: SubSlots): this;
+}

+ 79 - 0
examples/jsm/nodes/utils/SubSlotNode.js

@@ -0,0 +1,79 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { TempNode } from '../core/TempNode.js';
+
+function SubSlotNode( slots ) {
+
+	TempNode.call( this );
+
+	this.slots = slots || {};
+
+}
+
+SubSlotNode.prototype = Object.create( TempNode.prototype );
+SubSlotNode.prototype.constructor = SubSlotNode;
+SubSlotNode.prototype.nodeType = "SubSlot";
+
+SubSlotNode.prototype.getType = function ( builder, output ) {
+
+	return output;
+
+};
+
+SubSlotNode.prototype.generate = function ( builder, output ) {
+
+	if ( this.slots[ builder.slot ] ) {
+
+		return this.slots[ builder.slot ].build( builder, output )
+
+	}
+
+	return builder.format( '0.0', 'f', output );
+
+};
+
+SubSlotNode.prototype.copy = function ( source ) {
+
+	TempNode.prototype.copy.call( this, source );
+
+	for ( var prop in source.slots ) {
+
+		this.slots[ prop ] = source.slots[ prop ];
+
+	}
+
+	return this;
+
+};
+
+SubSlotNode.prototype.toJSON = function ( meta ) {
+
+	var data = this.getJSONNode( meta );
+
+	if ( ! data ) {
+
+		data = this.createJSONNode( meta );
+
+		data.slots = {};
+
+		for ( var prop in this.slots ) {
+
+			var slot = this.slots[ prop ];
+
+			if ( slot ) {
+
+				data.slots[ prop ] = slot.toJSON( meta ).uuid;
+
+			}
+
+		}
+
+	}
+
+	return data;
+
+};
+
+export { SubSlotNode };

+ 4 - 2
examples/jsm/objects/Reflector.js

@@ -186,9 +186,11 @@ var Reflector = function ( geometry, options ) {
 
 		// Restore viewport
 
-		if ( camera.isArrayCamera ) {
+		var viewport = camera.viewport;
 
-			renderer.state.viewport( camera.viewport );
+		if ( viewport !== undefined ) {
+
+			renderer.state.viewport( viewport );
 
 		}
 

+ 4 - 2
examples/jsm/objects/Refractor.js

@@ -222,9 +222,11 @@ var Refractor = function ( geometry, options ) {
 
 		// restore viewport
 
-		if ( camera.isArrayCamera ) {
+		var viewport = camera.viewport;
 
-			renderer.state.viewport( camera.viewport );
+		if ( viewport !== undefined ) {
+
+			renderer.state.viewport( viewport );
 
 		}
 

+ 4 - 4
examples/jsm/objects/Sky.js

@@ -48,7 +48,8 @@ Sky.SkyShader = {
 		"rayleigh": { value: 1 },
 		"mieCoefficient": { value: 0.005 },
 		"mieDirectionalG": { value: 0.8 },
-		"sunPosition": { value: new Vector3() }
+		"sunPosition": { value: new Vector3() },
+		"up": { value: new Vector3( 0, 1, 0 ) }
 	},
 
 	vertexShader: [
@@ -56,6 +57,7 @@ Sky.SkyShader = {
 		'uniform float rayleigh;',
 		'uniform float turbidity;',
 		'uniform float mieCoefficient;',
+		'uniform vec3 up;',
 
 		'varying vec3 vWorldPosition;',
 		'varying vec3 vSunDirection;',
@@ -64,8 +66,6 @@ Sky.SkyShader = {
 		'varying vec3 vBetaM;',
 		'varying float vSunE;',
 
-		'const vec3 up = vec3( 0.0, 1.0, 0.0 );',
-
 		// constants for atmospheric scattering
 		'const float e = 2.71828182845904523536028747135266249775724709369995957;',
 		'const float pi = 3.141592653589793238462643383279502884197169;',
@@ -135,6 +135,7 @@ Sky.SkyShader = {
 
 		'uniform float luminance;',
 		'uniform float mieDirectionalG;',
+		'uniform vec3 up;',
 
 		'const vec3 cameraPos = vec3( 0.0, 0.0, 0.0 );',
 
@@ -147,7 +148,6 @@ Sky.SkyShader = {
 		// optical length at zenith for molecules
 		'const float rayleighZenithLength = 8.4E3;',
 		'const float mieZenithLength = 1.25E3;',
-		'const vec3 up = vec3( 0.0, 1.0, 0.0 );',
 		// 66 arc seconds -> degrees, and the cosine of that
 		'const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;',
 

BIN
examples/textures/carbon/Carbon.png


BIN
examples/textures/carbon/Carbon_Normal.png


BIN
examples/textures/cube/angus/cube_m00_c00.jpg


BIN
examples/textures/cube/angus/cube_m00_c01.jpg


BIN
examples/textures/cube/angus/cube_m00_c02.jpg


BIN
examples/textures/cube/angus/cube_m00_c03.jpg


BIN
examples/textures/cube/angus/cube_m00_c04.jpg


BIN
examples/textures/cube/angus/cube_m00_c05.jpg


BIN
examples/textures/cube/angus/cube_m01_c00.jpg


BIN
examples/textures/cube/angus/cube_m01_c01.jpg


BIN
examples/textures/cube/angus/cube_m01_c02.jpg


BIN
examples/textures/cube/angus/cube_m01_c03.jpg


BIN
examples/textures/cube/angus/cube_m01_c04.jpg


BIN
examples/textures/cube/angus/cube_m01_c05.jpg


BIN
examples/textures/cube/angus/cube_m02_c00.jpg


BIN
examples/textures/cube/angus/cube_m02_c01.jpg


BIN
examples/textures/cube/angus/cube_m02_c02.jpg


BIN
examples/textures/cube/angus/cube_m02_c03.jpg


BIN
examples/textures/cube/angus/cube_m02_c04.jpg


BIN
examples/textures/cube/angus/cube_m02_c05.jpg


BIN
examples/textures/cube/angus/cube_m03_c00.jpg


BIN
examples/textures/cube/angus/cube_m03_c01.jpg


BIN
examples/textures/cube/angus/cube_m03_c02.jpg


BIN
examples/textures/cube/angus/cube_m03_c03.jpg


BIN
examples/textures/cube/angus/cube_m03_c04.jpg


BIN
examples/textures/cube/angus/cube_m03_c05.jpg


BIN
examples/textures/cube/angus/cube_m04_c00.jpg


BIN
examples/textures/cube/angus/cube_m04_c01.jpg


BIN
examples/textures/cube/angus/cube_m04_c02.jpg


BIN
examples/textures/cube/angus/cube_m04_c03.jpg


BIN
examples/textures/cube/angus/cube_m04_c04.jpg


BIN
examples/textures/cube/angus/cube_m04_c05.jpg


BIN
examples/textures/cube/angus/cube_m05_c00.jpg


BIN
examples/textures/cube/angus/cube_m05_c01.jpg


BIN
examples/textures/cube/angus/cube_m05_c02.jpg


BIN
examples/textures/cube/angus/cube_m05_c03.jpg


BIN
examples/textures/cube/angus/cube_m05_c04.jpg


BIN
examples/textures/cube/angus/cube_m05_c05.jpg


BIN
examples/textures/cube/angus/cube_m06_c00.jpg


BIN
examples/textures/cube/angus/cube_m06_c01.jpg


BIN
examples/textures/cube/angus/cube_m06_c02.jpg


BIN
examples/textures/cube/angus/cube_m06_c03.jpg


BIN
examples/textures/cube/angus/cube_m06_c04.jpg


BIN
examples/textures/cube/angus/cube_m06_c05.jpg


BIN
examples/textures/cube/angus/cube_m07_c00.jpg


BIN
examples/textures/cube/angus/cube_m07_c01.jpg


BIN
examples/textures/cube/angus/cube_m07_c02.jpg


BIN
examples/textures/cube/angus/cube_m07_c03.jpg


BIN
examples/textures/cube/angus/cube_m07_c04.jpg


BIN
examples/textures/cube/angus/cube_m07_c05.jpg


BIN
examples/textures/cube/angus/cube_m08_c00.jpg


BIN
examples/textures/cube/angus/cube_m08_c01.jpg


BIN
examples/textures/cube/angus/cube_m08_c02.jpg


BIN
examples/textures/cube/angus/cube_m08_c03.jpg


BIN
examples/textures/cube/angus/cube_m08_c04.jpg


BIN
examples/textures/cube/angus/cube_m08_c05.jpg


BIN
examples/textures/nvidia_tentacle/tentacle_object_space.png


BIN
examples/textures/nvidia_tentacle/tentacle_tangent_space.png


+ 239 - 0
examples/webgl_materials_clearcoat_normalmap.html

@@ -0,0 +1,239 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<title>three.js webgl - materials - clearcoat normal</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<link type="text/css" rel="stylesheet" href="main.css">
+	<style>
+		#vt {
+			display: none
+		}
+
+		#vt,
+		#vt a {
+			color: orange;
+		}
+	</style>
+</head>
+
+<body>
+	<div id="info">
+		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl - materials - clearcoat normal map<br />
+	</div>
+
+	<script type="module">
+
+		import * as THREE from '../build/three.module.js';
+
+		import Stats from './jsm/libs/stats.module.js';
+
+		import { OrbitControls } from './jsm/controls/OrbitControls.js';
+		import { HDRCubeTextureLoader } from './jsm/loaders/HDRCubeTextureLoader.js';
+		import { PMREMGenerator } from './jsm/pmrem/PMREMGenerator.js';
+		import { PMREMCubeUVPacker } from './jsm/pmrem/PMREMCubeUVPacker.js';
+
+		var container, stats;
+
+		var camera, scene, renderer;
+
+		var particleLight;
+		var group;
+
+		init();
+		animate();
+
+		function init() {
+
+			container = document.createElement( 'div' );
+			document.body.appendChild( container );
+
+			camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 10000 );
+			camera.position.z = 1000;
+
+			scene = new THREE.Scene();
+
+			group = new THREE.Group();
+			scene.add( group );
+
+			new HDRCubeTextureLoader()
+				.setDataType( THREE.UnsignedByteType )
+				.setPath( './textures/cube/pisaHDR/' )
+				.load( [ 'px.hdr', 'nx.hdr', 'py.hdr', 'ny.hdr', 'pz.hdr', 'nz.hdr' ],
+					function ( hdrCubeMap ) {
+
+						var pmremGenerator = new PMREMGenerator( hdrCubeMap );
+						pmremGenerator.update( renderer );
+
+						var pmremCubeUVPacker = new PMREMCubeUVPacker( pmremGenerator.cubeLods );
+						pmremCubeUVPacker.update( renderer );
+
+						var hdrCubeRenderTarget = pmremCubeUVPacker.CubeUVRenderTarget;
+
+						var geometry = new THREE.SphereBufferGeometry( 80, 64, 32 );
+
+						var textureLoader = new THREE.TextureLoader();
+
+						var diffuse = textureLoader.load( "textures/carbon/Carbon.png" );
+						diffuse.wrapS = THREE.RepeatWrapping;
+						diffuse.wrapT = THREE.RepeatWrapping;
+						diffuse.repeat.x = 10;
+						diffuse.repeat.y = 10;
+
+						var normalMap = textureLoader.load( "textures/carbon/Carbon_Normal.png" );
+						normalMap.wrapS = THREE.RepeatWrapping;
+						normalMap.wrapT = THREE.RepeatWrapping;
+
+						var clearCoatNormaMap = textureLoader.load( "textures/waternormals.jpg" );
+						clearCoatNormaMap.wrapS = THREE.RepeatWrapping;
+						clearCoatNormaMap.wrapT = THREE.RepeatWrapping;
+
+						//
+
+						var material = new THREE.MeshPhysicalMaterial( {
+							clearCoat: 1.0,
+							envMap: hdrCubeRenderTarget.texture,
+							map: diffuse
+						} );
+
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.position.x = - 100;
+						mesh.position.y = 100;
+						group.add( mesh );
+
+						// normalmap
+
+						var material = new THREE.MeshPhysicalMaterial( {
+							clearCoat: 1.0,
+							envMap: hdrCubeRenderTarget.texture,
+							map: diffuse,
+							normalMap: normalMap
+						} );
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.position.x = 100;
+						mesh.position.y = 100;
+						group.add( mesh );
+
+						// clearcoat
+
+						var material = new THREE.MeshPhysicalMaterial( {
+							clearCoat: 1.0,
+							envMap: hdrCubeRenderTarget.texture,
+							map: diffuse,
+							clearCoatNormalMap: clearCoatNormaMap
+						} );
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.position.x = - 100;
+						mesh.position.y = - 100;
+						group.add( mesh );
+
+						// clearcoat + normalmap
+
+						var material = new THREE.MeshPhysicalMaterial( {
+							clearCoat: 1.0,
+							envMap: hdrCubeRenderTarget.texture,
+							map: diffuse,
+							normalMap: normalMap,
+							clearCoatNormalMap: clearCoatNormaMap
+						} );
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.position.x = 100;
+						mesh.position.y = - 100;
+						group.add( mesh );
+
+						//
+
+						hdrCubeMap.magFilter = THREE.LinearFilter;
+						hdrCubeMap.needsUpdate = true;
+						scene.background = hdrCubeMap;
+
+						pmremGenerator.dispose();
+						pmremCubeUVPacker.dispose();
+
+					}
+
+				);
+
+			// LIGHTS
+
+			particleLight = new THREE.Mesh(
+				new THREE.SphereBufferGeometry( 4, 8, 8 ),
+				new THREE.MeshBasicMaterial( { color: 0xffffff } )
+			);
+			scene.add( particleLight );
+
+			particleLight.add( new THREE.PointLight( 0xffffff, 1.25 ) );
+
+			renderer = new THREE.WebGLRenderer();
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			container.appendChild( renderer.domElement );
+
+			//
+
+			renderer.gammaInput = true;
+			renderer.gammaOutput = true;
+
+			//
+
+			stats = new Stats();
+			container.appendChild( stats.dom );
+
+			// EVENTS
+
+			var controls = new OrbitControls( camera, renderer.domElement );
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+		}
+
+		//
+
+		function onWindowResize() {
+
+			var width = window.innerWidth;
+			var height = window.innerHeight;
+
+			camera.aspect = width / height;
+			camera.updateProjectionMatrix();
+
+			renderer.setSize( width, height );
+
+		}
+
+		//
+
+		function animate() {
+
+			requestAnimationFrame( animate );
+
+			render();
+
+			stats.update();
+
+		}
+
+		function render() {
+
+			var timer = Date.now() * 0.00025;
+
+			particleLight.position.x = Math.sin( timer * 7 ) * 300;
+			particleLight.position.y = Math.cos( timer * 5 ) * 400;
+			particleLight.position.z = Math.cos( timer * 3 ) * 300;
+
+			for ( var i = 0; i < group.children.length; i ++ ) {
+
+				var child = group.children[ i ];
+				child.rotation.y += 0.005;
+
+			}
+
+			renderer.render( scene, camera );
+
+		}
+
+
+	</script>
+</body>
+</html>

+ 162 - 0
examples/webgl_materials_cubemap_mipmaps.html

@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - materials - cubemap mipmaps</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - cubemap customized mipmaps demo. Author <a href="https://github.com/AngusLang" target="_blank">Angus</a><br/>
+			Left: webgl generated mipmaps<br/>
+			Right: manual mipmaps<br/>
+		</div>
+
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+
+			import { OrbitControls } from './jsm/controls/OrbitControls.js';
+
+			var container;
+
+			var camera, scene, renderer;
+
+			init();
+			animate();
+
+			//load custmized cube texture
+			async function loadCubeTextureWithMipmaps() {
+
+				var path = 'textures/cube/angus/';
+				var format = '.jpg';
+				var mipmaps = [];
+
+				async function loadCubeTexture( urls ) {
+
+					return new Promise( function ( resolve, reject) {
+
+						new THREE.CubeTextureLoader().load( urls, function ( cubeTexture ) {
+
+							resolve( cubeTexture );
+
+						} );
+
+
+					} );
+
+				}
+
+				// load mipmaps
+				var pendings = [];
+
+				for ( var level = 0; level < 9; ++ level ) {
+
+					var urls = [];
+
+					for ( var face = 0; face < 6; ++ face ) {
+
+						urls.push( path + 'cube_m0' + level + '_c0' + face + format );
+
+					}
+
+					pendings.push( loadCubeTexture( urls ).then( function ( cubeTexture ) {
+
+						mipmaps.push( cubeTexture );
+
+					} ) );
+
+				}
+
+				await Promise.all( pendings );
+
+				var customizedCubeTexture = mipmaps.shift();
+				customizedCubeTexture.mipmaps = mipmaps;
+				customizedCubeTexture.minFilter = THREE.LinearMipMapLinearFilter;
+				customizedCubeTexture.magFilter = THREE.LinearFilter;
+				customizedCubeTexture.generateMipmaps = false;
+				customizedCubeTexture.needsUpdate = true;
+
+				return customizedCubeTexture;
+
+			}
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.z = 500;
+
+				scene = new THREE.Scene();
+
+				loadCubeTextureWithMipmaps().then( function ( cubeTexture ) {
+
+					//model
+					var sphere = new THREE.SphereBufferGeometry( 100, 128, 128 );
+
+					//manual mipmaps
+					var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: cubeTexture } );
+					material.name = 'manual mipmaps';
+
+					var mesh = new THREE.Mesh( sphere, material );
+					mesh.position.set( 100, 0, 0 );
+					scene.add( mesh );
+
+
+					//webgl mipmaps
+					material = material.clone();
+					material.name = 'auto mipmaps';
+
+					var autoCubeTexture = cubeTexture.clone();
+					autoCubeTexture.mipmaps = [];
+					autoCubeTexture.generateMipmaps = true;
+					autoCubeTexture.needsUpdate = true;
+
+					material.envMap = autoCubeTexture;
+
+					mesh = new THREE.Mesh( sphere, material );
+					mesh.position.set( - 100, 0, 0 );
+					scene.add( mesh );
+
+				} );
+
+				//renderer
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				//controls
+				var controls = new OrbitControls( camera, renderer.domElement );
+				controls.minPolarAngle = Math.PI / 4;
+				controls.maxPolarAngle = Math.PI / 1.5;
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 3 - 3
examples/webgl_materials_envmaps_parallax.html

@@ -156,15 +156,15 @@
 					return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
 				}
 
-				vec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
+				vec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float blinnShininessExponent, const in int maxMIPLevel ) {
 
 					#ifdef ENVMAP_MODE_REFLECTION
 
-						vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );
+						vec3 reflectVec = reflect( -viewDir, normal );
 
 					#else
 
-						vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );
+						vec3 reflectVec = refract( -viewDir, normal, refractionRatio );
 
 					#endif
 

+ 8 - 2
examples/webgl_materials_envmaps_pmrem_nodes.html

@@ -46,6 +46,7 @@
 			import {
 				StandardNodeMaterial,
 				FloatNode,
+				OperatorNode,
 				TextureNode,
 				TextureCubeNode
 			} from './jsm/nodes/Nodes.js';
@@ -55,13 +56,14 @@
 				roughness: 0.0,
 				metalness: 0.0,
 				exposure: 1.0,
+				intensity: 1.0,
 				animate: true,
 				debug: false
 			};
 
 			var container, stats;
 			var camera, scene, renderer, controls;
-			var nodeMaterial, nodeTexture, nodeTextureSize, torusMesh, planeMesh;
+			var nodeMaterial, nodeTexture, nodeTextureSize, nodeTextureIntensity, torusMesh, planeMesh;
 			var hdrCubeRenderTarget;
 			var hdrCubeMap;
 
@@ -118,8 +120,9 @@
 
 				nodeTexture = new TextureNode();
 				nodeTextureSize = new FloatNode( 1024 );
+				nodeTextureIntensity = new FloatNode( 1 );
 
-				nodeMaterial.environment = new TextureCubeNode( nodeTexture, nodeTextureSize );
+				nodeMaterial.environment = new OperatorNode( new TextureCubeNode( nodeTexture, nodeTextureSize ), nodeTextureIntensity, OperatorNode.MUL );
 
 				torusMesh = new THREE.Mesh( geometry, nodeMaterial );
 				scene.add( torusMesh );
@@ -164,6 +167,7 @@
 				gui.add( params, 'roughness', 0, 1, 0.01 );
 				gui.add( params, 'metalness', 0, 1, 0.01 );
 				gui.add( params, 'exposure', 0, 2, 0.01 );
+				gui.add( params, 'intensity', 0, 2, 0.01 );
 				gui.add( params, 'animate', true );
 				gui.add( params, 'debug', false );
 				gui.open();
@@ -197,6 +201,8 @@
 				torusMesh.material.roughness.value = params.roughness;
 				torusMesh.material.metalness.value = params.metalness;
 
+				nodeTextureIntensity.value = params.intensity;
+
 				if ( nodeTextureSize.value !== params.textureSize ) {
 
 					generate( params.textureSize );

+ 248 - 7
examples/webgl_materials_nodes.html

@@ -20,14 +20,20 @@
 
 			import { GUI } from './jsm/libs/dat.gui.module.js';
 			import { OrbitControls } from './jsm/controls/OrbitControls.js';
-			import { NodeMaterialLoader, NodeMaterialLoaderUtils } from './jsm/loaders/NodeMaterialLoader.js';
+
 			import { TeapotBufferGeometry } from './jsm/geometries/TeapotBufferGeometry.js';
 
+			import { HDRCubeTextureLoader } from './jsm/loaders/HDRCubeTextureLoader.js';
+			import { PMREMGenerator } from './jsm/pmrem/PMREMGenerator.js';
+			import { PMREMCubeUVPacker } from './jsm/pmrem/PMREMCubeUVPacker.js';
+
+			import { NodeMaterialLoader, NodeMaterialLoaderUtils } from './jsm/loaders/NodeMaterialLoader.js';
+
 			import * as Nodes from './jsm/nodes/Nodes.js';
 
 			var container = document.getElementById( 'container' );
 
-			var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
+			var renderer, scene, lightGroup, camera, clock = new THREE.Clock(), fov = 50;
 			var frame = new Nodes.NodeFrame();
 			var teapot, mesh;
 			var controls;
@@ -84,6 +90,45 @@
 
 			}();
 
+			function generatePREM( cubeMap, textureSize ) {
+
+				textureSize = textureSize || 1024;
+
+				var pmremGenerator = new PMREMGenerator( cubeMap, undefined, textureSize / 4 );
+				pmremGenerator.update( renderer );
+
+				var pmremCubeUVPacker = new PMREMCubeUVPacker( pmremGenerator.cubeLods );
+				pmremCubeUVPacker.update( renderer );
+
+				pmremGenerator.dispose();
+				pmremCubeUVPacker.dispose();
+
+				return pmremCubeUVPacker.CubeUVRenderTarget.texture;
+
+			}
+
+			var premTexture;
+
+			function getPREM( callback, textureSize ) {
+
+				if ( premTexture ) return callback( premTexture );
+
+				var hdrUrls = [ 'px.hdr', 'nx.hdr', 'py.hdr', 'ny.hdr', 'pz.hdr', 'nz.hdr' ];
+				var hdrCubeMap = new HDRCubeTextureLoader()
+					.setPath( './textures/cube/pisaHDR/' )
+					.setDataType( THREE.UnsignedByteType )
+					.load( hdrUrls, function () {
+
+						premTexture = generatePREM( hdrCubeMap, textureSize );
+
+						library[ premTexture.uuid ] = premTexture;
+
+						callback( premTexture );
+
+					} );
+
+			}
+
 			window.addEventListener( 'load', init );
 
 			function init() {
@@ -107,15 +152,20 @@
 				controls.minDistance = 50;
 				controls.maxDistance = 200;
 
-				scene.add( new THREE.AmbientLight( 0x464646 ) );
+				lightGroup = new THREE.Group();
+				scene.add( lightGroup );
+
+				var light;
+
+				lightGroup.add( new THREE.AmbientLight( 0x464646 ) );
 
-				var light = new THREE.DirectionalLight( 0xffddcc, 1 );
+				light = new THREE.DirectionalLight( 0xffddcc, 1 );
 				light.position.set( 1, 0.75, 0.5 );
-				scene.add( light );
+				lightGroup.add( light );
 
-				var light = new THREE.DirectionalLight( 0xccccff, 1 );
+				light = new THREE.DirectionalLight( 0xccccff, 1 );
 				light.position.set( - 1, 0.75, - 0.5 );
-				scene.add( light );
+				lightGroup.add( light );
 
 				teapot = new TeapotBufferGeometry( 15, 18 );
 
@@ -145,6 +195,7 @@
 					'basic / mesh-standard': 'mesh-standard',
 					'basic / standard': 'standard',
 					'basic / physical': 'physical',
+					'basic / prem': 'prem',
 					'basic / phong': 'phong',
 					'basic / layers': 'layers',
 					'basic / rim': 'rim',
@@ -178,6 +229,7 @@
 					'node / position': 'node-position',
 					'node / normal': 'node-normal',
 					'node / reflect': 'node-reflect',
+					'misc / sub-slot': 'sub-slot',
 					'misc / smoke': 'smoke',
 					'misc / firefly': 'firefly',
 					'misc / reserved-keywords': 'reserved-keywords',
@@ -238,6 +290,8 @@
 
 				move = false;
 
+				lightGroup.visible = true;
+
 				if ( mesh.material ) mesh.material.dispose();
 
 				if ( rtTexture ) {
@@ -393,6 +447,193 @@
 
 						break;
 
+					case 'prem':
+
+						// MATERIAL
+
+						mtl = new Nodes.StandardNodeMaterial();
+
+						//mtl.color = // albedo (vec3)
+						//mtl.alpha = // opacity (float)
+						//mtl.roughness = // roughness (float)
+						//mtl.metalness = // metalness (float)
+						//mtl.normal = // normal (vec3)
+						//mtl.emissive = // emissive color (vec3)
+						//mtl.ambient = // ambient color (vec3)
+						//mtl.shadow = // shadowmap (vec3)
+						//mtl.light = // custom-light (vec3)
+						//mtl.ao = // ambient occlusion (float)
+						//mtl.environment = // reflection/refraction (vec3)
+						//mtl.position = // vertex local position (vec3)
+
+						var mask = new Nodes.SwitchNode( new Nodes.TextureNode( getTexture( "decalDiffuse" ) ), 'w' );
+
+						var intensity = new Nodes.FloatNode( 1 );
+
+						var normalScale = new Nodes.FloatNode( .3 );
+
+						var roughnessA = new Nodes.FloatNode( .5 );
+						var metalnessA = new Nodes.FloatNode( .5 );
+
+						var roughnessB = new Nodes.FloatNode( 0 );
+						var metalnessB = new Nodes.FloatNode( 1 );
+
+						var roughness = new Nodes.MathNode(
+							roughnessA,
+							roughnessB,
+							mask,
+							Nodes.MathNode.MIX
+						);
+
+						var metalness = new Nodes.MathNode(
+							metalnessA,
+							metalnessB,
+							mask,
+							Nodes.MathNode.MIX
+						);
+
+						var normalMask = new Nodes.OperatorNode(
+							new Nodes.MathNode( mask, Nodes.MathNode.INVERT ),
+							normalScale,
+							Nodes.OperatorNode.MUL
+						);
+
+						mtl.color = new Nodes.ColorNode( 0xEEEEEE );
+						mtl.roughness = roughness;
+						mtl.metalness = metalness;
+						mtl.normal = new Nodes.NormalMapNode( new Nodes.TextureNode( getTexture( "grassNormal" ) ) );
+						mtl.normal.scale = normalMask;
+
+						getPREM(function(texture) {
+
+							var envNode = new Nodes.TextureCubeNode( new Nodes.TextureNode( texture ) );
+
+							mtl.environment = new Nodes.OperatorNode( envNode, intensity, Nodes.OperatorNode.MUL );
+							mtl.needsUpdate = true;
+
+						});
+
+						// GUI
+
+						addGui( 'color', mtl.color.value.getHex(), function ( val ) {
+
+							mtl.color.value.setHex( val );
+
+						}, true );
+
+						addGui( 'intensity', intensity.value, function ( val ) {
+
+							intensity.value = val;
+
+						}, false, 0, 2 );
+
+						addGui( 'roughnessA', roughnessA.value, function ( val ) {
+
+							roughnessA.value = val;
+
+						}, false, 0, 1 );
+
+						addGui( 'metalnessA', metalnessA.value, function ( val ) {
+
+							metalnessA.value = val;
+
+						}, false, 0, 1 );
+
+						addGui( 'roughnessB', roughnessB.value, function ( val ) {
+
+							roughnessB.value = val;
+
+						}, false, 0, 1 );
+
+						addGui( 'metalnessB', metalnessB.value, function ( val ) {
+
+							metalnessB.value = val;
+
+						}, false, 0, 1 );
+
+						addGui( 'normalScale', normalScale.value, function ( val ) {
+
+							normalScale.value = val;
+
+						}, false, 0, 1 );
+
+						break;
+
+					case 'sub-slot':
+
+						// disable dynamic light
+
+						lightGroup.visible = false;
+
+						// MATERIAL
+
+						mtl = new Nodes.StandardNodeMaterial();
+
+						// NODES
+
+						var mask = new Nodes.SwitchNode( new Nodes.TextureNode( getTexture( "decalDiffuse" ) ), 'w' );
+
+						var normalScale = new Nodes.FloatNode( .3 );
+
+						var radiance = new Nodes.FloatNode( 1 );
+						var irradiance = new Nodes.FloatNode( 1 );
+
+						var roughness = new Nodes.FloatNode( .5 );
+						var metalness = new Nodes.FloatNode( .5 );
+
+						mtl.color = new Nodes.ColorNode( 0xEEEEEE );
+						mtl.roughness = roughness;
+						mtl.metalness = metalness;
+						mtl.normal = new Nodes.NormalMapNode( new Nodes.TextureNode( getTexture( "grassNormal" ) ) );
+						mtl.normal.scale = normalScale;
+
+						getPREM(function(texture) {
+
+							var envNode = new Nodes.TextureCubeNode( new Nodes.TextureNode( texture ) );
+
+							var subSlotNode = new Nodes.SubSlotNode();
+							subSlotNode.slots['radiance'] = new Nodes.OperatorNode( radiance, envNode, Nodes.OperatorNode.MUL );
+							subSlotNode.slots['irradiance'] = new Nodes.OperatorNode( irradiance, envNode, Nodes.OperatorNode.MUL );
+
+							mtl.environment = subSlotNode;
+							mtl.needsUpdate = true;
+
+						});
+
+						// GUI
+
+						addGui( 'radiance', radiance.value, function ( val ) {
+
+							radiance.value = val;
+
+						}, false, 0, 2 );
+
+						addGui( 'irradiance', irradiance.value, function ( val ) {
+
+							irradiance.value = val;
+
+						}, false, 0, 2 );
+
+						addGui( 'roughness', roughness.value, function ( val ) {
+
+							roughness.value = val;
+
+						}, false, 0, 1 );
+
+						addGui( 'metalness', metalness.value, function ( val ) {
+
+							metalness.value = val;
+
+						}, false, 0, 1 );
+
+						addGui( 'normalScale', normalScale.value, function ( val ) {
+
+							normalScale.value = val;
+
+						}, false, 0, 1 );
+
+						break;
+
 					case 'mesh-standard':
 
 						// MATERIAL

+ 10 - 3
examples/webgl_shadowmap_pcss.html

@@ -143,8 +143,15 @@
 				// camera
 
 				camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 10000 );
-				camera.position.y = 5;
-				camera.position.z = 15;
+
+				// We use this particular camera position in order to expose a bug that can sometimes happen presumably
+				// due to lack of precision when interpolating values over really large triangles.
+				// It reproduced on at least NVIDIA GTX 1080 and GTX 1050 Ti GPUs when the ground plane was not
+				// subdivided into segments.
+				camera.position.x = 7;
+				camera.position.y = 13;
+				camera.position.z = 7;
+
 				scene.add( camera );
 
 				// lights
@@ -191,7 +198,7 @@
 
 				var groundMaterial = new THREE.MeshPhongMaterial( { color: 0x404040, specular: 0x111111 } );
 
-				var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
+				var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000, 8, 8 ), groundMaterial );
 				mesh.rotation.x = - Math.PI / 2;
 				mesh.receiveShadow = true;
 				scene.add( mesh );

+ 5 - 5
src/audio/AudioContext.js

@@ -2,25 +2,25 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-var context;
+var _context;
 
 var AudioContext = {
 
 	getContext: function () {
 
-		if ( context === undefined ) {
+		if ( _context === undefined ) {
 
-			context = new ( window.AudioContext || window.webkitAudioContext )();
+			_context = new ( window.AudioContext || window.webkitAudioContext )();
 
 		}
 
-		return context;
+		return _context;
 
 	},
 
 	setContext: function ( value ) {
 
-		context = value;
+		_context = value;
 
 	}
 

+ 37 - 32
src/audio/AudioListener.js

@@ -8,6 +8,9 @@ import { Clock } from '../core/Clock.js';
 import { Object3D } from '../core/Object3D.js';
 import { AudioContext } from './AudioContext.js';
 
+var _position, _quaternion, _scale;
+var _orientation;
+
 function AudioListener() {
 
 	Object3D.call( this );
@@ -23,6 +26,10 @@ function AudioListener() {
 
 	this.timeDelta = 0;
 
+	// private
+
+	this._clock = new Clock();
+
 }
 
 AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
@@ -91,54 +98,52 @@ AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 	},
 
-	updateMatrixWorld: ( function () {
-
-		var position = new Vector3();
-		var quaternion = new Quaternion();
-		var scale = new Vector3();
+	updateMatrixWorld: function ( force ) {
 
-		var orientation = new Vector3();
-		var clock = new Clock();
+		Object3D.prototype.updateMatrixWorld.call( this, force );
 
-		return function updateMatrixWorld( force ) {
+		if ( _position === undefined ) {
 
-			Object3D.prototype.updateMatrixWorld.call( this, force );
+			_position = new Vector3();
+			_quaternion = new Quaternion();
+			_scale = new Vector3();
+			_orientation = new Vector3();
 
-			var listener = this.context.listener;
-			var up = this.up;
+		}
 
-			this.timeDelta = clock.getDelta();
+		var listener = this.context.listener;
+		var up = this.up;
 
-			this.matrixWorld.decompose( position, quaternion, scale );
+		this.timeDelta = this._clock.getDelta();
 
-			orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion );
+		this.matrixWorld.decompose( _position, _quaternion, _scale );
 
-			if ( listener.positionX ) {
+		_orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion );
 
-				// code path for Chrome (see #14393)
+		if ( listener.positionX ) {
 
-				var endTime = this.context.currentTime + this.timeDelta;
+			// code path for Chrome (see #14393)
 
-				listener.positionX.linearRampToValueAtTime( position.x, endTime );
-				listener.positionY.linearRampToValueAtTime( position.y, endTime );
-				listener.positionZ.linearRampToValueAtTime( position.z, endTime );
-				listener.forwardX.linearRampToValueAtTime( orientation.x, endTime );
-				listener.forwardY.linearRampToValueAtTime( orientation.y, endTime );
-				listener.forwardZ.linearRampToValueAtTime( orientation.z, endTime );
-				listener.upX.linearRampToValueAtTime( up.x, endTime );
-				listener.upY.linearRampToValueAtTime( up.y, endTime );
-				listener.upZ.linearRampToValueAtTime( up.z, endTime );
+			var endTime = this.context.currentTime + this.timeDelta;
 
-			} else {
+			listener.positionX.linearRampToValueAtTime( _position.x, endTime );
+			listener.positionY.linearRampToValueAtTime( _position.y, endTime );
+			listener.positionZ.linearRampToValueAtTime( _position.z, endTime );
+			listener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );
+			listener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );
+			listener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );
+			listener.upX.linearRampToValueAtTime( up.x, endTime );
+			listener.upY.linearRampToValueAtTime( up.y, endTime );
+			listener.upZ.linearRampToValueAtTime( up.z, endTime );
 
-				listener.setPosition( position.x, position.y, position.z );
-				listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
+		} else {
 
-			}
+			listener.setPosition( _position.x, _position.y, _position.z );
+			listener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );
 
-		};
+		}
 
-	} )()
+	}
 
 } );
 

+ 29 - 28
src/audio/PositionalAudio.js

@@ -7,6 +7,9 @@ import { Quaternion } from '../math/Quaternion.js';
 import { Audio } from './Audio.js';
 import { Object3D } from '../core/Object3D.js';
 
+var _position, _quaternion, _scale;
+var _orientation;
+
 function PositionalAudio( listener ) {
 
 	Audio.call( this, listener );
@@ -93,50 +96,48 @@ PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {
 
 	},
 
-	updateMatrixWorld: ( function () {
-
-		var position = new Vector3();
-		var quaternion = new Quaternion();
-		var scale = new Vector3();
-
-		var orientation = new Vector3();
+	updateMatrixWorld: function ( force ) {
 
-		return function updateMatrixWorld( force ) {
+		Object3D.prototype.updateMatrixWorld.call( this, force );
 
-			Object3D.prototype.updateMatrixWorld.call( this, force );
+		if ( _position === undefined ) {
 
-			if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
+			_position = new Vector3();
+			_quaternion = new Quaternion();
+			_scale = new Vector3();
+			_orientation = new Vector3();
 
-			this.matrixWorld.decompose( position, quaternion, scale );
+		}
 
-			orientation.set( 0, 0, 1 ).applyQuaternion( quaternion );
+		if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
 
-			var panner = this.panner;
+		this.matrixWorld.decompose( _position, _quaternion, _scale );
 
-			if ( panner.positionX ) {
+		_orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
 
-				// code path for Chrome and Firefox (see #14393)
+		var panner = this.panner;
 
-				var endTime = this.context.currentTime + this.listener.timeDelta;
+		if ( panner.positionX ) {
 
-				panner.positionX.linearRampToValueAtTime( position.x, endTime );
-				panner.positionY.linearRampToValueAtTime( position.y, endTime );
-				panner.positionZ.linearRampToValueAtTime( position.z, endTime );
-				panner.orientationX.linearRampToValueAtTime( orientation.x, endTime );
-				panner.orientationY.linearRampToValueAtTime( orientation.y, endTime );
-				panner.orientationZ.linearRampToValueAtTime( orientation.z, endTime );
+			// code path for Chrome and Firefox (see #14393)
 
-			} else {
+			var endTime = this.context.currentTime + this.listener.timeDelta;
 
-				panner.setPosition( position.x, position.y, position.z );
-				panner.setOrientation( orientation.x, orientation.y, orientation.z );
+			panner.positionX.linearRampToValueAtTime( _position.x, endTime );
+			panner.positionY.linearRampToValueAtTime( _position.y, endTime );
+			panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
+			panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
+			panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
+			panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
 
-			}
+		} else {
 
-		};
+			panner.setPosition( _position.x, _position.y, _position.z );
+			panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
 
-	} )()
+		}
 
+	}
 
 } );
 

+ 55 - 43
src/cameras/StereoCamera.js

@@ -2,6 +2,8 @@ import { Matrix4 } from '../math/Matrix4.js';
 import { _Math } from '../math/Math.js';
 import { PerspectiveCamera } from './PerspectiveCamera.js';
 
+var _eyeRight, _eyeLeft;
+
 /**
  * @author mrdoob / http://mrdoob.com/
  */
@@ -22,75 +24,85 @@ function StereoCamera() {
 	this.cameraR.layers.enable( 2 );
 	this.cameraR.matrixAutoUpdate = false;
 
+	this._cache = {
+		focus: null,
+		fov: null,
+		aspect: null,
+		near: null,
+		far: null,
+		zoom: null,
+		eyeSep: null
+	};
+
 }
 
 Object.assign( StereoCamera.prototype, {
 
-	update: ( function () {
+	update: function ( camera ) {
 
-		var instance, focus, fov, aspect, near, far, zoom, eyeSep;
+		if ( _eyeRight === undefined ) {
 
-		var eyeRight = new Matrix4();
-		var eyeLeft = new Matrix4();
+			_eyeRight = new Matrix4();
+			_eyeLeft = new Matrix4();
 
-		return function update( camera ) {
+		}
 
-			var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov ||
-												aspect !== camera.aspect * this.aspect || near !== camera.near ||
-												far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep;
+		var cache = this._cache;
 
-			if ( needsUpdate ) {
+		var needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
+			cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
+			cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
 
-				instance = this;
-				focus = camera.focus;
-				fov = camera.fov;
-				aspect = camera.aspect * this.aspect;
-				near = camera.near;
-				far = camera.far;
-				zoom = camera.zoom;
+		if ( needsUpdate ) {
 
-				// Off-axis stereoscopic effect based on
-				// http://paulbourke.net/stereographics/stereorender/
+			cache.focus = camera.focus;
+			cache.fov = camera.fov;
+			cache.aspect = camera.aspect * this.aspect;
+			cache.near = camera.near;
+			cache.far = camera.far;
+			cache.zoom = camera.zoom;
+			cache.eyeSep = this.eyeSep;
 
-				var projectionMatrix = camera.projectionMatrix.clone();
-				eyeSep = this.eyeSep / 2;
-				var eyeSepOnProjection = eyeSep * near / focus;
-				var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom;
-				var xmin, xmax;
+			// Off-axis stereoscopic effect based on
+			// http://paulbourke.net/stereographics/stereorender/
 
-				// translate xOffset
+			var projectionMatrix = camera.projectionMatrix.clone();
+			var eyeSepHalf = cache.eyeSep / 2;
+			var eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
+			var ymax = ( cache.near * Math.tan( _Math.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
+			var xmin, xmax;
 
-				eyeLeft.elements[ 12 ] = - eyeSep;
-				eyeRight.elements[ 12 ] = eyeSep;
+			// translate xOffset
 
-				// for left eye
+			_eyeLeft.elements[ 12 ] = - eyeSepHalf;
+			_eyeRight.elements[ 12 ] = eyeSepHalf;
 
-				xmin = - ymax * aspect + eyeSepOnProjection;
-				xmax = ymax * aspect + eyeSepOnProjection;
+			// for left eye
 
-				projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
-				projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
+			xmin = - ymax * cache.aspect + eyeSepOnProjection;
+			xmax = ymax * cache.aspect + eyeSepOnProjection;
 
-				this.cameraL.projectionMatrix.copy( projectionMatrix );
+			projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
+			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
 
-				// for right eye
+			this.cameraL.projectionMatrix.copy( projectionMatrix );
 
-				xmin = - ymax * aspect - eyeSepOnProjection;
-				xmax = ymax * aspect - eyeSepOnProjection;
+			// for right eye
 
-				projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin );
-				projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
+			xmin = - ymax * cache.aspect - eyeSepOnProjection;
+			xmax = ymax * cache.aspect - eyeSepOnProjection;
 
-				this.cameraR.projectionMatrix.copy( projectionMatrix );
+			projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
+			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
 
-			}
+			this.cameraR.projectionMatrix.copy( projectionMatrix );
 
-			this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft );
-			this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight );
+		}
 
-		};
+		this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
+		this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
 
-	} )()
+	}
 
 } );
 

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

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

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

@@ -50,6 +50,8 @@ export class Geometry extends EventDispatcher {
 
 	uuid: string;
 
+	isGeometry: boolean;
+
 	/**
 	 * Name for this geometry. Default is an empty string.
 	 */

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä