Browse Source

Merge remote-tracking branch 'upstream/dev' into dev

zhaoy 7 years ago
parent
commit
358e791fae
100 changed files with 3737 additions and 3194 deletions
  1. 1 1
      .github/CONTRIBUTING.md
  2. 185 82
      build/three.js
  3. 385 382
      build/three.min.js
  4. 185 82
      build/three.module.js
  5. 5 5
      docs/api/animation/PropertyMixer.html
  6. 1 1
      docs/api/cameras/Camera.html
  7. 1 1
      docs/api/cameras/StereoCamera.html
  8. 15 15
      docs/api/core/BufferAttribute.html
  9. 2 2
      docs/api/core/DirectGeometry.html
  10. 3 3
      docs/api/core/InterleavedBuffer.html
  11. 11 11
      docs/api/core/InterleavedBufferAttribute.html
  12. 1 1
      docs/api/core/Object3D.html
  13. 2 2
      docs/api/core/Raycaster.html
  14. 1 1
      docs/api/helpers/Box3Helper.html
  15. 1 1
      docs/api/helpers/PlaneHelper.html
  16. 16 14
      docs/api/lights/DirectionalLight.html
  17. 0 13
      docs/api/loaders/TextureLoader.html
  18. 2 2
      docs/api/materials/LineBasicMaterial.html
  19. 2 2
      docs/api/materials/LineDashedMaterial.html
  20. 1 2
      docs/api/materials/Material.html
  21. 3 2
      docs/api/materials/MeshBasicMaterial.html
  22. 3 2
      docs/api/materials/MeshDepthMaterial.html
  23. 3 2
      docs/api/materials/MeshLambertMaterial.html
  24. 3 2
      docs/api/materials/MeshNormalMaterial.html
  25. 3 2
      docs/api/materials/MeshPhongMaterial.html
  26. 3 2
      docs/api/materials/MeshStandardMaterial.html
  27. 1 1
      docs/api/materials/PointsMaterial.html
  28. 6 4
      docs/api/materials/ShaderMaterial.html
  29. 1 1
      docs/api/materials/SpriteMaterial.html
  30. 2 2
      docs/api/math/Box2.html
  31. 1 1
      docs/api/math/Cylindrical.html
  32. 7 2
      docs/api/math/Euler.html
  33. 1 6
      docs/api/math/Math.html
  34. 2 11
      docs/api/math/Matrix3.html
  35. 1 5
      docs/api/math/Matrix4.html
  36. 1 11
      docs/api/math/Quaternion.html
  37. 1 1
      docs/api/objects/Mesh.html
  38. 1 1
      docs/api/renderers/WebGLRenderer.html
  39. 3 3
      docs/api/textures/Texture.html
  40. 1 1
      docs/examples/loaders/GLTFLoader.html
  41. 28 3
      docs/examples/loaders/SVGLoader.html
  42. 1 1
      docs/examples/renderers/SVGRenderer.html
  43. 2 0
      docs/index.html
  44. 6 6
      editor/index.html
  45. 1 1
      examples/canvas_ascii_effect.html
  46. 1 1
      examples/canvas_camera_orthographic.html
  47. 1 1
      examples/canvas_geometry_earth.html
  48. 1 1
      examples/canvas_geometry_hierarchy.html
  49. 1 1
      examples/canvas_geometry_panorama.html
  50. 7 5
      examples/canvas_geometry_panorama_fisheye.html
  51. 1 1
      examples/canvas_geometry_shapes.html
  52. 1 1
      examples/canvas_geometry_text.html
  53. 1 1
      examples/canvas_interactive_cubes.html
  54. 1 1
      examples/canvas_interactive_cubes_tween.html
  55. 1 1
      examples/canvas_interactive_voxelpainter.html
  56. 42 21
      examples/canvas_lines_colors.html
  57. 25 58
      examples/canvas_lines_dashed.html
  58. 1 1
      examples/canvas_materials_video.html
  59. 1 1
      examples/canvas_performance.html
  60. 1 1
      examples/canvas_sandbox.html
  61. 2 0
      examples/files.js
  62. 2 4
      examples/index.html
  63. 1 1
      examples/js/controls/DragControls.js
  64. 66 15
      examples/js/loaders/ColladaLoader.js
  65. 1603 1620
      examples/js/loaders/FBXLoader.js
  66. 59 84
      examples/js/loaders/GLTFLoader.js
  67. 1 1
      examples/js/loaders/HDRCubeTextureLoader.js
  68. 24 7
      examples/js/loaders/STLLoader.js
  69. 316 24
      examples/js/loaders/SVGLoader.js
  70. 8 0
      examples/js/loaders/TGALoader.js
  71. 7 1
      examples/js/nodes/Nodes.js
  72. 43 25
      examples/js/nodes/THREE.Nodes.js
  73. 22 22
      examples/js/nodes/accessors/CameraNode.js
  74. 7 8
      examples/js/nodes/accessors/ColorsNode.js
  75. 6 6
      examples/js/nodes/accessors/LightNode.js
  76. 7 7
      examples/js/nodes/accessors/NormalNode.js
  77. 8 8
      examples/js/nodes/accessors/PositionNode.js
  78. 6 6
      examples/js/nodes/accessors/ReflectNode.js
  79. 18 12
      examples/js/nodes/accessors/ResolutionNode.js
  80. 7 6
      examples/js/nodes/accessors/ScreenUVNode.js
  81. 6 6
      examples/js/nodes/accessors/UVNode.js
  82. 4 4
      examples/js/nodes/bsdfs/BlinnExponentToRoughnessNode.js
  83. 1 1
      examples/js/nodes/bsdfs/BlinnShininessExponentNode.js
  84. 12 11
      examples/js/nodes/bsdfs/RoughnessToBlinnExponentNode.js
  85. 9 9
      examples/js/nodes/core/AttributeNode.js
  86. 12 12
      examples/js/nodes/core/ConstNode.js
  87. 17 0
      examples/js/nodes/core/ExpressionNode.js
  88. 5 5
      examples/js/nodes/core/FunctionCallNode.js
  89. 25 26
      examples/js/nodes/core/FunctionNode.js
  90. 5 5
      examples/js/nodes/core/InputNode.js
  91. 45 41
      examples/js/nodes/core/Node.js
  92. 260 309
      examples/js/nodes/core/NodeBuilder.js
  93. 23 7
      examples/js/nodes/core/NodeFrame.js
  94. 6 6
      examples/js/nodes/core/NodeUniform.js
  95. 9 9
      examples/js/nodes/core/NodeUtils.js
  96. 28 28
      examples/js/nodes/core/StructNode.js
  97. 17 17
      examples/js/nodes/core/TempNode.js
  98. 10 10
      examples/js/nodes/core/VarNode.js
  99. 15 15
      examples/js/nodes/effects/BlurNode.js
  100. 24 24
      examples/js/nodes/effects/ColorAdjustmentNode.js

+ 1 - 1
.github/CONTRIBUTING.md

@@ -1,6 +1,6 @@
 
 
 # Help 
 # Help 
-#### The issues section is for bug reports and feature requests only. If you need help, please use [stackoverflow](http://stackoverflow.com/questions/tagged/three.js).
+#### The issues section is for bug reports and feature requests only. If you need help, please use the [forum](http://discourse.threejs.org/) or [stackoverflow](http://stackoverflow.com/questions/tagged/three.js).
 ---
 ---
 # Bugs
 # Bugs
 #### Before reporting a bug
 #### Before reporting a bug

+ 185 - 82
build/three.js

@@ -14722,7 +14722,7 @@
 	 * @author mrdoob / http://mrdoob.com/
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 	 */
 
 
-	function WebGLBufferRenderer( gl, extensions, info ) {
+	function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
 
 
 		var mode;
 		var mode;
 
 
@@ -14742,16 +14742,26 @@
 
 
 		function renderInstances( geometry, start, count ) {
 		function renderInstances( geometry, start, count ) {
 
 
-			var extension = extensions.get( 'ANGLE_instanced_arrays' );
+			var extension;
 
 
-			if ( extension === null ) {
+			if ( capabilities.isWebGL2 ) {
 
 
-				console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
-				return;
+				extension = gl;
+
+			} else {
+
+				extension = extensions.get( 'ANGLE_instanced_arrays' );
+
+				if ( extension === null ) {
+
+					console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
+					return;
+
+				}
 
 
 			}
 			}
 
 
-			extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
+			extension[ capabilities.isWebGL2 ? 'drawArraysInstanced' : 'drawArraysInstancedANGLE' ]( mode, start, count, geometry.maxInstancedCount );
 
 
 			info.update( count, mode, geometry.maxInstancedCount );
 			info.update( count, mode, geometry.maxInstancedCount );
 
 
@@ -14823,6 +14833,8 @@
 
 
 		}
 		}
 
 
+		var isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
+
 		var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
 		var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
 		var maxPrecision = getMaxPrecision( precision );
 		var maxPrecision = getMaxPrecision( precision );
 
 
@@ -14846,11 +14858,13 @@
 		var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
 		var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
 
 
 		var vertexTextures = maxVertexTextures > 0;
 		var vertexTextures = maxVertexTextures > 0;
-		var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
+		var floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
 		var floatVertexTextures = vertexTextures && floatFragmentTextures;
 		var floatVertexTextures = vertexTextures && floatFragmentTextures;
 
 
 		return {
 		return {
 
 
+			isWebGL2: isWebGL2,
+
 			getMaxAnisotropy: getMaxAnisotropy,
 			getMaxAnisotropy: getMaxAnisotropy,
 			getMaxPrecision: getMaxPrecision,
 			getMaxPrecision: getMaxPrecision,
 
 
@@ -15123,18 +15137,7 @@
 
 
 			delete geometries[ geometry.id ];
 			delete geometries[ geometry.id ];
 
 
-			// TODO Remove duplicate code
-
-			var attribute = wireframeAttributes[ geometry.id ];
-
-			if ( attribute ) {
-
-				attributes.remove( attribute );
-				delete wireframeAttributes[ geometry.id ];
-
-			}
-
-			attribute = wireframeAttributes[ buffergeometry.id ];
+			var attribute = wireframeAttributes[ buffergeometry.id ];
 
 
 			if ( attribute ) {
 			if ( attribute ) {
 
 
@@ -15286,7 +15289,7 @@
 	 * @author mrdoob / http://mrdoob.com/
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 	 */
 
 
-	function WebGLIndexedBufferRenderer( gl, extensions, info ) {
+	function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
 
 
 		var mode;
 		var mode;
 
 
@@ -15315,16 +15318,26 @@
 
 
 		function renderInstances( geometry, start, count ) {
 		function renderInstances( geometry, start, count ) {
 
 
-			var extension = extensions.get( 'ANGLE_instanced_arrays' );
+			var extension;
 
 
-			if ( extension === null ) {
+			if ( capabilities.isWebGL2 ) {
 
 
-				console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
-				return;
+				extension = gl;
+
+			} else {
+
+				var extension = extensions.get( 'ANGLE_instanced_arrays' );
+
+				if ( extension === null ) {
+
+					console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
+					return;
+
+				}
 
 
 			}
 			}
 
 
-			extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
+			extension[ capabilities.isWebGL2 ? 'drawElementsInstanced' : 'drawElementsInstancedANGLE' ]( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
 
 
 			info.update( count, mode, geometry.maxInstancedCount );
 			info.update( count, mode, geometry.maxInstancedCount );
 
 
@@ -16714,7 +16727,7 @@
 
 
 	}
 	}
 
 
-	function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
+	function WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities ) {
 
 
 		var gl = renderer.context;
 		var gl = renderer.context;
 
 
@@ -16797,7 +16810,7 @@
 
 
 		//
 		//
 
 
-		var customExtensions = generateExtensions( material.extensions, parameters, extensions );
+		var customExtensions = capabilities.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );
 
 
 		var customDefines = generateDefines( defines );
 		var customDefines = generateDefines( defines );
 
 
@@ -16885,7 +16898,7 @@
 				parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
 				parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
 
 
 				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
 				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
-				parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
+				parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
 
 
 				'uniform mat4 modelMatrix;',
 				'uniform mat4 modelMatrix;',
 				'uniform mat4 modelViewMatrix;',
 				'uniform mat4 modelViewMatrix;',
@@ -16990,9 +17003,9 @@
 				parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
 				parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
 
 
 				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
 				parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
-				parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
+				parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
 
 
-				parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
+				parameters.envMap && ( capabilities.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',
 
 
 				'uniform mat4 viewMatrix;',
 				'uniform mat4 viewMatrix;',
 				'uniform vec3 cameraPosition;',
 				'uniform vec3 cameraPosition;',
@@ -17028,6 +17041,50 @@
 		vertexShader = unrollLoops( vertexShader );
 		vertexShader = unrollLoops( vertexShader );
 		fragmentShader = unrollLoops( fragmentShader );
 		fragmentShader = unrollLoops( fragmentShader );
 
 
+		if ( capabilities.isWebGL2 && ! material.isRawShaderMaterial ) {
+
+			var isGLSL3ShaderMaterial = false;
+
+			var versionRegex = /^\s*#version\s+300\s+es\s*\n/;
+
+			if ( material.isShaderMaterial &&
+				vertexShader.match( versionRegex ) !== null &&
+				fragmentShader.match( versionRegex ) !== null ) {
+
+				isGLSL3ShaderMaterial = true;
+
+				vertexShader = vertexShader.replace( versionRegex, '' );
+				fragmentShader = fragmentShader.replace( versionRegex, '' );
+
+			}
+
+			// GLSL 3.0 conversion
+			prefixVertex = [
+				'#version 300 es\n',
+				'#define attribute in',
+				'#define varying out',
+				'#define texture2D texture'
+			].join( '\n' ) + '\n' + prefixVertex;
+
+			prefixFragment = [
+				'#version 300 es\n',
+				'#define varying in',
+				isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
+				isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
+				'#define gl_FragDepthEXT gl_FragDepth',
+				'#define texture2D texture',
+				'#define textureCube texture',
+				'#define texture2DProj textureProj',
+				'#define texture2DLodEXT textureLod',
+				'#define texture2DProjLodEXT textureProjLod',
+				'#define textureCubeLodEXT textureLod',
+				'#define texture2DGradEXT textureGrad',
+				'#define texture2DProjGradEXT textureProjGrad',
+				'#define textureCubeGradEXT textureGrad'
+			].join( '\n' ) + '\n' + prefixFragment;
+
+		}
+
 		var vertexGlsl = prefixVertex + vertexShader;
 		var vertexGlsl = prefixVertex + vertexShader;
 		var fragmentGlsl = prefixFragment + fragmentShader;
 		var fragmentGlsl = prefixFragment + fragmentShader;
 
 
@@ -17465,7 +17522,7 @@
 
 
 			if ( program === undefined ) {
 			if ( program === undefined ) {
 
 
-				program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
+				program = new WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities );
 				programs.push( program );
 				programs.push( program );
 
 
 			}
 			}
@@ -18727,7 +18784,7 @@
 	 * @author mrdoob / http://mrdoob.com/
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 	 */
 
 
-	function WebGLState( gl, extensions, utils ) {
+	function WebGLState( gl, extensions, utils, capabilities ) {
 
 
 		function ColorBuffer() {
 		function ColorBuffer() {
 
 
@@ -19039,7 +19096,7 @@
 		var enabledAttributes = new Uint8Array( maxVertexAttributes );
 		var enabledAttributes = new Uint8Array( maxVertexAttributes );
 		var attributeDivisors = new Uint8Array( maxVertexAttributes );
 		var attributeDivisors = new Uint8Array( maxVertexAttributes );
 
 
-		var capabilities = {};
+		var enabledCapabilities = {};
 
 
 		var compressedTextureFormats = null;
 		var compressedTextureFormats = null;
 
 
@@ -19156,9 +19213,9 @@
 
 
 			if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
 			if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
 
 
-				var extension = extensions.get( 'ANGLE_instanced_arrays' );
+				var extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
 
 
-				extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
+				extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
 				attributeDivisors[ attribute ] = meshPerAttribute;
 				attributeDivisors[ attribute ] = meshPerAttribute;
 
 
 			}
 			}
@@ -19182,10 +19239,10 @@
 
 
 		function enable( id ) {
 		function enable( id ) {
 
 
-			if ( capabilities[ id ] !== true ) {
+			if ( enabledCapabilities[ id ] !== true ) {
 
 
 				gl.enable( id );
 				gl.enable( id );
-				capabilities[ id ] = true;
+				enabledCapabilities[ id ] = true;
 
 
 			}
 			}
 
 
@@ -19193,10 +19250,10 @@
 
 
 		function disable( id ) {
 		function disable( id ) {
 
 
-			if ( capabilities[ id ] !== false ) {
+			if ( enabledCapabilities[ id ] !== false ) {
 
 
 				gl.disable( id );
 				gl.disable( id );
-				capabilities[ id ] = false;
+				enabledCapabilities[ id ] = false;
 
 
 			}
 			}
 
 
@@ -19605,7 +19662,7 @@
 
 
 			}
 			}
 
 
-			capabilities = {};
+			enabledCapabilities = {};
 
 
 			compressedTextureFormats = null;
 			compressedTextureFormats = null;
 
 
@@ -19674,7 +19731,6 @@
 
 
 	function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
 	function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
 
 
-		var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
 		var _videoTextures = {};
 		var _videoTextures = {};
 		var _canvas;
 		var _canvas;
 
 
@@ -19743,6 +19799,8 @@
 
 
 		function textureNeedsPowerOfTwo( texture ) {
 		function textureNeedsPowerOfTwo( texture ) {
 
 
+			if ( capabilities.isWebGL2 ) return false;
+
 			return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
 			return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
 				( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
 				( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
 
 
@@ -19766,6 +19824,30 @@
 
 
 		}
 		}
 
 
+		function getInternalFormat( glFormat, glType ) {
+
+			if ( ! capabilities.isWebGL2 ) return glFormat;
+
+			if ( glFormat === _gl.RGB ) {
+
+				if ( glType === _gl.FLOAT ) return _gl.RGB32F;
+				if ( glType === _gl.HALF_FLOAT ) return _gl.RGB16F;
+				if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGB8;
+
+			}
+
+			if ( glFormat === _gl.RGBA ) {
+
+				if ( glType === _gl.FLOAT ) return _gl.RGBA32F;
+				if ( glType === _gl.HALF_FLOAT ) return _gl.RGBA16F;
+				if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGBA8;
+
+			}
+
+			return glFormat;
+
+		}
+
 		// Fallback filters for non-power-of-2 textures
 		// Fallback filters for non-power-of-2 textures
 
 
 		function filterFallback( f ) {
 		function filterFallback( f ) {
@@ -19960,7 +20042,8 @@
 					var image = cubeImage[ 0 ],
 					var image = cubeImage[ 0 ],
 						isPowerOfTwoImage = isPowerOfTwo( image ),
 						isPowerOfTwoImage = isPowerOfTwo( image ),
 						glFormat = utils.convert( texture.format ),
 						glFormat = utils.convert( texture.format ),
-						glType = utils.convert( texture.type );
+						glType = utils.convert( texture.type ),
+						glInternalFormat = getInternalFormat( glFormat, glType );
 
 
 					setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
 					setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
 
 
@@ -19970,11 +20053,11 @@
 
 
 							if ( isDataTexture ) {
 							if ( isDataTexture ) {
 
 
-								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
+								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
 
 
 							} else {
 							} else {
 
 
-								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
+								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
 
 
 							}
 							}
 
 
@@ -19990,7 +20073,7 @@
 
 
 									if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 									if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 
 
-										state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+										state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
 									} else {
 									} else {
 
 
@@ -20000,7 +20083,7 @@
 
 
 								} else {
 								} else {
 
 
-									state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+									state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
 								}
 								}
 
 
@@ -20088,7 +20171,7 @@
 			if ( extension ) {
 			if ( extension ) {
 
 
 				if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
 				if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
-				if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
+				if ( texture.type === HalfFloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
 
 
 				if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
 				if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
 
 
@@ -20132,7 +20215,8 @@
 
 
 			var isPowerOfTwoImage = isPowerOfTwo( image ),
 			var isPowerOfTwoImage = isPowerOfTwo( image ),
 				glFormat = utils.convert( texture.format ),
 				glFormat = utils.convert( texture.format ),
-				glType = utils.convert( texture.type );
+				glType = utils.convert( texture.type ),
+				glInternalFormat = getInternalFormat( glFormat, glType );
 
 
 			setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
 			setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
 
 
@@ -20142,21 +20226,21 @@
 
 
 				// populate depth texture with dummy data
 				// populate depth texture with dummy data
 
 
-				var internalFormat = _gl.DEPTH_COMPONENT;
+				glInternalFormat = _gl.DEPTH_COMPONENT;
 
 
 				if ( texture.type === FloatType ) {
 				if ( texture.type === FloatType ) {
 
 
-					if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
-					internalFormat = _gl.DEPTH_COMPONENT32F;
+					if ( ! capabilities.isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
+					glInternalFormat = _gl.DEPTH_COMPONENT32F;
 
 
-				} else if ( _isWebGL2 ) {
+				} else if ( capabilities.isWebGL2 ) {
 
 
 					// WebGL 2.0 requires signed internalformat for glTexImage2D
 					// WebGL 2.0 requires signed internalformat for glTexImage2D
-					internalFormat = _gl.DEPTH_COMPONENT16;
+					glInternalFormat = _gl.DEPTH_COMPONENT16;
 
 
 				}
 				}
 
 
-				if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
+				if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
 
 
 					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 					// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
 					// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
@@ -20176,7 +20260,7 @@
 				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
 				// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
 				if ( texture.format === DepthStencilFormat ) {
 				if ( texture.format === DepthStencilFormat ) {
 
 
-					internalFormat = _gl.DEPTH_STENCIL;
+					glInternalFormat = _gl.DEPTH_STENCIL;
 
 
 					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 					// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 					// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
 					// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
@@ -20192,7 +20276,7 @@
 
 
 				}
 				}
 
 
-				state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
+				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
 
 
 			} else if ( texture.isDataTexture ) {
 			} else if ( texture.isDataTexture ) {
 
 
@@ -20205,7 +20289,7 @@
 					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
 						mipmap = mipmaps[ i ];
 						mipmap = mipmaps[ i ];
-						state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+						state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
 					}
 					}
 
 
@@ -20214,7 +20298,7 @@
 
 
 				} else {
 				} else {
 
 
-					state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
+					state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
 					textureProperties.__maxMipLevel = 0;
 					textureProperties.__maxMipLevel = 0;
 
 
 				}
 				}
@@ -20229,7 +20313,7 @@
 
 
 						if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 						if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 
 
-							state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+							state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
 						} else {
 						} else {
 
 
@@ -20239,7 +20323,7 @@
 
 
 					} else {
 					} else {
 
 
-						state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+						state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
 					}
 					}
 
 
@@ -20260,7 +20344,7 @@
 					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
 						mipmap = mipmaps[ i ];
 						mipmap = mipmaps[ i ];
-						state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
+						state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
 
 
 					}
 					}
 
 
@@ -20269,7 +20353,7 @@
 
 
 				} else {
 				} else {
 
 
-					state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
+					state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
 					textureProperties.__maxMipLevel = 0;
 					textureProperties.__maxMipLevel = 0;
 
 
 				}
 				}
@@ -20295,7 +20379,8 @@
 
 
 			var glFormat = utils.convert( renderTarget.texture.format );
 			var glFormat = utils.convert( renderTarget.texture.format );
 			var glType = utils.convert( renderTarget.texture.type );
 			var glType = utils.convert( renderTarget.texture.type );
-			state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
+			var glInternalFormat = getInternalFormat( glFormat, glType );
+			state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
 			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
 			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
 			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
@@ -20540,7 +20625,7 @@
 	 * @author thespite / http://www.twitter.com/thespite
 	 * @author thespite / http://www.twitter.com/thespite
 	 */
 	 */
 
 
-	function WebGLUtils( gl, extensions ) {
+	function WebGLUtils( gl, extensions, capabilities ) {
 
 
 		function convert( p ) {
 		function convert( p ) {
 
 
@@ -20572,6 +20657,8 @@
 
 
 			if ( p === HalfFloatType ) {
 			if ( p === HalfFloatType ) {
 
 
+				if ( capabilities.isWebGL2 ) return gl.HALF_FLOAT;
+
 				extension = extensions.get( 'OES_texture_half_float' );
 				extension = extensions.get( 'OES_texture_half_float' );
 
 
 				if ( extension !== null ) return extension.HALF_FLOAT_OES;
 				if ( extension !== null ) return extension.HALF_FLOAT_OES;
@@ -20661,6 +20748,13 @@
 
 
 			if ( p === MinEquation || p === MaxEquation ) {
 			if ( p === MinEquation || p === MaxEquation ) {
 
 
+				if ( capabilities.isWebGL2 ) {
+
+					if ( p === MinEquation ) return gl.MIN;
+					if ( p === MaxEquation ) return gl.MAX;
+
+				}
+
 				extension = extensions.get( 'EXT_blend_minmax' );
 				extension = extensions.get( 'EXT_blend_minmax' );
 
 
 				if ( extension !== null ) {
 				if ( extension !== null ) {
@@ -20674,6 +20768,8 @@
 
 
 			if ( p === UnsignedInt248Type ) {
 			if ( p === UnsignedInt248Type ) {
 
 
+				if ( capabilities.isWebGL2 ) return gl.UNSIGNED_INT_24_8;
+
 				extension = extensions.get( 'WEBGL_depth_texture' );
 				extension = extensions.get( 'WEBGL_depth_texture' );
 
 
 				if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
 				if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
@@ -21805,20 +21901,26 @@
 		function initGLContext() {
 		function initGLContext() {
 
 
 			extensions = new WebGLExtensions( _gl );
 			extensions = new WebGLExtensions( _gl );
-			extensions.get( 'WEBGL_depth_texture' );
-			extensions.get( 'OES_texture_float' );
-			extensions.get( 'OES_texture_float_linear' );
-			extensions.get( 'OES_texture_half_float' );
-			extensions.get( 'OES_texture_half_float_linear' );
-			extensions.get( 'OES_standard_derivatives' );
-			extensions.get( 'OES_element_index_uint' );
-			extensions.get( 'ANGLE_instanced_arrays' );
-
-			utils = new WebGLUtils( _gl, extensions );
 
 
 			capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 			capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 
 
-			state = new WebGLState( _gl, extensions, utils );
+			if ( ! capabilities.isWebGL2 ) {
+
+				extensions.get( 'WEBGL_depth_texture' );
+				extensions.get( 'OES_texture_float' );
+				extensions.get( 'OES_texture_half_float' );
+				extensions.get( 'OES_texture_half_float_linear' );
+				extensions.get( 'OES_standard_derivatives' );
+				extensions.get( 'OES_element_index_uint' );
+				extensions.get( 'ANGLE_instanced_arrays' );
+
+			}
+
+			extensions.get( 'OES_texture_float_linear' );
+
+			utils = new WebGLUtils( _gl, extensions, capabilities );
+
+			state = new WebGLState( _gl, extensions, utils, capabilities );
 			state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
 			state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
 			state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
 			state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
 
 
@@ -21835,8 +21937,8 @@
 
 
 			background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
 			background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
 
 
-			bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
-			indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
+			bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
+			indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
 
 
 			info.programs = programCache.programs;
 			info.programs = programCache.programs;
 
 
@@ -22373,7 +22475,7 @@
 
 
 		function setupVertexAttributes( material, program, geometry ) {
 		function setupVertexAttributes( material, program, geometry ) {
 
 
-			if ( geometry && geometry.isInstancedBufferGeometry ) {
+			if ( geometry && geometry.isInstancedBufferGeometry & ! capabilities.isWebGL2 ) {
 
 
 				if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 				if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 
 
@@ -22802,8 +22904,6 @@
 							_vector3.setFromMatrixPosition( object.matrixWorld )
 							_vector3.setFromMatrixPosition( object.matrixWorld )
 								.applyMatrix4( _projScreenMatrix );
 								.applyMatrix4( _projScreenMatrix );
 
 
-							var material = object.material;
-
 						}
 						}
 
 
 						var geometry = objects.update( object );
 						var geometry = objects.update( object );
@@ -23038,6 +23138,9 @@
 
 
 				material.onBeforeCompile( materialProperties.shader, _this );
 				material.onBeforeCompile( materialProperties.shader, _this );
 
 
+				// Computing code again as onBeforeCompile may have changed the shaders
+				code = programCache.getProgramCode( material, parameters );
+
 				program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
 				program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
 
 
 				materialProperties.program = program;
 				materialProperties.program = program;
@@ -24086,8 +24189,8 @@
 					}
 					}
 
 
 					if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
 					if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
-						! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
-						! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
+						! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
+						! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
 
 
 						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
 						console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
 						return;
 						return;

File diff suppressed because it is too large
+ 385 - 382
build/three.min.js


+ 185 - 82
build/three.module.js

@@ -14716,7 +14716,7 @@ function WebGLBackground( renderer, state, objects, premultipliedAlpha ) {
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-function WebGLBufferRenderer( gl, extensions, info ) {
+function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
 
 
 	var mode;
 	var mode;
 
 
@@ -14736,16 +14736,26 @@ function WebGLBufferRenderer( gl, extensions, info ) {
 
 
 	function renderInstances( geometry, start, count ) {
 	function renderInstances( geometry, start, count ) {
 
 
-		var extension = extensions.get( 'ANGLE_instanced_arrays' );
+		var extension;
 
 
-		if ( extension === null ) {
+		if ( capabilities.isWebGL2 ) {
 
 
-			console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
-			return;
+			extension = gl;
+
+		} else {
+
+			extension = extensions.get( 'ANGLE_instanced_arrays' );
+
+			if ( extension === null ) {
+
+				console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
+				return;
+
+			}
 
 
 		}
 		}
 
 
-		extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount );
+		extension[ capabilities.isWebGL2 ? 'drawArraysInstanced' : 'drawArraysInstancedANGLE' ]( mode, start, count, geometry.maxInstancedCount );
 
 
 		info.update( count, mode, geometry.maxInstancedCount );
 		info.update( count, mode, geometry.maxInstancedCount );
 
 
@@ -14817,6 +14827,8 @@ function WebGLCapabilities( gl, extensions, parameters ) {
 
 
 	}
 	}
 
 
+	var isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
+
 	var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
 	var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
 	var maxPrecision = getMaxPrecision( precision );
 	var maxPrecision = getMaxPrecision( precision );
 
 
@@ -14840,11 +14852,13 @@ function WebGLCapabilities( gl, extensions, parameters ) {
 	var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
 	var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
 
 
 	var vertexTextures = maxVertexTextures > 0;
 	var vertexTextures = maxVertexTextures > 0;
-	var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
+	var floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
 	var floatVertexTextures = vertexTextures && floatFragmentTextures;
 	var floatVertexTextures = vertexTextures && floatFragmentTextures;
 
 
 	return {
 	return {
 
 
+		isWebGL2: isWebGL2,
+
 		getMaxAnisotropy: getMaxAnisotropy,
 		getMaxAnisotropy: getMaxAnisotropy,
 		getMaxPrecision: getMaxPrecision,
 		getMaxPrecision: getMaxPrecision,
 
 
@@ -15117,18 +15131,7 @@ function WebGLGeometries( gl, attributes, info ) {
 
 
 		delete geometries[ geometry.id ];
 		delete geometries[ geometry.id ];
 
 
-		// TODO Remove duplicate code
-
-		var attribute = wireframeAttributes[ geometry.id ];
-
-		if ( attribute ) {
-
-			attributes.remove( attribute );
-			delete wireframeAttributes[ geometry.id ];
-
-		}
-
-		attribute = wireframeAttributes[ buffergeometry.id ];
+		var attribute = wireframeAttributes[ buffergeometry.id ];
 
 
 		if ( attribute ) {
 		if ( attribute ) {
 
 
@@ -15280,7 +15283,7 @@ function WebGLGeometries( gl, attributes, info ) {
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-function WebGLIndexedBufferRenderer( gl, extensions, info ) {
+function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
 
 
 	var mode;
 	var mode;
 
 
@@ -15309,16 +15312,26 @@ function WebGLIndexedBufferRenderer( gl, extensions, info ) {
 
 
 	function renderInstances( geometry, start, count ) {
 	function renderInstances( geometry, start, count ) {
 
 
-		var extension = extensions.get( 'ANGLE_instanced_arrays' );
+		var extension;
 
 
-		if ( extension === null ) {
+		if ( capabilities.isWebGL2 ) {
 
 
-			console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
-			return;
+			extension = gl;
+
+		} else {
+
+			var extension = extensions.get( 'ANGLE_instanced_arrays' );
+
+			if ( extension === null ) {
+
+				console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
+				return;
+
+			}
 
 
 		}
 		}
 
 
-		extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
+		extension[ capabilities.isWebGL2 ? 'drawElementsInstanced' : 'drawElementsInstancedANGLE' ]( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount );
 
 
 		info.update( count, mode, geometry.maxInstancedCount );
 		info.update( count, mode, geometry.maxInstancedCount );
 
 
@@ -16708,7 +16721,7 @@ function unrollLoops( string ) {
 
 
 }
 }
 
 
-function WebGLProgram( renderer, extensions, code, material, shader, parameters ) {
+function WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities ) {
 
 
 	var gl = renderer.context;
 	var gl = renderer.context;
 
 
@@ -16791,7 +16804,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 
 
 	//
 	//
 
 
-	var customExtensions = generateExtensions( material.extensions, parameters, extensions );
+	var customExtensions = capabilities.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );
 
 
 	var customDefines = generateDefines( defines );
 	var customDefines = generateDefines( defines );
 
 
@@ -16879,7 +16892,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
 			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
 
 
 			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
 			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
-			parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
+			parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
 
 
 			'uniform mat4 modelMatrix;',
 			'uniform mat4 modelMatrix;',
 			'uniform mat4 modelViewMatrix;',
 			'uniform mat4 modelViewMatrix;',
@@ -16984,9 +16997,9 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 			parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
 			parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
 
 
 			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
 			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
-			parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
+			parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
 
 
-			parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '',
+			parameters.envMap && ( capabilities.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',
 
 
 			'uniform mat4 viewMatrix;',
 			'uniform mat4 viewMatrix;',
 			'uniform vec3 cameraPosition;',
 			'uniform vec3 cameraPosition;',
@@ -17022,6 +17035,50 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 	vertexShader = unrollLoops( vertexShader );
 	vertexShader = unrollLoops( vertexShader );
 	fragmentShader = unrollLoops( fragmentShader );
 	fragmentShader = unrollLoops( fragmentShader );
 
 
+	if ( capabilities.isWebGL2 && ! material.isRawShaderMaterial ) {
+
+		var isGLSL3ShaderMaterial = false;
+
+		var versionRegex = /^\s*#version\s+300\s+es\s*\n/;
+
+		if ( material.isShaderMaterial &&
+			vertexShader.match( versionRegex ) !== null &&
+			fragmentShader.match( versionRegex ) !== null ) {
+
+			isGLSL3ShaderMaterial = true;
+
+			vertexShader = vertexShader.replace( versionRegex, '' );
+			fragmentShader = fragmentShader.replace( versionRegex, '' );
+
+		}
+
+		// GLSL 3.0 conversion
+		prefixVertex = [
+			'#version 300 es\n',
+			'#define attribute in',
+			'#define varying out',
+			'#define texture2D texture'
+		].join( '\n' ) + '\n' + prefixVertex;
+
+		prefixFragment = [
+			'#version 300 es\n',
+			'#define varying in',
+			isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
+			isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
+			'#define gl_FragDepthEXT gl_FragDepth',
+			'#define texture2D texture',
+			'#define textureCube texture',
+			'#define texture2DProj textureProj',
+			'#define texture2DLodEXT textureLod',
+			'#define texture2DProjLodEXT textureProjLod',
+			'#define textureCubeLodEXT textureLod',
+			'#define texture2DGradEXT textureGrad',
+			'#define texture2DProjGradEXT textureProjGrad',
+			'#define textureCubeGradEXT textureGrad'
+		].join( '\n' ) + '\n' + prefixFragment;
+
+	}
+
 	var vertexGlsl = prefixVertex + vertexShader;
 	var vertexGlsl = prefixVertex + vertexShader;
 	var fragmentGlsl = prefixFragment + fragmentShader;
 	var fragmentGlsl = prefixFragment + fragmentShader;
 
 
@@ -17459,7 +17516,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 
 
 		if ( program === undefined ) {
 		if ( program === undefined ) {
 
 
-			program = new WebGLProgram( renderer, extensions, code, material, shader, parameters );
+			program = new WebGLProgram( renderer, extensions, code, material, shader, parameters, capabilities );
 			programs.push( program );
 			programs.push( program );
 
 
 		}
 		}
@@ -18721,7 +18778,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-function WebGLState( gl, extensions, utils ) {
+function WebGLState( gl, extensions, utils, capabilities ) {
 
 
 	function ColorBuffer() {
 	function ColorBuffer() {
 
 
@@ -19033,7 +19090,7 @@ function WebGLState( gl, extensions, utils ) {
 	var enabledAttributes = new Uint8Array( maxVertexAttributes );
 	var enabledAttributes = new Uint8Array( maxVertexAttributes );
 	var attributeDivisors = new Uint8Array( maxVertexAttributes );
 	var attributeDivisors = new Uint8Array( maxVertexAttributes );
 
 
-	var capabilities = {};
+	var enabledCapabilities = {};
 
 
 	var compressedTextureFormats = null;
 	var compressedTextureFormats = null;
 
 
@@ -19150,9 +19207,9 @@ function WebGLState( gl, extensions, utils ) {
 
 
 		if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
 		if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
 
 
-			var extension = extensions.get( 'ANGLE_instanced_arrays' );
+			var extension = capabilities.isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );
 
 
-			extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute );
+			extension[ capabilities.isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
 			attributeDivisors[ attribute ] = meshPerAttribute;
 			attributeDivisors[ attribute ] = meshPerAttribute;
 
 
 		}
 		}
@@ -19176,10 +19233,10 @@ function WebGLState( gl, extensions, utils ) {
 
 
 	function enable( id ) {
 	function enable( id ) {
 
 
-		if ( capabilities[ id ] !== true ) {
+		if ( enabledCapabilities[ id ] !== true ) {
 
 
 			gl.enable( id );
 			gl.enable( id );
-			capabilities[ id ] = true;
+			enabledCapabilities[ id ] = true;
 
 
 		}
 		}
 
 
@@ -19187,10 +19244,10 @@ function WebGLState( gl, extensions, utils ) {
 
 
 	function disable( id ) {
 	function disable( id ) {
 
 
-		if ( capabilities[ id ] !== false ) {
+		if ( enabledCapabilities[ id ] !== false ) {
 
 
 			gl.disable( id );
 			gl.disable( id );
-			capabilities[ id ] = false;
+			enabledCapabilities[ id ] = false;
 
 
 		}
 		}
 
 
@@ -19599,7 +19656,7 @@ function WebGLState( gl, extensions, utils ) {
 
 
 		}
 		}
 
 
-		capabilities = {};
+		enabledCapabilities = {};
 
 
 		compressedTextureFormats = null;
 		compressedTextureFormats = null;
 
 
@@ -19668,7 +19725,6 @@ function WebGLState( gl, extensions, utils ) {
 
 
 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
 
 
-	var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
 	var _videoTextures = {};
 	var _videoTextures = {};
 	var _canvas;
 	var _canvas;
 
 
@@ -19737,6 +19793,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 	function textureNeedsPowerOfTwo( texture ) {
 	function textureNeedsPowerOfTwo( texture ) {
 
 
+		if ( capabilities.isWebGL2 ) return false;
+
 		return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
 		return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
 			( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
 			( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );
 
 
@@ -19760,6 +19818,30 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 	}
 	}
 
 
+	function getInternalFormat( glFormat, glType ) {
+
+		if ( ! capabilities.isWebGL2 ) return glFormat;
+
+		if ( glFormat === _gl.RGB ) {
+
+			if ( glType === _gl.FLOAT ) return _gl.RGB32F;
+			if ( glType === _gl.HALF_FLOAT ) return _gl.RGB16F;
+			if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGB8;
+
+		}
+
+		if ( glFormat === _gl.RGBA ) {
+
+			if ( glType === _gl.FLOAT ) return _gl.RGBA32F;
+			if ( glType === _gl.HALF_FLOAT ) return _gl.RGBA16F;
+			if ( glType === _gl.UNSIGNED_BYTE ) return _gl.RGBA8;
+
+		}
+
+		return glFormat;
+
+	}
+
 	// Fallback filters for non-power-of-2 textures
 	// Fallback filters for non-power-of-2 textures
 
 
 	function filterFallback( f ) {
 	function filterFallback( f ) {
@@ -19954,7 +20036,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 				var image = cubeImage[ 0 ],
 				var image = cubeImage[ 0 ],
 					isPowerOfTwoImage = isPowerOfTwo( image ),
 					isPowerOfTwoImage = isPowerOfTwo( image ),
 					glFormat = utils.convert( texture.format ),
 					glFormat = utils.convert( texture.format ),
-					glType = utils.convert( texture.type );
+					glType = utils.convert( texture.type ),
+					glInternalFormat = getInternalFormat( glFormat, glType );
 
 
 				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
 				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage );
 
 
@@ -19964,11 +20047,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 						if ( isDataTexture ) {
 						if ( isDataTexture ) {
 
 
-							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
+							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
 
 
 						} else {
 						} else {
 
 
-							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
+							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );
 
 
 						}
 						}
 
 
@@ -19984,7 +20067,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 								if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 								if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 
 
-									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
 								} else {
 								} else {
 
 
@@ -19994,7 +20077,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 							} else {
 							} else {
 
 
-								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
 							}
 							}
 
 
@@ -20082,7 +20165,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 		if ( extension ) {
 		if ( extension ) {
 
 
 			if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
 			if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
-			if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
+			if ( texture.type === HalfFloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;
 
 
 			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
 			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
 
 
@@ -20126,7 +20209,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 		var isPowerOfTwoImage = isPowerOfTwo( image ),
 		var isPowerOfTwoImage = isPowerOfTwo( image ),
 			glFormat = utils.convert( texture.format ),
 			glFormat = utils.convert( texture.format ),
-			glType = utils.convert( texture.type );
+			glType = utils.convert( texture.type ),
+			glInternalFormat = getInternalFormat( glFormat, glType );
 
 
 		setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
 		setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage );
 
 
@@ -20136,21 +20220,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 			// populate depth texture with dummy data
 			// populate depth texture with dummy data
 
 
-			var internalFormat = _gl.DEPTH_COMPONENT;
+			glInternalFormat = _gl.DEPTH_COMPONENT;
 
 
 			if ( texture.type === FloatType ) {
 			if ( texture.type === FloatType ) {
 
 
-				if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
-				internalFormat = _gl.DEPTH_COMPONENT32F;
+				if ( ! capabilities.isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' );
+				glInternalFormat = _gl.DEPTH_COMPONENT32F;
 
 
-			} else if ( _isWebGL2 ) {
+			} else if ( capabilities.isWebGL2 ) {
 
 
 				// WebGL 2.0 requires signed internalformat for glTexImage2D
 				// WebGL 2.0 requires signed internalformat for glTexImage2D
-				internalFormat = _gl.DEPTH_COMPONENT16;
+				glInternalFormat = _gl.DEPTH_COMPONENT16;
 
 
 			}
 			}
 
 
-			if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) {
+			if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
 
 
 				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 				// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
 				// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT
@@ -20170,7 +20254,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 			// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
 			// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)
 			if ( texture.format === DepthStencilFormat ) {
 			if ( texture.format === DepthStencilFormat ) {
 
 
-				internalFormat = _gl.DEPTH_STENCIL;
+				glInternalFormat = _gl.DEPTH_STENCIL;
 
 
 				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 				// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are
 				// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
 				// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.
@@ -20186,7 +20270,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 			}
 			}
 
 
-			state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null );
+			state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );
 
 
 		} else if ( texture.isDataTexture ) {
 		} else if ( texture.isDataTexture ) {
 
 
@@ -20199,7 +20283,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
 					mipmap = mipmaps[ i ];
 					mipmap = mipmaps[ i ];
-					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
 				}
 				}
 
 
@@ -20208,7 +20292,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 			} else {
 			} else {
 
 
-				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
+				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
 				textureProperties.__maxMipLevel = 0;
 				textureProperties.__maxMipLevel = 0;
 
 
 			}
 			}
@@ -20223,7 +20307,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 					if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 					if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
 
 
-						state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+						state.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
 
 					} else {
 					} else {
 
 
@@ -20233,7 +20317,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 				} else {
 				} else {
 
 
-					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
 
 				}
 				}
 
 
@@ -20254,7 +20338,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
 
 					mipmap = mipmaps[ i ];
 					mipmap = mipmaps[ i ];
-					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
+					state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );
 
 
 				}
 				}
 
 
@@ -20263,7 +20347,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 			} else {
 			} else {
 
 
-				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
+				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
 				textureProperties.__maxMipLevel = 0;
 				textureProperties.__maxMipLevel = 0;
 
 
 			}
 			}
@@ -20289,7 +20373,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 
 		var glFormat = utils.convert( renderTarget.texture.format );
 		var glFormat = utils.convert( renderTarget.texture.format );
 		var glType = utils.convert( renderTarget.texture.type );
 		var glType = utils.convert( renderTarget.texture.type );
-		state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
+		var glInternalFormat = getInternalFormat( glFormat, glType );
+		state.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
 		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
@@ -20534,7 +20619,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
  * @author thespite / http://www.twitter.com/thespite
  * @author thespite / http://www.twitter.com/thespite
  */
  */
 
 
-function WebGLUtils( gl, extensions ) {
+function WebGLUtils( gl, extensions, capabilities ) {
 
 
 	function convert( p ) {
 	function convert( p ) {
 
 
@@ -20566,6 +20651,8 @@ function WebGLUtils( gl, extensions ) {
 
 
 		if ( p === HalfFloatType ) {
 		if ( p === HalfFloatType ) {
 
 
+			if ( capabilities.isWebGL2 ) return gl.HALF_FLOAT;
+
 			extension = extensions.get( 'OES_texture_half_float' );
 			extension = extensions.get( 'OES_texture_half_float' );
 
 
 			if ( extension !== null ) return extension.HALF_FLOAT_OES;
 			if ( extension !== null ) return extension.HALF_FLOAT_OES;
@@ -20655,6 +20742,13 @@ function WebGLUtils( gl, extensions ) {
 
 
 		if ( p === MinEquation || p === MaxEquation ) {
 		if ( p === MinEquation || p === MaxEquation ) {
 
 
+			if ( capabilities.isWebGL2 ) {
+
+				if ( p === MinEquation ) return gl.MIN;
+				if ( p === MaxEquation ) return gl.MAX;
+
+			}
+
 			extension = extensions.get( 'EXT_blend_minmax' );
 			extension = extensions.get( 'EXT_blend_minmax' );
 
 
 			if ( extension !== null ) {
 			if ( extension !== null ) {
@@ -20668,6 +20762,8 @@ function WebGLUtils( gl, extensions ) {
 
 
 		if ( p === UnsignedInt248Type ) {
 		if ( p === UnsignedInt248Type ) {
 
 
+			if ( capabilities.isWebGL2 ) return gl.UNSIGNED_INT_24_8;
+
 			extension = extensions.get( 'WEBGL_depth_texture' );
 			extension = extensions.get( 'WEBGL_depth_texture' );
 
 
 			if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
 			if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
@@ -21799,20 +21895,26 @@ function WebGLRenderer( parameters ) {
 	function initGLContext() {
 	function initGLContext() {
 
 
 		extensions = new WebGLExtensions( _gl );
 		extensions = new WebGLExtensions( _gl );
-		extensions.get( 'WEBGL_depth_texture' );
-		extensions.get( 'OES_texture_float' );
-		extensions.get( 'OES_texture_float_linear' );
-		extensions.get( 'OES_texture_half_float' );
-		extensions.get( 'OES_texture_half_float_linear' );
-		extensions.get( 'OES_standard_derivatives' );
-		extensions.get( 'OES_element_index_uint' );
-		extensions.get( 'ANGLE_instanced_arrays' );
-
-		utils = new WebGLUtils( _gl, extensions );
 
 
 		capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 		capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 
 
-		state = new WebGLState( _gl, extensions, utils );
+		if ( ! capabilities.isWebGL2 ) {
+
+			extensions.get( 'WEBGL_depth_texture' );
+			extensions.get( 'OES_texture_float' );
+			extensions.get( 'OES_texture_half_float' );
+			extensions.get( 'OES_texture_half_float_linear' );
+			extensions.get( 'OES_standard_derivatives' );
+			extensions.get( 'OES_element_index_uint' );
+			extensions.get( 'ANGLE_instanced_arrays' );
+
+		}
+
+		extensions.get( 'OES_texture_float_linear' );
+
+		utils = new WebGLUtils( _gl, extensions, capabilities );
+
+		state = new WebGLState( _gl, extensions, utils, capabilities );
 		state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
 		state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) );
 		state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
 		state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
 
 
@@ -21829,8 +21931,8 @@ function WebGLRenderer( parameters ) {
 
 
 		background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
 		background = new WebGLBackground( _this, state, objects, _premultipliedAlpha );
 
 
-		bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info );
-		indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info );
+		bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );
+		indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
 
 
 		info.programs = programCache.programs;
 		info.programs = programCache.programs;
 
 
@@ -22367,7 +22469,7 @@ function WebGLRenderer( parameters ) {
 
 
 	function setupVertexAttributes( material, program, geometry ) {
 	function setupVertexAttributes( material, program, geometry ) {
 
 
-		if ( geometry && geometry.isInstancedBufferGeometry ) {
+		if ( geometry && geometry.isInstancedBufferGeometry & ! capabilities.isWebGL2 ) {
 
 
 			if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 			if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 
 
@@ -22796,8 +22898,6 @@ function WebGLRenderer( parameters ) {
 						_vector3.setFromMatrixPosition( object.matrixWorld )
 						_vector3.setFromMatrixPosition( object.matrixWorld )
 							.applyMatrix4( _projScreenMatrix );
 							.applyMatrix4( _projScreenMatrix );
 
 
-						var material = object.material;
-
 					}
 					}
 
 
 					var geometry = objects.update( object );
 					var geometry = objects.update( object );
@@ -23032,6 +23132,9 @@ function WebGLRenderer( parameters ) {
 
 
 			material.onBeforeCompile( materialProperties.shader, _this );
 			material.onBeforeCompile( materialProperties.shader, _this );
 
 
+			// Computing code again as onBeforeCompile may have changed the shaders
+			code = programCache.getProgramCode( material, parameters );
+
 			program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
 			program = programCache.acquireProgram( material, materialProperties.shader, parameters, code );
 
 
 			materialProperties.program = program;
 			materialProperties.program = program;
@@ -24080,8 +24183,8 @@ function WebGLRenderer( parameters ) {
 				}
 				}
 
 
 				if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
 				if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)
-					! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
-					! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
+					! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox
+					! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {
 
 
 					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
 					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
 					return;
 					return;

+ 5 - 5
docs/api/animation/PropertyMixer.html

@@ -18,7 +18,7 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]( binding, typeName, valueSize )</h3>
+		<h3>[name]( [param:PropertyBinding binding], [param:String typeName], [param:Number valueSize] )</h3>
 		<p>
 		<p>
 			-- binding <br />
 			-- binding <br />
 			-- typeName <br />
 			-- typeName <br />
@@ -29,12 +29,12 @@
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
 
 
-		<h3>[property:Number binding]</h3>
+		<h3>[property:PropertyBinding binding]</h3>
 		<p>
 		<p>
 
 
 		</p>
 		</p>
 
 
-		<h3>[property:Number buffer]</h3>
+		<h3>[property:TypedArray buffer]</h3>
 		<p>
 		<p>
 			Buffer with size [page:PropertyMixer valueSize] * 4. <br /><br />
 			Buffer with size [page:PropertyMixer valueSize] * 4. <br /><br />
 			This has the layout: [ incoming | accu0 | accu1 | orig ]<br /><br />
 			This has the layout: [ incoming | accu0 | accu1 | orig ]<br /><br />
@@ -67,14 +67,14 @@
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 
 
-		<h3>[method:null accumulate]( accuIndex, weight )</h3>
+		<h3>[method:null accumulate]( [param:Number accuIndex], [param:Number weight] )</h3>
 		<p>
 		<p>
 			Accumulate data in [page:PropertyMixer.buffer buffer][accuIndex] 'incoming' region into 'accu[i]'.<br />
 			Accumulate data in [page:PropertyMixer.buffer buffer][accuIndex] 'incoming' region into 'accu[i]'.<br />
 
 
 			If weight is *0* this does nothing.
 			If weight is *0* this does nothing.
 		</p>
 		</p>
 
 
-		<h3>[method:null apply]( accuIndex )</h3>
+		<h3>[method:null apply]( [param:Number accuIndex] )</h3>
 		<p>
 		<p>
 			Apply the state of [page:PropertyMixer.buffer buffer] 'accu[i]' to the binding when accus differ.
 			Apply the state of [page:PropertyMixer.buffer buffer] 'accu[i]' to the binding when accus differ.
 		</p>
 		</p>

+ 1 - 1
docs/api/cameras/Camera.html

@@ -64,7 +64,7 @@
 			Return a new camera with the same properties as this one.
 			Return a new camera with the same properties as this one.
 		</p>
 		</p>
 
 
-		<h3>[method:Camera copy]( [param:Camera source] )</h3>
+		<h3>[method:Camera copy]( [param:Camera source], [param:Boolean recursive] )</h3>
 		<p>
 		<p>
 		Copy the properties from the source camera into this one.
 		Copy the properties from the source camera into this one.
 		</p>
 		</p>

+ 1 - 1
docs/api/cameras/StereoCamera.html

@@ -55,7 +55,7 @@
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
-		<h3>[method:null update]( camera )</h3>
+		<h3>[method:null update]( [param:PerspectiveCamera camera] )</h3>
 		<p>
 		<p>
 		Update the stereo cameras based on the camera passed in.
 		Update the stereo cameras based on the camera passed in.
 		</p>
 		</p>

+ 15 - 15
docs/api/core/BufferAttribute.html

@@ -131,28 +131,28 @@
 		<h3>[method:null copyAt] ( [param:Integer index1], [param:BufferAttribute bufferAttribute], [param:Integer index2] ) </h3>
 		<h3>[method:null copyAt] ( [param:Integer index1], [param:BufferAttribute bufferAttribute], [param:Integer index2] ) </h3>
 		<p>Copy a vector from bufferAttribute[index2] to [page:BufferAttribute.array array][index1].</p>
 		<p>Copy a vector from bufferAttribute[index2] to [page:BufferAttribute.array array][index1].</p>
 
 
-		<h3>[method:BufferAttribute copyColorsArray]( colors ) </h3>
+		<h3>[method:BufferAttribute copyColorsArray]( [param:Array colors] ) </h3>
 		<p>Copy an array representing RGB color values into [page:BufferAttribute.array array].</p>
 		<p>Copy an array representing RGB color values into [page:BufferAttribute.array array].</p>
 
 
-		<h3>[method:BufferAttribute copyVector2sArray]( vectors ) </h3>
+		<h3>[method:BufferAttribute copyVector2sArray]( [param:Array vectors] ) </h3>
 		<p>Copy an array representing [page:Vector2]s into [page:BufferAttribute.array array].</p>
 		<p>Copy an array representing [page:Vector2]s into [page:BufferAttribute.array array].</p>
 
 
-		<h3>[method:BufferAttribute copyVector3sArray]( vectors ) </h3>
+		<h3>[method:BufferAttribute copyVector3sArray]( [param:Array vectors] ) </h3>
 		<p>Copy an array representing [page:Vector3]s into [page:BufferAttribute.array array].</p>
 		<p>Copy an array representing [page:Vector3]s into [page:BufferAttribute.array array].</p>
 
 
-		<h3>[method:BufferAttribute copyVector4sArray]( vectors ) </h3>
+		<h3>[method:BufferAttribute copyVector4sArray]( [param:Array vectors] ) </h3>
 		<p>Copy an array representing [page:Vector4]s into [page:BufferAttribute.array array].</p>
 		<p>Copy an array representing [page:Vector4]s into [page:BufferAttribute.array array].</p>
 
 
-		<h3>[method:Number getX]( index ) </h3>
+		<h3>[method:Number getX]( [param:Integer index] ) </h3>
 		<p>Returns the x component of the vector at the given index.</p>
 		<p>Returns the x component of the vector at the given index.</p>
 
 
-		<h3>[method:Number getY]( index ) </h3>
+		<h3>[method:Number getY]( [param:Integer index] ) </h3>
 		<p>Returns the y component of the vector at the given index.</p>
 		<p>Returns the y component of the vector at the given index.</p>
 
 
-		<h3>[method:Number getZ]( index ) </h3>
+		<h3>[method:Number getZ]( [param:Integer index] ) </h3>
 		<p>Returns the z component of the vector at the given index.</p>
 		<p>Returns the z component of the vector at the given index.</p>
 
 
-		<h3>[method:Number getW]( index ) </h3>
+		<h3>[method:Number getW]( [param:Integer index] ) </h3>
 		<p>Returns the w component of the vector at the given index.</p>
 		<p>Returns the w component of the vector at the given index.</p>
 
 
 		<h3>[method:null onUpload]( [param:Function callback] ) </h3>
 		<h3>[method:null onUpload]( [param:Function callback] ) </h3>
@@ -185,25 +185,25 @@
 		<h3>[method:BufferAttribute setDynamic] ( [param:Boolean value] ) </h3>
 		<h3>[method:BufferAttribute setDynamic] ( [param:Boolean value] ) </h3>
 		<p>Set [page:BufferAttribute.dynamic dynamic] to value.</p>
 		<p>Set [page:BufferAttribute.dynamic dynamic] to value.</p>
 
 
-		<h3>[method:BufferAttribute setX]( index, x ) </h3>
+		<h3>[method:BufferAttribute setX]( [param:Integer index], [param:Float x] ) </h3>
 		<p>Sets the x component of the vector at the given index.</p>
 		<p>Sets the x component of the vector at the given index.</p>
 
 
-		<h3>[method:BufferAttribute setY]( index, y ) </h3>
+		<h3>[method:BufferAttribute setY]( [param:Integer index], [param:Float y] ) </h3>
 		<p>Sets the y component of the vector at the given index.</p>
 		<p>Sets the y component of the vector at the given index.</p>
 
 
-		<h3>[method:BufferAttribute setZ]( index, z ) </h3>
+		<h3>[method:BufferAttribute setZ]( [param:Integer index], [param:Float z] ) </h3>
 		<p>Sets the z component of the vector at the given index.</p>
 		<p>Sets the z component of the vector at the given index.</p>
 
 
-		<h3>[method:BufferAttribute setW]( index, w ) </h3>
+		<h3>[method:BufferAttribute setW]( [param:Integer index], [param:Float w] ) </h3>
 		<p>Sets the w component of the vector at the given index.</p>
 		<p>Sets the w component of the vector at the given index.</p>
 
 
-		<h3>[method:BufferAttribute setXY]( index, x, y ) </h3>
+		<h3>[method:BufferAttribute setXY]( [param:Integer index], [param:Float x], [param:Float y] ) </h3>
 		<p>Sets the x and y components of the vector at the given index.</p>
 		<p>Sets the x and y components of the vector at the given index.</p>
 
 
-		<h3>[method:BufferAttribute setXYZ]( index, x, y, z ) </h3>
+		<h3>[method:BufferAttribute setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] ) </h3>
 		<p>Sets the x, y and z components of the vector at the given index.</p>
 		<p>Sets the x, y and z components of the vector at the given index.</p>
 
 
-		<h3>[method:BufferAttribute setXYZW]( index, x, y, z, w ) </h3>
+		<h3>[method:BufferAttribute setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] ) </h3>
 		<p>Sets the x, y, z and w components of the vector at the given index.</p>
 		<p>Sets the x, y, z and w components of the vector at the given index.</p>
 
 
 
 

+ 2 - 2
docs/api/core/DirectGeometry.html

@@ -91,13 +91,13 @@
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
-		<h3>[property:null computeGroups]( [page:Geometry geometry] )</h3>
+		<h3>[property:null computeGroups]( [param:Geometry geometry] )</h3>
 		<p>
 		<p>
 			Compute the parts of the geometry that have different materialIndex.
 			Compute the parts of the geometry that have different materialIndex.
 			See [page:BufferGeometry.groups].
 			See [page:BufferGeometry.groups].
 		</p>
 		</p>
 
 
-		<h3>[property:null fromGeometry]( [page:Geometry geometry] )</h3>
+		<h3>[property:null fromGeometry]( [param:Geometry geometry] )</h3>
 		<p>Pass in a [page:Geometry] instance for conversion.</p>
 		<p>Pass in a [page:Geometry] instance for conversion.</p>
 
 
 
 

+ 3 - 3
docs/api/core/InterleavedBuffer.html

@@ -91,15 +91,15 @@
 			Set [page:InterleavedBuffer.dynamic dynamic] to value.
 			Set [page:InterleavedBuffer.dynamic dynamic] to value.
 		</p>
 		</p>
 
 
-		<h3>[method:InterleavedBuffer copy]( source ) </h3>
+		<h3>[method:InterleavedBuffer copy]( [param:InterleavedBuffer source] ) </h3>
 		<p>
 		<p>
 		 Copies another [name] to this [name].
 		 Copies another [name] to this [name].
 		</p>
 		</p>
 
 
-		<h3>[method:InterleavedBuffer copyAt]( index1, attribute, index2 ) </h3>
+		<h3>[method:InterleavedBuffer copyAt]( [param:Integer index1], [param:InterleavedBuffer attribute], [param:Integer index2] ) </h3>
 		<p>Copies data from attribute[index2] to [page:InterleavedBuffer.array array][index1].</p>
 		<p>Copies data from attribute[index2] to [page:InterleavedBuffer.array array][index1].</p>
 
 
-		<h3>[method:InterleavedBuffer set]( value, offset ) </h3>
+		<h3>[method:InterleavedBuffer set]( [param:TypedArray value], [param:Integer offset] ) </h3>
 		<p>
 		<p>
 			value - The source (typed) array.<br/>
 			value - The source (typed) array.<br/>
 			offset - The offset into the target array at which to begin writing values from the source array. Default is *0*.<br/><br />
 			offset - The offset into the target array at which to begin writing values from the source array. Default is *0*.<br/><br />

+ 11 - 11
docs/api/core/InterleavedBufferAttribute.html

@@ -62,37 +62,37 @@
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
-		<h3>[method:Number getX]( index ) </h3>
+		<h3>[method:Number getX]( [param:Integer index] ) </h3>
 		<p>Returns the x component of the item at the given index.</p>
 		<p>Returns the x component of the item at the given index.</p>
 
 
-		<h3>[method:Number getY]( index ) </h3>
+		<h3>[method:Number getY]( [param:Integer index] ) </h3>
 		<p>Returns the y component of the item at the given index.</p>
 		<p>Returns the y component of the item at the given index.</p>
 
 
-		<h3>[method:Number getZ]( index ) </h3>
+		<h3>[method:Number getZ]( [param:Integer index] ) </h3>
 		<p>Returns the z component of the item at the given index.</p>
 		<p>Returns the z component of the item at the given index.</p>
 
 
-		<h3>[method:Number getW]( index ) </h3>
+		<h3>[method:Number getW]( [param:Integer index] ) </h3>
 		<p>Returns the w component of the item at the given index.</p>
 		<p>Returns the w component of the item at the given index.</p>
 
 
-		<h3>[method:null setX]( index, x ) </h3>
+		<h3>[method:null setX]( [param:Integer index], [param:Float x] ) </h3>
 		<p>Sets the x component of the item at the given index.</p>
 		<p>Sets the x component of the item at the given index.</p>
 
 
-		<h3>[method:null setY]( index, y ) </h3>
+		<h3>[method:null setY]( [param:Integer index], [param:Float y] ) </h3>
 		<p>Sets the y component of the item at the given index.</p>
 		<p>Sets the y component of the item at the given index.</p>
 
 
-		<h3>[method:null setZ]( index, z ) </h3>
+		<h3>[method:null setZ]( [param:Integer index], [param:Float z] ) </h3>
 		<p>Sets the z component of the item at the given index.</p>
 		<p>Sets the z component of the item at the given index.</p>
 
 
-		<h3>[method:null setW]( index, w ) </h3>
+		<h3>[method:null setW]( [param:Integer index], [param:Float w] ) </h3>
 		<p>Sets the w component of the item at the given index.</p>
 		<p>Sets the w component of the item at the given index.</p>
 
 
-		<h3>[method:null setXY]( index, x, y ) </h3>
+		<h3>[method:null setXY]( [param:Integer index], [param:Float x], [param:Float y] ) </h3>
 		<p>Sets the x and y components of the item at the given index.</p>
 		<p>Sets the x and y components of the item at the given index.</p>
 
 
-		<h3>[method:null setXYZ]( index, x, y, z ) </h3>
+		<h3>[method:null setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] ) </h3>
 		<p>Sets the x, y and z components of the item at the given index.</p>
 		<p>Sets the x, y and z components of the item at the given index.</p>
 
 
-		<h3>[method:null setXYZW]( index, x, y, z, w ) </h3>
+		<h3>[method:null setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] ) </h3>
 		<p>Sets the x, y, z and w components of the item at the given index.</p>
 		<p>Sets the x, y, z and w components of the item at the given index.</p>
 
 
 
 

+ 1 - 1
docs/api/core/Object3D.html

@@ -39,7 +39,7 @@
 		<h3>[property:Boolean frustumCulled]</h3>
 		<h3>[property:Boolean frustumCulled]</h3>
 		<p>
 		<p>
 		When this is set, it checks every frame if the object is in the frustum of the camera before rendering the object.
 		When this is set, it checks every frame if the object is in the frustum of the camera before rendering the object.
-		Otherwise the object gets renderered every frame even if it isn't visible. Default is *true*.
+		Otherwise the object gets rendered every frame even if it isn't visible. Default is *true*.
 		</p>
 		</p>
 
 
 		<h3>[property:Integer id]</h3>
 		<h3>[property:Integer id]</h3>

+ 2 - 2
docs/api/core/Raycaster.html

@@ -78,7 +78,7 @@
 		[page:Vector3 origin] — The origin vector where the ray casts from.<br />
 		[page:Vector3 origin] — The origin vector where the ray casts from.<br />
 		[page:Vector3 direction] — The direction vector that gives direction to the ray. Should be normalized.<br />
 		[page:Vector3 direction] — The direction vector that gives direction to the ray. Should be normalized.<br />
 		[page:Float near] — All results returned are further away than near. Near can't be negative. Default value is 0.<br />
 		[page:Float near] — All results returned are further away than near. Near can't be negative. Default value is 0.<br />
-		[page:Float far] — All results returned are closer then far. Far can't be lower then near . Default value is Infinity.
+		[page:Float far] — All results returned are closer than far. Far can't be lower than near. Default value is Infinity.
 		</p>
 		</p>
 		<p>
 		<p>
 		This creates a new raycaster object.<br />
 		This creates a new raycaster object.<br />
@@ -144,7 +144,7 @@
 		Updates the ray with a new origin and direction.
 		Updates the ray with a new origin and direction.
 		</p>
 		</p>
 
 
-		<h3>[method:Array intersectObject]( [page:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
+		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 		<p>
 		[page:Object3D object] — The object to check for intersection with the ray.<br />
 		[page:Object3D object] — The object to check for intersection with the ray.<br />
 		[page:Boolean recursive] — If true, it also checks all descendants. Otherwise it only checks intersecton with the object. Default is false.<br />
 		[page:Boolean recursive] — If true, it also checks all descendants. Otherwise it only checks intersecton with the object. Default is false.<br />

+ 1 - 1
docs/api/helpers/Box3Helper.html

@@ -50,7 +50,7 @@
 		<p>See the base [page:LineSegments] class for common methods.</p>
 		<p>See the base [page:LineSegments] class for common methods.</p>
 
 
 
 
-		<h3>[method:void updateMatrixWorld]( force )</h3>
+		<h3>[method:void updateMatrixWorld]( [param:Boolean force] )</h3>
 		<p>
 		<p>
 			This overrides the method in the base [page:Object3D] class so that it
 			This overrides the method in the base [page:Object3D] class so that it
 			also updates the wireframe box to the extent of the [page:Box3Helper.box .box]
 			also updates the wireframe box to the extent of the [page:Box3Helper.box .box]

+ 1 - 1
docs/api/helpers/PlaneHelper.html

@@ -51,7 +51,7 @@
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<p>See the base [page:LineSegments] class for common methods.</p>
 		<p>See the base [page:LineSegments] class for common methods.</p>
 
 
-		<h3>[method:void updateMatrixWorld]( force )</h3>
+		<h3>[method:void updateMatrixWorld]( [param:Boolean force] )</h3>
 		<p>
 		<p>
 			This overrides the method in the base [page:Object3D] class so that it also
 			This overrides the method in the base [page:Object3D] class so that it also
 			updates the helper object according to the [page:PlaneHelper.plane .plane] and
 			updates the helper object according to the [page:PlaneHelper.plane .plane] and

+ 16 - 14
docs/api/lights/DirectionalLight.html

@@ -52,10 +52,10 @@
 		</p>
 		</p>
 
 
 		<code>
 		<code>
-// White directional light at half intensity shining from the top.
-var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
-scene.add( directionalLight );
-	</code>
+		// White directional light at half intensity shining from the top.
+		var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
+		scene.add( directionalLight );
+		</code>
 
 
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
@@ -104,26 +104,28 @@ scene.add( directionalLight );
 
 
 			*Note*: For the target's position to be changed to anything other than the default,
 			*Note*: For the target's position to be changed to anything other than the default,
 			it must be added to the [page:Scene scene] using
 			it must be added to the [page:Scene scene] using
-			<code>
-				scene.add( light.target );
-			</code>
-
+		</p>
+		<code>
+		scene.add( light.target );
+		</code>
+		<p>
 			This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets automatically
 			This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets automatically
 			updated each frame.<br /><br />
 			updated each frame.<br /><br />
 
 
 			It is also possible to set the target to be another object in the scene (anything with a
 			It is also possible to set the target to be another object in the scene (anything with a
 			[page:Object3D.position position] property), like so:
 			[page:Object3D.position position] property), like so:
-			<code>
-	var targetObject = new THREE.Object3D();
-	scene.add(targetObject);
+		</p>
+		<code>
+		var targetObject = new THREE.Object3D();
+		scene.add(targetObject);
 
 
-	light.target = targetObject;
-			</code>
+		light.target = targetObject;
+		</code>
+		<p>
 			The directionalLight will now track the target object.
 			The directionalLight will now track the target object.
 		</p>
 		</p>
 
 
 
 
-
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 		See the base [page:Light Light] class for common methods.
 		See the base [page:Light Light] class for common methods.

+ 0 - 13
docs/api/loaders/TextureLoader.html

@@ -85,12 +85,6 @@
 		<p>The base path from which files will be loaded. See [page:.setPath]. Default is *undefined*.</p>
 		<p>The base path from which files will be loaded. See [page:.setPath]. Default is *undefined*.</p>
 
 
 
 
-		<h3>[property:String withCredentials]</h3>
-		<p>
-			Whether the XMLHttpRequest uses credentials - see [page:.setWithCredentials].
-			Default is *undefined*.
-		</p>
-
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 		<h3>[method:Texture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
 		<h3>[method:Texture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
@@ -114,13 +108,6 @@
 			you are loading many models from the same directory.
 			you are loading many models from the same directory.
 		</p>
 		</p>
 
 
-		<h3>[method:FileLoader setWithCredentials]( [param:Boolean value] )</h3>
-		<p>
-		Whether the XMLHttpRequest uses credentials such as cookies, authorization headers or
-		TLS client certificates. See
-		[link:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials XMLHttpRequest.withCredentials].<br />
-		Note that this has no effect if you are loading files locally or from the same domain.
-		</p>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 

+ 2 - 2
docs/api/materials/LineBasicMaterial.html

@@ -75,8 +75,8 @@ var material = new THREE.LineBasicMaterial( {
 		<p>
 		<p>
 			Controls line thickness. Default is *1*.<br /><br />
 			Controls line thickness. Default is *1*.<br /><br />
 
 
-			Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-			with the [page:WebGLRenderer WebGL] renderer on Windows platforms linewidth will
+			Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+			with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
 			always be 1 regardless of the set value.
 			always be 1 regardless of the set value.
 		</p>
 		</p>
 
 

+ 2 - 2
docs/api/materials/LineDashedMaterial.html

@@ -70,8 +70,8 @@ var material = new THREE.LineDashedMaterial( {
 		<p>
 		<p>
 			Controls line thickness. Default is *1*.<br /><br />
 			Controls line thickness. Default is *1*.<br /><br />
 
 
-			Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-			with the [page:WebGLRenderer WebGL] renderer on Windows platforms linewidth will
+			Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+			with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
 			always be 1 regardless of the set value.
 			always be 1 regardless of the set value.
 		</p>
 		</p>
 
 

+ 1 - 2
docs/api/materials/Material.html

@@ -162,8 +162,7 @@
 
 
 		<h3>[property:Boolean needsUpdate]</h3>
 		<h3>[property:Boolean needsUpdate]</h3>
 		<p>
 		<p>
-		Specifies that the material needs to be updated at the WebGL level.
-		Set it to true if you made changes that need to be reflected in WebGL.<br />
+		Specifies that the material needs to be recompiled.<br />
 		This property is automatically set to *true* when instancing a new material.
 		This property is automatically set to *true* when instancing a new material.
 		</p>
 		</p>
 
 

+ 3 - 2
docs/api/materials/MeshBasicMaterial.html

@@ -151,8 +151,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshDepthMaterial.html

@@ -107,8 +107,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshLambertMaterial.html

@@ -177,8 +177,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshNormalMaterial.html

@@ -68,8 +68,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshPhongMaterial.html

@@ -247,8 +247,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshStandardMaterial.html

@@ -274,8 +274,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 1 - 1
docs/api/materials/PointsMaterial.html

@@ -55,7 +55,7 @@ var starField = new THREE.Points( starsGeometry, starsMaterial );
 scene.add( starField );
 scene.add( starField );
 		</code>
 		</code>
 
 
-		<h3>[name]( [page:Object parameters] )</h3>
+		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
 		<p>
 			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
 			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
 			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />
 			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />

+ 6 - 4
docs/api/materials/ShaderMaterial.html

@@ -371,8 +371,9 @@ this.extensions = {
 		<h3>[property:Float linewidth]</h3>
 		<h3>[property:Float linewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 
 
@@ -443,8 +444,9 @@ this.extensions = {
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile)
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
 
 

+ 1 - 1
docs/api/materials/SpriteMaterial.html

@@ -37,7 +37,7 @@ scene.add( sprite );
 		</code>
 		</code>
 
 
 
 
-		<h3>[name]( [page:Object parameters] )</h3>
+		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
 		<p>
 			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
 			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
 			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />
 			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />

+ 2 - 2
docs/api/math/Box2.html

@@ -23,7 +23,7 @@
 		[page:Vector2 min] - (optional) [page:Vector2] representing the lower (x, y) boundary of the box.
 		[page:Vector2 min] - (optional) [page:Vector2] representing the lower (x, y) boundary of the box.
 		Default is ( + Infinity, + Infinity ).<br>
 		Default is ( + Infinity, + Infinity ).<br>
 
 
-		[page:Vector2 max] - (optional) [page:Vector2] representing the lower upper (x, y) boundary of the box.
+		[page:Vector2 max] - (optional) [page:Vector2] representing the upper (x, y) boundary of the box.
 		Default is ( - Infinity, - Infinity ).<br /><br />
 		Default is ( - Infinity, - Infinity ).<br /><br />
 
 
 		Creates a [name] bounded by min and max.
 		Creates a [name] bounded by min and max.
@@ -172,7 +172,7 @@
 		<h3>[method:Box2 set]( [param:Vector2 min], [param:Vector2 max] )</h3>
 		<h3>[method:Box2 set]( [param:Vector2 min], [param:Vector2 max] )</h3>
 		<p>
 		<p>
 			[page:Vector2 min] - (required ) [page:Vector2] representing the lower (x, y) boundary of the box. <br>
 			[page:Vector2 min] - (required ) [page:Vector2] representing the lower (x, y) boundary of the box. <br>
-			[page:Vector2 max]  - (required) [page:Vector2] representing the lower upper (x, y) boundary of the box. <br /><br />
+			[page:Vector2 max]  - (required) [page:Vector2] representing the upper (x, y) boundary of the box. <br /><br />
 
 
 			Sets the lower and upper (x, y) boundaries of this box.
 			Sets the lower and upper (x, y) boundaries of this box.
 		</p>
 		</p>

+ 1 - 1
docs/api/math/Cylindrical.html

@@ -50,7 +50,7 @@
 			and [page:.y y] properties to this cylindrical.
 			and [page:.y y] properties to this cylindrical.
 		</p>
 		</p>
 
 
-		<h3>[method:Cylindrical set]( [param:Float radius], [param:Float phi], [param:Float theta] )</h3>
+		<h3>[method:Cylindrical set]( [param:Float radius], [param:Float theta], [param:Float y] )</h3>
 		<p>Sets values of this cylindrical's [page:.radius radius], [page:.theta theta]
 		<p>Sets values of this cylindrical's [page:.radius radius], [page:.theta theta]
 		and [page:.y y] properties.</p>
 		and [page:.y y] properties.</p>
 
 

+ 7 - 2
docs/api/math/Euler.html

@@ -176,8 +176,13 @@
 		Returns an array of the form [[page:.x x], [page:.y y], [page:.z z], [page:.order order ]].
 		Returns an array of the form [[page:.x x], [page:.y y], [page:.z z], [page:.order order ]].
 		</p>
 		</p>
 
 
-		<h3>[method:Vector3 toVector3]()</h3>
-		<p>Returns the Euler's [page:.x x], [page:.y y] and [page:.z z] properties as a [page:Vector3].</p>
+		<h3>[method:Vector3 toVector3]( [param:Vector3 optionalResult] )</h3>
+		<p>
+			[page:Vector3 optionalResult] — (optional) If specified, the result will be copied into this Vector,
+			otherwise a new one will be created. <br /><br />
+
+			Returns the Euler's [page:.x x], [page:.y y] and [page:.z z] properties as a [page:Vector3].
+		</p>
 
 
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 1 - 6
docs/api/math/Math.html

@@ -54,12 +54,7 @@
 		and [page:Float t] = 1 will return [page:Float y].
 		and [page:Float t] = 1 will return [page:Float y].
 		</p>
 		</p>
 
 
-		<h3>[method:Float mapLinear](
-			[page:Float x],
-			[page:Float a1],
-			[page:Float a2],
-			[page:Float b1],
-			[page:Float b2] )</h3>
+		<h3>[method:Float mapLinear]( [param:Float x], [param:Float a1], [param:Float a2], [param:Float b1], [param:Float b2] )</h3>
 		<p>
 		<p>
 		[page:Float x] — Value to be mapped.<br />
 		[page:Float x] — Value to be mapped.<br />
 		[page:Float a1] — Minimum value for range A.<br />
 		[page:Float a1] — Minimum value for range A.<br />

+ 2 - 11
docs/api/math/Matrix3.html

@@ -144,12 +144,7 @@ m.elements = [ 11, 21, 31,
 		<h3>[method:this multiplyScalar]( [param:Float s] )</h3>
 		<h3>[method:this multiplyScalar]( [param:Float s] )</h3>
 		<p>Multiplies every component of the matrix by the scalar value *s*.</p>
 		<p>Multiplies every component of the matrix by the scalar value *s*.</p>
 
 
-		<h3>
-			[method:this set](
-			[page:Float n11], [page:Float n12], [page:Float n13],
-			[page:Float n21], [page:Float n22], [page:Float n23],
-			[page:Float n31], [page:Float n32], [page:Float n33] )
-		</h3>
+		<h3>[method:this set]( [param:Float n11], [param:Float n12], [param:Float n13], [param:Float n21], [param:Float n22], [param:Float n23], [param:Float n31], [param:Float n32], [param:Float n33] )</h3>
 		<p>
 		<p>
 		[page:Float n11] - value to put in row 1, col 1.<br />
 		[page:Float n11] - value to put in row 1, col 1.<br />
 		[page:Float n12] - value to put in row 1, col 2.<br />
 		[page:Float n12] - value to put in row 1, col 2.<br />
@@ -169,11 +164,7 @@ m.elements = [ 11, 21, 31,
 		<h3>[method:this setFromMatrix4]( [param:Matrix4 m] )</h3>
 		<h3>[method:this setFromMatrix4]( [param:Matrix4 m] )</h3>
 		<p>Set this matrx to the upper 3x3 matrix of the Matrix4 [page:Matrix4 m].</p>
 		<p>Set this matrx to the upper 3x3 matrix of the Matrix4 [page:Matrix4 m].</p>
 
 
-		<h3>
-			[method:this setUvTransform](
-			[page:Float tx], [page:Float ty], [page:Float sx], [page:Float sy],
-			[page:Float rotation], [page:Float cx], [page:Float cy] )
-		</h3>
+		<h3>[method:this setUvTransform]( [param:Float tx], [param:Float ty], [param:Float sx], [param:Float sy], [param:Float rotation], [param:Float cx], [param:Float cy] )</h3>
 		<p>
 		<p>
 		[page:Float tx] - offset x<br />
 		[page:Float tx] - offset x<br />
 		[page:Float ty] - offset y<br />
 		[page:Float ty] - offset y<br />

+ 1 - 5
docs/api/math/Matrix4.html

@@ -368,11 +368,7 @@ x, y, 1, 0,
 		<h3>[method:this scale]( [param:Vector3 v] )</h3>
 		<h3>[method:this scale]( [param:Vector3 v] )</h3>
 		<p>Multiplies the columns of this matrix by vector [page:Vector3 v].</p>
 		<p>Multiplies the columns of this matrix by vector [page:Vector3 v].</p>
 
 
-		<h3>[method:this set](
-			[page:Float n11], [page:Float n12], [page:Float n13], [page:Float n14],
-			[page:Float n21], [page:Float n22], [page:Float n23], [page:Float n24],
-			[page:Float n31], [page:Float n32], [page:Float n33], [page:Float n34],
-			[page:Float n41], [page:Float n42], [page:Float n43], [page:Float n44] )</h3>
+		<h3>[method:this set]( [param:Float n11], [param:Float n12], [param:Float n13], [param:Float n14], [param:Float n21], [param:Float n22], [param:Float n23], [param:Float n24], [param:Float n31], [param:Float n32], [param:Float n33], [param:Float n34], [param:Float n41], [param:Float n42], [param:Float n43], [param:Float n44] )</h3>
 		<p>
 		<p>
 			Set the [page:.elements elements] of this matrix to the supplied row-major values [page:Float n11],
 			Set the [page:.elements elements] of this matrix to the supplied row-major values [page:Float n11],
 			[page:Float n12], ... [page:Float n44].
 			[page:Float n12], ... [page:Float n44].

+ 1 - 11
docs/api/math/Quaternion.html

@@ -261,17 +261,7 @@ q.slerp( qb, t )
 		</p>
 		</p>
 
 
 
 
-		<h3>
-		[method:null slerpFlat](
-			[page:Array dst],
-			[page:Integer dstOffset],
-			[page:Array src0],
-			[page:Integer srcOffset0],
-			[page:Array src1],
-			[page:Integer srcOffset1],
-			[page:Float t]
-		)
-		</h3>
+		<h3>[method:null slerpFlat]( [param:Array dst], [param:Integer dstOffset], [param:Array src0], [param:Integer srcOffset0], [param:Array src1], [param:Integer srcOffset1], [param:Float t] )</h3>
 		<p>
 		<p>
 		[page:Array dst] - The output array.<br />
 		[page:Array dst] - The output array.<br />
 		[page:Integer dstOffset] - An offset into the output array.<br />
 		[page:Integer dstOffset] - An offset into the output array.<br />

+ 1 - 1
docs/api/objects/Mesh.html

@@ -86,7 +86,7 @@
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<p>See the base [page:Object3D] class for common methods.</p>
 		<p>See the base [page:Object3D] class for common methods.</p>
 
 
-		<h3>[method:null setDrawMode]()</h3>
+		<h3>[method:null setDrawMode]( [param:Integer value] )</h3>
 		<p>Set the value of [page:.drawMode drawMode].</p>
 		<p>Set the value of [page:.drawMode drawMode].</p>
 
 
 		<h3>[method:Mesh clone]()</h3>
 		<h3>[method:Mesh clone]()</h3>

+ 1 - 1
docs/api/renderers/WebGLRenderer.html

@@ -392,7 +392,7 @@
 			either the [page:WebGLRenderer.autoClearColor autoClearColor], [page:WebGLRenderer.autoClearStencil autoClearStencil] or [page:WebGLRenderer.autoClearDepth autoClearDepth] properties to false.
 			either the [page:WebGLRenderer.autoClearColor autoClearColor], [page:WebGLRenderer.autoClearStencil autoClearStencil] or [page:WebGLRenderer.autoClearDepth autoClearDepth] properties to false.
 		</p>
 		</p>
 
 
-		<h3>[method:null renderBufferDirect]( [param:Camera camera], [param:Array lights], [param:Fog fog], [param:Material material], [param:Object geometryGroup], [param:Object3D object] )</h3>
+		<h3>[method:null renderBufferDirect]( [param:Camera camera], [param:Fog fog], [param:Geometry geometry], [param:Material material], [param:Object3D object], [param:Object group] )</h3>
 		<p>Render a buffer geometry group using the camera and with the specified material.</p>
 		<p>Render a buffer geometry group using the camera and with the specified material.</p>
 
 
 		<h3>[method:null renderBufferImmediate]( [param:Object3D object], [param:shaderprogram program], [param:Material shading] )</h3>
 		<h3>[method:null renderBufferImmediate]( [param:Object3D object], [param:shaderprogram program], [param:Material shading] )</h3>

+ 3 - 3
docs/api/textures/Texture.html

@@ -234,12 +234,12 @@
 		[page:Texture.rotation .rotation], and [page:Texture.center .center].
 		[page:Texture.rotation .rotation], and [page:Texture.center .center].
 		</p>
 		</p>
 
 
-		<h3>[method:Texture clone]( [param:Texture texture] )</h3>
+		<h3>[method:Texture clone]()</h3>
 		<p>
 		<p>
 		Make copy of the texture. Note this is not a "deep copy", the image is shared.
 		Make copy of the texture. Note this is not a "deep copy", the image is shared.
 		</p>
 		</p>
 
 
-		<h3>[method:Texture toJSON]( meta )</h3>
+		<h3>[method:Texture toJSON]( [param:Object meta] )</h3>
 		<p>
 		<p>
 		meta -- optional object containing metadata.<br />
 		meta -- optional object containing metadata.<br />
 		Convert the material to three.js JSON format.
 		Convert the material to three.js JSON format.
@@ -250,7 +250,7 @@
 		Call [page:EventDispatcher EventDispatcher].dispatchEvent with a 'dispose' event type.
 		Call [page:EventDispatcher EventDispatcher].dispatchEvent with a 'dispose' event type.
 		</p>
 		</p>
 
 
-		<h3>[method:null transformUv]( uv )</h3>
+		<h3>[method:null transformUv]( [param:Vector2 uv] )</h3>
 		<p>
 		<p>
 		Transform the uv based on the value of this texture's [page:Texture.offset .offset], [page:Texture.repeat .repeat],
 		Transform the uv based on the value of this texture's [page:Texture.offset .offset], [page:Texture.repeat .repeat],
 		[page:Texture.wrapS .wrapS], [page:Texture.wrapT .wrapT] and [page:Texture.flipY .flipY] properties.
 		[page:Texture.wrapS .wrapS], [page:Texture.wrapT .wrapT] and [page:Texture.flipY .flipY] properties.

+ 1 - 1
docs/examples/loaders/GLTFLoader.html

@@ -31,7 +31,7 @@
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_materials_unlit</li>
-			<li>KHR_lights (experimental)</li>
+			<li>KHR_lights_punctual (experimental)</li>
 		</ul>
 		</ul>
 
 
 		<h2>Example</h2>
 		<h2>Example</h2>

+ 28 - 3
docs/examples/loaders/SVGLoader.html

@@ -12,7 +12,7 @@
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
 		<p class="desc">A loader for loading a <em>.svg</em> resource.<br >
 		<p class="desc">A loader for loading a <em>.svg</em> resource.<br >
-		<a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">Scalabe Vector Graphics</a> is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation.
+		<a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">Scalable Vector Graphics</a> is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation.
 		</p>
 		</p>
 
 
 		<h2>Example</h2>
 		<h2>Example</h2>
@@ -26,9 +26,34 @@
 			// resource URL
 			// resource URL
 			'data/svgSample.svg',
 			'data/svgSample.svg',
 			// called when the resource is loaded
 			// called when the resource is loaded
-			function ( doc ) {
+			function ( paths ) {
 
 
-				scene.add( new THREE.SVGObject(doc) );
+				var group = new THREE.Group();
+
+				for ( var i = 0; i < paths.length; i ++ ) {
+
+					var path = paths[ i ];
+
+					var material = new THREE.MeshBasicMaterial( {
+						color: path.color,
+						side: THREE.DoubleSide,
+						depthWrite: false
+					} );
+
+					var shapes = path.toShapes( true );
+
+					for ( var j = 0; j < shapes.length; j ++ ) {
+
+						var shape = shapes[ j ];
+						var geometry = new THREE.ShapeBufferGeometry( shape );
+						var mesh = new THREE.Mesh( geometry, material );
+						group.add( mesh );
+
+					}
+
+				}
+
+				scene.add( group );
 
 
 			},
 			},
 			// called when loading is in progresses
 			// called when loading is in progresses

+ 1 - 1
docs/examples/renderers/SVGRenderer.html

@@ -21,7 +21,7 @@
 				<li>Complex or animated user interfaces</li>
 				<li>Complex or animated user interfaces</li>
 			</ul>
 			</ul>
 			<p>
 			<p>
-				[name] has various advantages. It produces crystal-clear and sharp output which is independet of the actual viewport resolution.<br />
+				[name] has various advantages. It produces crystal-clear and sharp output which is independent of the actual viewport resolution.<br />
 				SVG elements can be styled via CSS. And they have good accessibility since it's possible to add metadata like title or description (useful for search engines or screen readers).
 				SVG elements can be styled via CSS. And they have good accessibility since it's possible to add metadata like title or description (useful for search engines or screen readers).
 			</p>
 			</p>
 			<p>
 			<p>

+ 2 - 0
docs/index.html

@@ -93,6 +93,8 @@
 				link.setAttribute( 'target', 'viewer' );
 				link.setAttribute( 'target', 'viewer' );
 				link.addEventListener( 'click', function ( event ) {
 				link.addEventListener( 'click', function ( event ) {
 
 
+					if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
+
 					window.location.hash = pageURL;
 					window.location.hash = pageURL;
 					panel.classList.add( 'collapsed' );
 					panel.classList.add( 'collapsed' );
 
 

+ 6 - 6
editor/index.html

@@ -4,12 +4,12 @@
 		<title>three.js / editor</title>
 		<title>three.js / editor</title>
 		<meta charset="utf-8">
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<!-- Origin Trial Token, feature = WebVR (For Chrome M62+), origin = https://threejs.org, expires = 2018-07-25 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="2018-07-25" content="AtW06hJFoVWUJTZf5gqymMIlrR60JJi5MsSe44qsHjrCmzDUNmvaTtAVg+K9O9jFpjJtn/W9jvG//hHHaq5HcQoAAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUjEuMU02MiIsImV4cGlyeSI6MTUzMjUyNjI5OH0=">
-		<!-- Origin Trial Token, feature = WebXR Device API, origin = https://threejs.org, expires = 2018-07-21 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-07-21" content="Anlf1R/bCOUxOEgGI/9TWuzHHNxBMfZSTUMDCN7cLwDj2gpLwgA1K0DPwOzO/O0Jwaur5bsHo7k9KXx+6g+82wIAAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzMjE2NjIyNX0=">
-		<!-- Origin Trial Token, feature = WebXR Gamepad Support, origin = https://threejs.org, expires = 2018-07-21 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Gamepad Support" data-expires="2018-07-21" content="ArDsXbwATKHPmvQiPlEIWNCt4DlEjB7bLj9vOgoNmL8r38U+wQNYZyUvjQIqqzgACciUUuAnxluTIL7nNkI89gcAAABYeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkdhbWVwYWRTdXBwb3J0IiwiZXhwaXJ5IjoxNTMyMTY2MjI1fQ==">
+		<!-- Origin Trial Token, feature = WebVR (For Chrome M62+), origin = https://threejs.org, expires = 2018-08-30 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="2018-08-30" content="Ag80lPFLAvRyqP2W5I5XBzACxrTAQTWa3cXebXzq+WzW66nlQa6lvejGg1gdAMrzYbY6jUWp8g08kEnzb6svVgcAAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUjEuMU02MiIsImV4cGlyeSI6MTUzNTYzNjYxOX0=">
+		<!-- Origin Trial Token, feature = WebXR Device API, origin = https://threejs.org, expires = 2018-08-28 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-08-28" content="Ag7nJS0Q6nBKfmRY1XLKHslnz73amLhaf8RoFpYz36MpMq0oa30AETLXer74BIwa3t8uDXlR0n4W9f/o674Rqw4AAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzNTQxNDQwMH0=">
+		<!-- Origin Trial Token, feature = WebXR Gamepad Support, origin = https://threejs.org, expires = 2018-08-28 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Gamepad Support" data-expires="2018-08-28" content="AsflqqNG2L/Eepy8xSwCYwWH5U7w3nN7Ak137jGxMeBFz9lqQVcMBqMTcMw6ZkxThB7ZM2Cn7hgPqX++ZlgC9wMAAABYeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkdhbWVwYWRTdXBwb3J0IiwiZXhwaXJ5IjoxNTM1NDE0NDAwfQ==">
 	</head>
 	</head>
 	<body ontouchstart="">
 	<body ontouchstart="">
 		<link href="css/main.css" rel="stylesheet" />
 		<link href="css/main.css" rel="stylesheet" />

+ 1 - 1
examples/canvas_ascii_effect.html

@@ -72,7 +72,7 @@
 				light.position.set( - 500, - 500, - 500 );
 				light.position.set( - 500, - 500, - 500 );
 				scene.add( light );
 				scene.add( light );
 
 
-				sphere = new THREE.Mesh( new THREE.SphereGeometry( 200, 20, 10 ), new THREE.MeshLambertMaterial() );
+				sphere = new THREE.Mesh( new THREE.SphereBufferGeometry( 200, 20, 10 ), new THREE.MeshLambertMaterial() );
 				scene.add( sphere );
 				scene.add( sphere );
 
 
 				// Plane
 				// Plane

+ 1 - 1
examples/canvas_camera_orthographic.html

@@ -58,7 +58,7 @@
 
 
 				// Cubes
 				// Cubes
 
 
-				var geometry = new THREE.BoxGeometry( 50, 50, 50 );
+				var geometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
 				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: 0.5 } );
 				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: 0.5 } );
 
 
 				for ( var i = 0; i < 100; i ++ ) {
 				for ( var i = 0; i < 100; i ++ ) {

+ 1 - 1
examples/canvas_geometry_earth.html

@@ -72,7 +72,7 @@
 				var loader = new THREE.TextureLoader();
 				var loader = new THREE.TextureLoader();
 				loader.load( 'textures/land_ocean_ice_cloud_2048.jpg', function ( texture ) {
 				loader.load( 'textures/land_ocean_ice_cloud_2048.jpg', function ( texture ) {
 
 
-					var geometry = new THREE.SphereGeometry( 200, 20, 20 );
+					var geometry = new THREE.SphereBufferGeometry( 200, 20, 20 );
 
 
 					var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
 					var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
 					var mesh = new THREE.Mesh( geometry, material );
 					var mesh = new THREE.Mesh( geometry, material );

+ 1 - 1
examples/canvas_geometry_hierarchy.html

@@ -52,7 +52,7 @@
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0xffffff );
 				scene.background = new THREE.Color( 0xffffff );
 
 
-				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 				var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } );
 				var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } );
 
 
 				group = new THREE.Group();
 				group = new THREE.Group();

+ 1 - 1
examples/canvas_geometry_panorama.html

@@ -81,7 +81,7 @@
 
 
 				];
 				];
 
 
-				var geometry = new THREE.BoxGeometry( 300, 300, 300, 7, 7, 7 );
+				var geometry = new THREE.BoxBufferGeometry( 300, 300, 300, 7, 7, 7 );
 				geometry.scale( - 1, 1, 1 );
 				geometry.scale( - 1, 1, 1 );
 
 
 				mesh = new THREE.Mesh( geometry, materials );
 				mesh = new THREE.Mesh( geometry, materials );

+ 7 - 5
examples/canvas_geometry_panorama_fisheye.html

@@ -81,18 +81,20 @@
 
 
 				];
 				];
 
 
-				var geometry = new THREE.BoxGeometry( 300, 300, 300, 7, 7, 7 );
+				var geometry = new THREE.BoxBufferGeometry( 300, 300, 300, 7, 7, 7 );
 				geometry.scale( - 1, 1, 1 );
 				geometry.scale( - 1, 1, 1 );
 
 
 				mesh = new THREE.Mesh( geometry, materials );
 				mesh = new THREE.Mesh( geometry, materials );
 				scene.add( mesh );
 				scene.add( mesh );
 
 
-				for ( var i = 0, l = mesh.geometry.vertices.length; i < l; i ++ ) {
+				var vec = new THREE.Vector3();
+				var positions = mesh.geometry.attributes.position;
 
 
-					var vertex = mesh.geometry.vertices[ i ];
+				for ( var i = 0, l = positions.count; i < l; i ++ ) {
 
 
-					vertex.normalize();
-					vertex.multiplyScalar( 550 );
+					vec.fromBufferAttribute( positions, i );
+					vec.setLength( 550 );
+					positions.setXYZ( i, vec.x, vec.y, vec.z );
 
 
 				}
 				}
 
 

+ 1 - 1
examples/canvas_geometry_shapes.html

@@ -71,7 +71,7 @@
 
 
 					// flat shape
 					// flat shape
 
 
-					var geometry = new THREE.ShapeGeometry( shape );
+					var geometry = new THREE.ShapeBufferGeometry( shape );
 					var material = new THREE.MeshBasicMaterial( { color: color, overdraw: 0.5 } );
 					var material = new THREE.MeshBasicMaterial( { color: color, overdraw: 0.5 } );
 
 
 					var mesh = new THREE.Mesh( geometry, material );
 					var mesh = new THREE.Mesh( geometry, material );

+ 1 - 1
examples/canvas_geometry_text.html

@@ -80,7 +80,7 @@
 
 
 				}
 				}
 
 
-				var geometry = new THREE.TextGeometry( theText, {
+				var geometry = new THREE.TextBufferGeometry( theText, {
 
 
 					font: font,
 					font: font,
 					size: 80,
 					size: 80,

+ 1 - 1
examples/canvas_interactive_cubes.html

@@ -55,7 +55,7 @@
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0xf0f0f0 );
 				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
-				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 
 
 				for ( var i = 0; i < 10; i ++ ) {
 				for ( var i = 0; i < 10; i ++ ) {
 
 

+ 1 - 1
examples/canvas_interactive_cubes_tween.html

@@ -54,7 +54,7 @@
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0xf0f0f0 );
 				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
-				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 
 
 				for ( var i = 0; i < 20; i ++ ) {
 				for ( var i = 0; i < 20; i ++ ) {
 
 

+ 1 - 1
examples/canvas_interactive_voxelpainter.html

@@ -28,7 +28,7 @@
 
 
 			var mouse, raycaster, isShiftDown = false;
 			var mouse, raycaster, isShiftDown = false;
 
 
-			var cubeGeometry = new THREE.BoxGeometry( 50, 50, 50 );
+			var cubeGeometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
 			var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, overdraw: 0.5 } );
 			var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, overdraw: 0.5 } );
 
 
 			var objects = [];
 			var objects = [];

+ 42 - 21
examples/canvas_lines_colors.html

@@ -49,14 +49,11 @@
 		<script src="js/renderers/Projector.js"></script>
 		<script src="js/renderers/Projector.js"></script>
 		<script src="js/renderers/CanvasRenderer.js"></script>
 		<script src="js/renderers/CanvasRenderer.js"></script>
 
 
-		<script src="js/Detector.js"></script>
 		<script src="js/geometries/hilbert3D.js"></script>
 		<script src="js/geometries/hilbert3D.js"></script>
 		<script src="js/geometries/hilbert2D.js"></script>
 		<script src="js/geometries/hilbert2D.js"></script>
 
 
 		<script>
 		<script>
 
 
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
 			var mouseX = 0, mouseY = 0;
 			var mouseX = 0, mouseY = 0;
 
 
 			var windowHalfX = window.innerWidth / 2;
 			var windowHalfX = window.innerWidth / 2;
@@ -81,37 +78,61 @@
 
 
 				// 2d lines
 				// 2d lines
 
 
-				var geometry2 = new THREE.Geometry(),
-					points = hilbert2D( new THREE.Vector3( 0, 0, 0 ), 400, 4 ),
-					colors2 = [];
+				var vertices = hilbert2D( new THREE.Vector3( 0, 0, 0 ), 400, 4 );
+				var numVertices = vertices.length;
 
 
-				for ( var i = 0; i < points.length; i ++ ) {
+				var geometry2 = new THREE.BufferGeometry();
 
 
-					geometry2.vertices.push( points[ i ] );
+				var positions = new Float32Array( numVertices * 3 );
+				var colors = new Float32Array( numVertices * 3 );
 
 
-					colors2[ i ] = new THREE.Color( 0xffffff );
-					colors2[ i ].setHSL( i / points.length, 1, 0.5 );
+				geometry2.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry2.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
 
 
-				}
+				var color = new THREE.Color();
+
+				for ( var i = 0, index = 0, l = numVertices; i < l; i ++, index += 3 ) {
+
+					positions[ index ] = vertices[ i ].x;
+					positions[ index + 1 ] = vertices[ i ].y;
+					positions[ index + 2 ] = vertices[ i ].z;
 
 
-				geometry2.colors = colors2;
+					color.setHSL( i / l, 1.0, 0.5 );
+
+					colors[ index ] = color.r;
+					colors[ index + 1 ] = color.g;
+					colors[ index + 2 ] = color.b;
+
+				}
 
 
 				// 3d lines
 				// 3d lines
 
 
-				var geometry3 = new THREE.Geometry(),
-					points = hilbert3D( new THREE.Vector3( 0, 0, 0 ), 200, 2, 0, 1, 2, 3, 4, 5, 6, 7 ),
-					colors3 = [];
+				var vertices = hilbert3D( new THREE.Vector3( 0, 0, 0 ), 200, 2, 0, 1, 2, 3, 4, 5, 6, 7 );
+				var numVertices = vertices.length;
 
 
-				for ( var i = 0; i < points.length; i ++ ) {
+				var geometry3 = new THREE.BufferGeometry();
 
 
-					geometry3.vertices.push( points[ i ] );
+				var positions = new Float32Array( numVertices * 3 );
+				var colors = new Float32Array( numVertices * 3 );
 
 
-					colors3[ i ] = new THREE.Color( 0xffffff );
-					colors3[ i ].setHSL( i / points.length, 1, 0.5 );
+				geometry3.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry3.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
 
 
-				}
+				var color = new THREE.Color();
+
+				for ( var i = 0, index = 0, l = numVertices; i < l; i ++, index += 3 ) {
+
+					positions[ index ] = vertices[ i ].x;
+					positions[ index + 1 ] = vertices[ i ].y;
+					positions[ index + 2 ] = vertices[ i ].z;
 
 
-				geometry3.colors = colors3;
+					color.setHSL( i / l, 1.0, 0.5 );
+
+					colors[ index ] = color.r;
+					colors[ index + 1 ] = color.g;
+					colors[ index + 2 ] = color.b;
+
+				}
 
 
 				// lines
 				// lines
 
 

+ 25 - 58
examples/canvas_lines_dashed.html

@@ -38,17 +38,13 @@
 
 
 		<script src="js/geometries/hilbert3D.js"></script>
 		<script src="js/geometries/hilbert3D.js"></script>
 
 
-		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 
 		<script>
 		<script>
 
 
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
 			var renderer, scene, camera, stats;
 			var renderer, scene, camera, stats;
 			var objects = [];
 			var objects = [];
 
 
-
 			var WIDTH = window.innerWidth, HEIGHT = window.innerHeight;
 			var WIDTH = window.innerWidth, HEIGHT = window.innerHeight;
 
 
 			init();
 			init();
@@ -62,23 +58,43 @@
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0x111111 );
 				scene.background = new THREE.Color( 0x111111 );
 
 
-				var subdivisions = 6;
+				var subdivisions = 3;
 				var recursion = 1;
 				var recursion = 1;
 
 
 				var points = hilbert3D( new THREE.Vector3( 0,0,0 ), 25.0, recursion, 0, 1, 2, 3, 4, 5, 6, 7 );
 				var points = hilbert3D( new THREE.Vector3( 0,0,0 ), 25.0, recursion, 0, 1, 2, 3, 4, 5, 6, 7 );
 				var spline = new THREE.CatmullRomCurve3( points );
 				var spline = new THREE.CatmullRomCurve3( points );
 
 
 				var samples = spline.getPoints( points.length * subdivisions );
 				var samples = spline.getPoints( points.length * subdivisions );
-				var geometrySpline = new THREE.Geometry().setFromPoints( samples );
+				var numSamples = samples.length;
+
+				var geometrySpline = new THREE.BufferGeometry();
+
+				var positions = new Float32Array( numSamples * 3 );
+
+				geometrySpline.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+
+				for ( var i = 0, index = 0, l = numSamples; i < l; i ++, index += 3 ) {
+
+					positions[ index ] = samples[ i ].x;
+					positions[ index + 1 ] = samples[ i ].y;
+					positions[ index + 2 ] = samples[ i ].z;
 
 
-				var geometryCube = cube( 50 );
+				}
+
+				var geometryCube = new THREE.EdgesGeometry( new THREE.BoxBufferGeometry( 50, 50, 50 ) );
 
 
-				var object = new THREE.Line( geometrySpline, new THREE.LineDashedMaterial( { color: 0xffffff, dashSize: 1, gapSize: 0.5 } ) );
+				var object = new THREE.Line(
+					geometrySpline,
+					new THREE.LineDashedMaterial( { color: 0xffffff, dashSize: 10, gapSize: 10, linewidth: 3 } )
+				);
 
 
 				objects.push( object );
 				objects.push( object );
 				scene.add( object );
 				scene.add( object );
 
 
-				var object = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 30, gapSize: 10, linewidth: 2 } ) );
+				var object = new THREE.LineSegments(
+					geometryCube,
+					new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 30, gapSize: 10, linewidth: 3 } )
+				);
 
 
 				objects.push( object );
 				objects.push( object );
 				scene.add( object );
 				scene.add( object );
@@ -99,55 +115,6 @@
 
 
 			}
 			}
 
 
-			function cube( size ) {
-
-				var h = size * 0.5;
-
-				var geometry = new THREE.Geometry();
-
-				geometry.vertices.push(
-					new THREE.Vector3( -h, -h, -h ),
-					new THREE.Vector3( -h, h, -h ),
-
-					new THREE.Vector3( -h, h, -h ),
-					new THREE.Vector3( h, h, -h ),
-
-					new THREE.Vector3( h, h, -h ),
-					new THREE.Vector3( h, -h, -h ),
-
-					new THREE.Vector3( h, -h, -h ),
-					new THREE.Vector3( -h, -h, -h ),
-
-
-					new THREE.Vector3( -h, -h, h ),
-					new THREE.Vector3( -h, h, h ),
-
-					new THREE.Vector3( -h, h, h ),
-					new THREE.Vector3( h, h, h ),
-
-					new THREE.Vector3( h, h, h ),
-					new THREE.Vector3( h, -h, h ),
-
-					new THREE.Vector3( h, -h, h ),
-					new THREE.Vector3( -h, -h, h ),
-
-					new THREE.Vector3( -h, -h, -h ),
-					new THREE.Vector3( -h, -h, h ),
-
-					new THREE.Vector3( -h, h, -h ),
-					new THREE.Vector3( -h, h, h ),
-
-					new THREE.Vector3( h, h, -h ),
-					new THREE.Vector3( h, h, h ),
-
-					new THREE.Vector3( h, -h, -h ),
-					new THREE.Vector3( h, -h, h )
-				 );
-
-				return geometry;
-
-			}
-
 			function onWindowResize() {
 			function onWindowResize() {
 
 
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.aspect = window.innerWidth / window.innerHeight;

+ 1 - 1
examples/canvas_materials_video.html

@@ -103,7 +103,7 @@
 
 
 				//
 				//
 
 
-				var plane = new THREE.PlaneGeometry( 480, 204, 4, 4 );
+				var plane = new THREE.PlaneBufferGeometry( 480, 204, 4, 4 );
 
 
 				mesh = new THREE.Mesh( plane, material );
 				mesh = new THREE.Mesh( plane, material );
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5;
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5;

+ 1 - 1
examples/canvas_performance.html

@@ -53,7 +53,7 @@
 
 
 				// Spheres
 				// Spheres
 
 
-				var geometry = new THREE.SphereGeometry( 100, 26, 18 );
+				var geometry = new THREE.SphereBufferGeometry( 100, 26, 18 );
 				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: 0.5 } );
 				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: 0.5 } );
 
 
 				for ( var i = 0; i < 20; i ++ ) {
 				for ( var i = 0; i < 20; i ++ ) {

+ 1 - 1
examples/canvas_sandbox.html

@@ -56,7 +56,7 @@
 				group = new THREE.Group();
 				group = new THREE.Group();
 				scene.add( group );
 				scene.add( group );
 
 
-				var geometry = new THREE.IcosahedronGeometry( 100, 1 );
+				var geometry = new THREE.IcosahedronBufferGeometry( 100, 1 );
 
 
 				var envMap = new THREE.TextureLoader().load( 'textures/metal.jpg' );
 				var envMap = new THREE.TextureLoader().load( 'textures/metal.jpg' );
 				envMap.mapping = THREE.SphericalReflectionMapping;
 				envMap.mapping = THREE.SphericalReflectionMapping;

+ 2 - 0
examples/files.js

@@ -209,6 +209,7 @@ var files = {
 		"webgl_panorama_equirectangular",
 		"webgl_panorama_equirectangular",
 		"webgl_performance",
 		"webgl_performance",
 		"webgl_performance_doublesided",
 		"webgl_performance_doublesided",
+		"webgl_performance_nodes",
 		"webgl_performance_static",
 		"webgl_performance_static",
 		"webgl_physics_cloth",
 		"webgl_physics_cloth",
 		"webgl_physics_convex_break",
 		"webgl_physics_convex_break",
@@ -232,6 +233,7 @@ var files = {
 		"webgl_postprocessing_ssaa",
 		"webgl_postprocessing_ssaa",
 		"webgl_postprocessing_ssaa_unbiased",
 		"webgl_postprocessing_ssaa_unbiased",
 		"webgl_postprocessing_nodes",
 		"webgl_postprocessing_nodes",
+		"webgl_postprocessing_nodes_pass",
 		"webgl_postprocessing_outline",
 		"webgl_postprocessing_outline",
 		"webgl_postprocessing_pixel",
 		"webgl_postprocessing_pixel",
 		"webgl_postprocessing_procedural",
 		"webgl_postprocessing_procedural",

+ 2 - 4
examples/index.html

@@ -296,11 +296,9 @@
 			link.setAttribute( 'target', 'viewer' );
 			link.setAttribute( 'target', 'viewer' );
 			link.addEventListener( 'click', function ( event ) {
 			link.addEventListener( 'click', function ( event ) {
 
 
-				if ( event.button === 0 ) {
+				if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
 
 
-					selectFile( file );
-
-				}
+				selectFile( file );
 
 
 			} );
 			} );
 
 

+ 1 - 1
examples/js/controls/DragControls.js

@@ -154,7 +154,7 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 
 
 		}
 		}
 
 
-		_domElement.style.cursor = 'auto';
+		_domElement.style.cursor = _hovered ? 'pointer' : 'auto';
 
 
 	}
 	}
 
 

+ 66 - 15
examples/js/loaders/ColladaLoader.js

@@ -969,11 +969,11 @@ THREE.ColladaLoader.prototype = {
 
 
 			if ( data.bindShapeMatrix ) {
 			if ( data.bindShapeMatrix ) {
 
 
-				build.bindMatrix = new THREE.Matrix4().fromArray( data.bindShapeMatrix ).transpose(); 
+				build.bindMatrix = new THREE.Matrix4().fromArray( data.bindShapeMatrix ).transpose();
 
 
 			} else {
 			} else {
 
 
-				build.bindMatrix = new THREE.Matrix4().transpose(); 
+				build.bindMatrix = new THREE.Matrix4().identity();
 
 
 			}
 			}
 
 
@@ -1449,6 +1449,28 @@ THREE.ColladaLoader.prototype = {
 
 
 		}
 		}
 
 
+		function getTextureLoader( image ) {
+
+			var loader;
+
+			var extension = image.slice( ( image.lastIndexOf( '.' ) - 1 >>> 0 ) + 2 ); // http://www.jstips.co/en/javascript/get-file-extension/
+			extension = extension.toLowerCase();
+
+			switch ( extension ) {
+
+				case 'tga':
+					loader = tgaLoader;
+					break;
+
+				default:
+					loader = textureLoader;
+
+			}
+
+			return loader;
+
+		}
+
 		function buildMaterial( data ) {
 		function buildMaterial( data ) {
 
 
 			var effect = getEffect( data.url );
 			var effect = getEffect( data.url );
@@ -1499,28 +1521,40 @@ THREE.ColladaLoader.prototype = {
 
 
 				if ( image !== null ) {
 				if ( image !== null ) {
 
 
-					var texture = textureLoader.load( image );
+					var loader = getTextureLoader( image );
+
+					if ( loader !== undefined ) {
+
+						var texture = loader.load( image );
+
+						var extra = textureObject.extra;
+
+						if ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) {
 
 
-					var extra = textureObject.extra;
+							var technique = extra.technique;
 
 
-					if ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) {
+							texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
+							texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
 
 
-						var technique = extra.technique;
+							texture.offset.set( technique.offsetU || 0, technique.offsetV || 0 );
+							texture.repeat.set( technique.repeatU || 1, technique.repeatV || 1 );
 
 
-						texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
-						texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
+						} else {
+
+							texture.wrapS = THREE.RepeatWrapping;
+							texture.wrapT = THREE.RepeatWrapping;
 
 
-						texture.offset.set( technique.offsetU || 0, technique.offsetV || 0 );
-						texture.repeat.set( technique.repeatU || 1, technique.repeatV || 1 );
+						}
+
+						return texture;
 
 
 					} else {
 					} else {
 
 
-						texture.wrapS = THREE.RepeatWrapping;
-						texture.wrapT = THREE.RepeatWrapping;
+						console.warn( 'THREE.ColladaLoader: Loader for texture %s not found.', image );
 
 
-					}
+						return null;
 
 
-					return texture;
+					}
 
 
 				} else {
 				} else {
 
 
@@ -3183,7 +3217,15 @@ THREE.ColladaLoader.prototype = {
 
 
 			}
 			}
 
 
-			library.nodes[ data.id ] = data;
+			if ( hasNode( data.id ) ) {
+
+				console.warn( 'THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id );
+
+			} else {
+
+				library.nodes[ data.id ] = data;
+
+			}
 
 
 			return data;
 			return data;
 
 
@@ -3761,6 +3803,15 @@ THREE.ColladaLoader.prototype = {
 		var textureLoader = new THREE.TextureLoader( this.manager );
 		var textureLoader = new THREE.TextureLoader( this.manager );
 		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 
 
+		var tgaLoader;
+
+		if ( THREE.TGALoader ) {
+
+			tgaLoader = new THREE.TGALoader( this.manager );
+			tgaLoader.setPath( path );
+
+		}
+
 		//
 		//
 
 
 		var animations = [];
 		var animations = [];

File diff suppressed because it is too large
+ 1603 - 1620
examples/js/loaders/FBXLoader.js


+ 59 - 84
examples/js/loaders/GLTFLoader.js

@@ -130,7 +130,7 @@ THREE.GLTFLoader = ( function () {
 
 
 					switch ( extensionName ) {
 					switch ( extensionName ) {
 
 
-						case EXTENSIONS.KHR_LIGHTS:
+						case EXTENSIONS.KHR_LIGHTS_PUNCTUAL:
 							extensions[ extensionName ] = new GLTFLightsExtension( json );
 							extensions[ extensionName ] = new GLTFLightsExtension( json );
 							break;
 							break;
 
 
@@ -237,7 +237,7 @@ THREE.GLTFLoader = ( function () {
 	var EXTENSIONS = {
 	var EXTENSIONS = {
 		KHR_BINARY_GLTF: 'KHR_binary_glTF',
 		KHR_BINARY_GLTF: 'KHR_binary_glTF',
 		KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
 		KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
-		KHR_LIGHTS: 'KHR_lights',
+		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
@@ -270,21 +270,24 @@ THREE.GLTFLoader = ( function () {
 	 */
 	 */
 	function GLTFLightsExtension( json ) {
 	function GLTFLightsExtension( json ) {
 
 
-		this.name = EXTENSIONS.KHR_LIGHTS;
+		this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
 
 
-		this.lights = {};
+		this.lights = [];
 
 
-		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS ] ) || {};
-		var lights = extension.lights || {};
+		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};
+		var lightDefs = extension.lights || [];
 
 
-		for ( var lightId in lights ) {
+		for ( var i = 0; i < lightDefs.length; i ++ ) {
 
 
-			var light = lights[ lightId ];
+			var lightDef = lightDefs[ i ];
 			var lightNode;
 			var lightNode;
 
 
-			var color = new THREE.Color().fromArray( light.color );
+			var color = new THREE.Color( 0xffffff );
+			if ( lightDef.color !== undefined ) color.fromArray( lightDef.color );
 
 
-			switch ( light.type ) {
+			var range = lightDef.range !== undefined ? lightDef.range : 0;
+
+			switch ( lightDef.type ) {
 
 
 				case 'directional':
 				case 'directional':
 					lightNode = new THREE.DirectionalLight( color );
 					lightNode = new THREE.DirectionalLight( color );
@@ -294,40 +297,34 @@ THREE.GLTFLoader = ( function () {
 
 
 				case 'point':
 				case 'point':
 					lightNode = new THREE.PointLight( color );
 					lightNode = new THREE.PointLight( color );
+					lightNode.distance = range;
 					break;
 					break;
 
 
 				case 'spot':
 				case 'spot':
 					lightNode = new THREE.SpotLight( color );
 					lightNode = new THREE.SpotLight( color );
+					lightNode.distance = range;
 					// Handle spotlight properties.
 					// Handle spotlight properties.
-					light.spot = light.spot || {};
-					light.spot.innerConeAngle = light.spot.innerConeAngle !== undefined ? light.spot.innerConeAngle : 0;
-					light.spot.outerConeAngle = light.spot.outerConeAngle !== undefined ? light.spot.outerConeAngle : Math.PI / 4.0;
-					lightNode.angle = light.spot.outerConeAngle;
-					lightNode.penumbra = 1.0 - light.spot.innerConeAngle / light.spot.outerConeAngle;
+					lightDef.spot = lightDef.spot || {};
+					lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
+					lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
+					lightNode.angle = 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;
 
 
-				case 'ambient':
-					lightNode = new THREE.AmbientLight( color );
-					break;
+				default:
+					throw new Error( 'THREE.GLTFLoader: Unexpected light type, "' + lightDef.type + '".' );
 
 
 			}
 			}
 
 
-			if ( lightNode ) {
+			lightNode.decay = 2;
 
 
-				lightNode.decay = 2;
+			if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
 
 
-				if ( light.intensity !== undefined ) {
-
-					lightNode.intensity = light.intensity;
-
-				}
+			lightNode.name = lightDef.name || ( 'light_' + i );
 
 
-				lightNode.name = light.name || ( 'light_' + lightId );
-				this.lights[ lightId ] = lightNode;
-
-			}
+			this.lights.push( lightNode );
 
 
 		}
 		}
 
 
@@ -1019,21 +1016,6 @@ THREE.GLTFLoader = ( function () {
 		10497: THREE.RepeatWrapping
 		10497: THREE.RepeatWrapping
 	};
 	};
 
 
-	var WEBGL_TEXTURE_FORMATS = {
-		6406: THREE.AlphaFormat,
-		6407: THREE.RGBFormat,
-		6408: THREE.RGBAFormat,
-		6409: THREE.LuminanceFormat,
-		6410: THREE.LuminanceAlphaFormat
-	};
-
-	var WEBGL_TEXTURE_DATATYPES = {
-		5121: THREE.UnsignedByteType,
-		32819: THREE.UnsignedShort4444Type,
-		32820: THREE.UnsignedShort5551Type,
-		33635: THREE.UnsignedShort565Type
-	};
-
 	var WEBGL_SIDES = {
 	var WEBGL_SIDES = {
 		1028: THREE.BackSide, // Culling front
 		1028: THREE.BackSide, // Culling front
 		1029: THREE.FrontSide // Culling back
 		1029: THREE.FrontSide // Culling back
@@ -1188,6 +1170,28 @@ THREE.GLTFLoader = ( function () {
 
 
 	}
 	}
 
 
+	/**
+	 * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry} object
+	 * @param {GLTF.definition} def
+	 */
+	function assignExtrasToUserData( object, gltfDef ) {
+
+		if ( gltfDef.extras !== undefined ) {
+
+			if ( typeof gltfDef.extras === 'object' ) {
+
+				object.userData = gltfDef.extras;
+
+			} else {
+
+				console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );
+
+			}
+
+		}
+
+	}
+
 	/**
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
 	 *
 	 *
@@ -2014,22 +2018,6 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( textureDef.name !== undefined ) texture.name = textureDef.name;
 			if ( textureDef.name !== undefined ) texture.name = textureDef.name;
 
 
-			// .format of dds texture is set in DDSLoader
-			if ( ! textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {
-
-				texture.format = textureDef.format !== undefined ? WEBGL_TEXTURE_FORMATS[ textureDef.format ] : THREE.RGBAFormat;
-
-			}
-
-			if ( textureDef.internalFormat !== undefined && texture.format !== WEBGL_TEXTURE_FORMATS[ textureDef.internalFormat ] ) {
-
-				console.warn( 'THREE.GLTFLoader: Three.js does not support texture internalFormat which is different from texture format. ' +
-											'internalFormat will be forced to be the same value as format.' );
-
-			}
-
-			texture.type = textureDef.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ textureDef.type ] : THREE.UnsignedByteType;
-
 			var samplers = json.samplers || {};
 			var samplers = json.samplers || {};
 			var sampler = samplers[ textureDef.sampler ] || {};
 			var sampler = samplers[ textureDef.sampler ] || {};
 
 
@@ -2222,7 +2210,7 @@ THREE.GLTFLoader = ( function () {
 			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
 			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
 			if ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;
 			if ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;
 
 
-			if ( materialDef.extras ) material.userData = materialDef.extras;
+			assignExtrasToUserData( material, materialDef );
 
 
 			if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
 			if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
 
 
@@ -2266,11 +2254,7 @@ THREE.GLTFLoader = ( function () {
 
 
 		}
 		}
 
 
-		if ( primitiveDef.extras !== undefined ) {
-
-			geometry.userData = primitiveDef.extras;
-
-		}
+		assignExtrasToUserData( geometry, primitiveDef );
 
 
 	}
 	}
 
 
@@ -2539,7 +2523,7 @@ THREE.GLTFLoader = ( function () {
 
 
 					if ( geometries.length > 1 ) mesh.name += '_' + i;
 					if ( geometries.length > 1 ) mesh.name += '_' + i;
 
 
-					if ( meshDef.extras !== undefined ) mesh.userData = meshDef.extras;
+					assignExtrasToUserData( mesh, meshDef );
 
 
 					meshes.push( mesh );
 					meshes.push( mesh );
 
 
@@ -2707,7 +2691,8 @@ THREE.GLTFLoader = ( function () {
 		}
 		}
 
 
 		if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
 		if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
-		if ( cameraDef.extras ) camera.userData = cameraDef.extras;
+
+		assignExtrasToUserData( camera, cameraDef );
 
 
 		return Promise.resolve( camera );
 		return Promise.resolve( camera );
 
 
@@ -2956,11 +2941,11 @@ THREE.GLTFLoader = ( function () {
 				node = dependencies.cameras[ nodeDef.camera ];
 				node = dependencies.cameras[ nodeDef.camera ];
 
 
 			} else if ( nodeDef.extensions
 			} else if ( nodeDef.extensions
-					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS ]
-					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light !== undefined ) {
+					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]
+					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {
 
 
-				var lights = extensions[ EXTENSIONS.KHR_LIGHTS ].lights;
-				node = lights[ nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light ];
+				var lights = extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].lights;
+				node = lights[ nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light ];
 
 
 			} else {
 			} else {
 
 
@@ -2974,7 +2959,7 @@ THREE.GLTFLoader = ( function () {
 
 
 			}
 			}
 
 
-			if ( nodeDef.extras ) node.userData = nodeDef.extras;
+			assignExtrasToUserData( node, nodeDef );
 
 
 			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
 			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
 
 
@@ -3108,7 +3093,7 @@ THREE.GLTFLoader = ( function () {
 				var scene = new THREE.Scene();
 				var scene = new THREE.Scene();
 				if ( sceneDef.name !== undefined ) scene.name = sceneDef.name;
 				if ( sceneDef.name !== undefined ) scene.name = sceneDef.name;
 
 
-				if ( sceneDef.extras ) scene.userData = sceneDef.extras;
+				assignExtrasToUserData( scene, sceneDef );
 
 
 				if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
 				if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
 
 
@@ -3120,16 +3105,6 @@ THREE.GLTFLoader = ( function () {
 
 
 				}
 				}
 
 
-				// Ambient lighting, if present, is always attached to the scene root.
-				if ( sceneDef.extensions
-						 && sceneDef.extensions[ EXTENSIONS.KHR_LIGHTS ]
-						 && sceneDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light !== undefined ) {
-
-					var lights = extensions[ EXTENSIONS.KHR_LIGHTS ].lights;
-					scene.add( lights[ sceneDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light ] );
-
-				}
-
 				return scene;
 				return scene;
 
 
 			} );
 			} );

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

@@ -108,7 +108,7 @@ THREE.HDRCubeTextureLoader.prototype.load = function ( type, urls, onLoad, onPro
 
 
 	function loadHDRData( i, onLoad, onProgress, onError ) {
 	function loadHDRData( i, onLoad, onProgress, onError ) {
 
 
-		var loader = new THREE.FileLoader( this.manager );
+		var loader = new THREE.FileLoader( scope.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setResponseType( 'arraybuffer' );
 		loader.load( urls[ i ], function ( buffer ) {
 		loader.load( urls[ i ], function ( buffer ) {
 
 

+ 24 - 7
examples/js/loaders/STLLoader.js

@@ -86,22 +86,39 @@ THREE.STLLoader.prototype = {
 			// However, ASCII STLs lacking the SPACE after the 'd' are known to be
 			// However, ASCII STLs lacking the SPACE after the 'd' are known to be
 			// plentiful.  So, check the first 5 bytes for 'solid'.
 			// plentiful.  So, check the first 5 bytes for 'solid'.
 
 
+			// Several encodings, such as UTF-8, precede the text with up to 5 bytes:
+			// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
+			// Search for "solid" to start anywhere after those prefixes.
+
 			// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
 			// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
 
 
 			var solid = [ 115, 111, 108, 105, 100 ];
 			var solid = [ 115, 111, 108, 105, 100 ];
 
 
-			for ( var i = 0; i < 5; i ++ ) {
+			for ( var off = 0; off < 5; off ++ ) {
+
+				// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
+
+				if ( matchDataViewAt ( solid, reader, off ) ) return false;
 
 
-				// If solid[ i ] does not match the i-th byte, then it is not an
-				// ASCII STL; hence, it is binary and return true.
+			}
+
+			// Couldn't find "solid" text at the beginning; it is binary STL.
 
 
-				if ( solid[ i ] != reader.getUint8( i, false ) ) return true;
+			return true;
 
 
- 			}
+		}
 
 
-			// First 5 bytes read "solid"; declare it to be an ASCII STL
+		function matchDataViewAt( query, reader, offset ) {
+
+			// Check if each byte in query matches the corresponding byte from the current offset
+
+			for ( var i = 0, il = query.length; i < il; i ++ ) {
+
+				if ( query[ i ] !== reader.getUint8( offset + i, false ) ) return false;
+
+			}
 
 
-			return false;
+			return true;
 
 
 		}
 		}
 
 

+ 316 - 24
examples/js/loaders/SVGLoader.js

@@ -1,6 +1,7 @@
 /**
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  * @author zz85 / http://joshuakoo.com/
  * @author zz85 / http://joshuakoo.com/
+ * @author yomboprime / https://yombo.org
  */
  */
 
 
 THREE.SVGLoader = function ( manager ) {
 THREE.SVGLoader = function ( manager ) {
@@ -32,6 +33,10 @@ THREE.SVGLoader.prototype = {
 
 
 			if ( node.nodeType !== 1 ) return;
 			if ( node.nodeType !== 1 ) return;
 
 
+			var transform = getNodeTransform( node );
+
+			var path = null;
+
 			switch ( node.nodeName ) {
 			switch ( node.nodeName ) {
 
 
 				case 'svg':
 				case 'svg':
@@ -43,37 +48,37 @@ THREE.SVGLoader.prototype = {
 
 
 				case 'path':
 				case 'path':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( node.hasAttribute( 'd' ) && isVisible( style ) ) paths.push( parsePathNode( node, style ) );
+					if ( node.hasAttribute( 'd' ) && isVisible( style ) ) path = parsePathNode( node, style );
 					break;
 					break;
 
 
 				case 'rect':
 				case 'rect':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseRectNode( node, style ) );
+					if ( isVisible( style ) ) path = parseRectNode( node, style );
 					break;
 					break;
 
 
 				case 'polygon':
 				case 'polygon':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parsePolygonNode( node, style ) );
+					if ( isVisible( style ) ) path = parsePolygonNode( node, style );
 					break;
 					break;
 
 
 				case 'polyline':
 				case 'polyline':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parsePolylineNode( node, style ) );
+					if ( isVisible( style ) ) path = parsePolylineNode( node, style );
 					break;
 					break;
 
 
 				case 'circle':
 				case 'circle':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseCircleNode( node, style ) );
+					if ( isVisible( style ) ) path = parseCircleNode( node, style );
 					break;
 					break;
 
 
 				case 'ellipse':
 				case 'ellipse':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseEllipseNode( node, style ) );
+					if ( isVisible( style ) ) path = parseEllipseNode( node, style );
 					break;
 					break;
 
 
 				case 'line':
 				case 'line':
 					style = parseStyle( node, style );
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseLineNode( node, style ) );
+					if ( isVisible( style ) ) path = parseLineNode( node, style );
 					break;
 					break;
 
 
 				default:
 				default:
@@ -81,6 +86,14 @@ THREE.SVGLoader.prototype = {
 
 
 			}
 			}
 
 
+			if ( path ) {
+
+				transformPath( path, currentTransform );
+
+				paths.push( path );
+
+			}
+
 			var nodes = node.childNodes;
 			var nodes = node.childNodes;
 
 
 			for ( var i = 0; i < nodes.length; i ++ ) {
 			for ( var i = 0; i < nodes.length; i ++ ) {
@@ -89,6 +102,12 @@ THREE.SVGLoader.prototype = {
 
 
 			}
 			}
 
 
+			if ( transform ) {
+
+				currentTransform.copy( transformStack.pop() );
+
+			}
+
 		}
 		}
 
 
 		function parsePathNode( node, style ) {
 		function parsePathNode( node, style ) {
@@ -99,6 +118,10 @@ THREE.SVGLoader.prototype = {
 			var point = new THREE.Vector2();
 			var point = new THREE.Vector2();
 			var control = new THREE.Vector2();
 			var control = new THREE.Vector2();
 
 
+			var firstPoint = new THREE.Vector2();
+			var isFirstPoint = true;
+			var doSetFirstPoint = false;
+
 			var d = node.getAttribute( 'd' );
 			var d = node.getAttribute( 'd' );
 
 
 			// console.log( d );
 			// console.log( d );
@@ -112,6 +135,11 @@ THREE.SVGLoader.prototype = {
 				var type = command.charAt( 0 );
 				var type = command.charAt( 0 );
 				var data = command.substr( 1 ).trim();
 				var data = command.substr( 1 ).trim();
 
 
+				if ( isFirstPoint ) {
+					doSetFirstPoint = true;
+				}
+				isFirstPoint = false;
+
 				switch ( type ) {
 				switch ( type ) {
 
 
 					case 'M':
 					case 'M':
@@ -121,7 +149,11 @@ THREE.SVGLoader.prototype = {
 							point.y = numbers[ j + 1 ];
 							point.y = numbers[ j + 1 ];
 							control.x = point.x;
 							control.x = point.x;
 							control.y = point.y;
 							control.y = point.y;
-							path.moveTo( point.x, point.y );
+							if ( j === 0 ) {
+								path.moveTo( point.x, point.y );
+							} else {
+								path.lineTo( point.x, point.y );
+							}
 						}
 						}
 						break;
 						break;
 
 
@@ -249,7 +281,11 @@ THREE.SVGLoader.prototype = {
 							point.y += numbers[ j + 1 ];
 							point.y += numbers[ j + 1 ];
 							control.x = point.x;
 							control.x = point.x;
 							control.y = point.y;
 							control.y = point.y;
-							path.moveTo( point.x, point.y );
+							if ( j === 0 ) {
+								path.moveTo( point.x, point.y );
+							} else {
+								path.lineTo( point.x, point.y );
+							}
 						}
 						}
 						break;
 						break;
 
 
@@ -375,21 +411,9 @@ THREE.SVGLoader.prototype = {
 						path.currentPath.autoClose = true;
 						path.currentPath.autoClose = true;
 						if ( path.currentPath.curves.length > 0 ) {
 						if ( path.currentPath.curves.length > 0 ) {
 							// Reset point to beginning of Path
 							// Reset point to beginning of Path
-							var curve = path.currentPath.curves[ 0 ];
-							if ( curve.isLineCurve ) {
-								point.x = curve.v1.x;
-								point.y = curve.v1.y;
-							} else if ( curve.isEllipseCurve || curve.isArcCurve ) {
-								point.x = curve.aX;
-								point.y = curve.aY;
-							} else if ( curve.isCubicBezierCurve || curve.isQuadraticBezierCurve ) {
-								point.x = curve.v0.x;
-								point.y = curve.v0.y;
-							} else if ( curve.isSplineCurve ) {
-								point.x = curve.points[ 0 ].x;
-								point.y = curve.points[ 0 ].y;
-							}
+							point.copy( firstPoint );
 							path.currentPath.currentPoint.copy( point );
 							path.currentPath.currentPoint.copy( point );
+							isFirstPoint = true;
 						}
 						}
 						break;
 						break;
 
 
@@ -400,6 +424,13 @@ THREE.SVGLoader.prototype = {
 
 
 				// console.log( type, parseFloats( data ), parseFloats( data ).length  )
 				// console.log( type, parseFloats( data ), parseFloats( data ).length  )
 
 
+				if ( doSetFirstPoint ) {
+
+					firstPoint.copy( point );
+
+					doSetFirstPoint = false;
+
+				}
 			}
 			}
 
 
 			return path;
 			return path;
@@ -503,7 +534,13 @@ THREE.SVGLoader.prototype = {
 			if ( rx !== 0 || ry !== 0 ) {
 			if ( rx !== 0 || ry !== 0 ) {
 
 
 				path.bezierCurveTo( x, y + h, x, y + h, x, y + h - 2 * ry );
 				path.bezierCurveTo( x, y + h, x, y + h, x, y + h - 2 * ry );
-				path.lineTo( x, y + 2 * ry );
+
+			}
+
+			path.lineTo( x, y + 2 * ry );
+
+			if ( rx !== 0 || ry !== 0 ) {
+
 				path.bezierCurveTo( x, y, x, y, x + 2 * rx, y );
 				path.bezierCurveTo( x, y, x, y, x + 2 * rx, y );
 
 
 			}
 			}
@@ -683,6 +720,252 @@ THREE.SVGLoader.prototype = {
 
 
 			return array;
 			return array;
 
 
+
+		}
+
+		function getNodeTransform( node ) {
+
+			if ( ! node.hasAttribute( 'transform' ) ) {
+				return null;
+			}
+
+			var transform = parseTransformNode( node );
+
+			if ( transform ) {
+
+				if ( transformStack.length > 0 ) {
+					transform.premultiply( transformStack[ transformStack.length - 1 ] );
+				}
+
+				currentTransform.copy( transform );
+				transformStack.push( transform );
+
+			}
+
+			return transform;
+
+		}
+
+		function parseTransformNode( node ) {
+
+			var transformAttr = node.getAttribute( 'transform' );
+			var transform = null;
+			var openParPos = transformAttr.indexOf( "(" );
+			var closeParPos = transformAttr.indexOf( ")" );
+
+			if ( openParPos > 0 && openParPos < closeParPos ) {
+
+				var transformType = transformAttr.substr( 0, openParPos );
+
+				var array = parseFloats( transformAttr.substr( openParPos + 1, closeParPos - openParPos - 1 ) );
+
+				switch ( transformType ) {
+
+					case "translate":
+
+						if ( array.length >= 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							var tx = array[ 0 ];
+							var ty = tx;
+
+							if ( array.length >= 2 ) {
+
+								ty = array[ 1 ];
+
+							}
+
+							transform.translate( tx, ty );
+
+						}
+
+						break;
+
+					case "rotate":
+
+						if ( array.length >= 1 ) {
+
+							var angle = 0;
+							var cx = 0;
+							var cy = 0;
+
+							transform = new THREE.Matrix3();
+
+							// Angle
+							angle = - array[ 0 ] * Math.PI / 180;
+
+							if ( array.length >= 3 ) {
+
+								// Center x, y
+								cx = array[ 1 ];
+								cy = array[ 2 ];
+
+							}
+
+							// Rotate around center (cx, cy)
+							tempTransform1.identity().translate( -cx, -cy );
+							tempTransform2.identity().rotate( angle );
+							tempTransform3.multiplyMatrices( tempTransform2, tempTransform1 );
+							tempTransform1.identity().translate( cx, cy );
+							transform.multiplyMatrices( tempTransform1, tempTransform3 );
+
+						}
+
+						break;
+
+					case "scale":
+
+						if ( array.length >= 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							var scaleX = array[ 0 ];
+							var scaleY = scaleX;
+
+							if ( array.length >= 2 ) {
+								scaleY = array[ 1 ];
+							}
+
+							transform.scale( scaleX, scaleY );
+
+						}
+
+						break;
+
+					case "skewX":
+
+						if ( array.length === 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							transform.set(
+								1, Math.tan( array[ 0 ] * Math.PI / 180 ), 0,
+								0, 1, 0,
+								0, 0, 1
+							);
+
+						}
+
+						break;
+
+					case "skewY":
+
+						if ( array.length === 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							transform.set(
+								1, 0, 0,
+								Math.tan( array[ 0 ] * Math.PI / 180 ), 1, 0,
+								0, 0, 1
+							);
+
+						}
+
+						break;
+
+					case "matrix":
+
+						if ( array.length === 6 ) {
+
+							transform = new THREE.Matrix3();
+
+							transform.set(
+								array[ 0 ], array[ 2 ], array[ 4 ],
+								array[ 1 ], array[ 3 ], array[ 5 ],
+								0, 0, 1
+							);
+
+						}
+
+						break;
+				}
+
+			}
+
+			return transform;
+
+		}
+
+		function transformPath( path, m ) {
+
+			function transfVec2( v2 ) {
+
+				tempV3.set( v2.x, v2.y, 1 ).applyMatrix3( m );
+
+				v2.set( tempV3.x, tempV3.y );
+
+			}
+
+			var isRotated = isTransformRotated( m );
+
+			var tempV2 = new THREE.Vector2();
+			var tempV3 = new THREE.Vector3();
+
+			var subPaths = path.subPaths;
+
+			for ( var i = 0, n = subPaths.length; i < n; i++ ) {
+
+				var subPath = subPaths[ i ];
+				var curves = subPath.curves;
+
+				for ( var j = 0; j < curves.length; j++ ) {
+
+					var curve = curves[ j ];
+
+					if ( curve.isLineCurve ) {
+
+						transfVec2( curve.v1 );
+						transfVec2( curve.v2 );
+
+					} else if ( curve.isCubicBezierCurve ) {
+
+						transfVec2( curve.v0 );
+						transfVec2( curve.v1 );
+						transfVec2( curve.v2 );
+						transfVec2( curve.v3 );
+
+					} else if ( curve.isQuadraticBezierCurve ) {
+
+						transfVec2( curve.v0 );
+						transfVec2( curve.v1 );
+						transfVec2( curve.v2 );
+
+					} else if ( curve.isEllipseCurve ) {
+
+						if ( isRotated ) {
+							console.warn( "SVGLoader: Elliptic arc or ellipse rotation or skewing is not implemented." );
+						}
+
+						tempV2.set( curve.aX, curve.aY );
+						transfVec2( tempV2 );
+						curve.aX = tempV2.x;
+						curve.aY = tempV2.y;
+
+						curve.xRadius *= getTransformScaleX( m );
+						curve.yRadius *= getTransformScaleY( m );
+
+					}
+
+				}
+
+			}
+
+		}
+
+		function isTransformRotated( m ) {
+			return m.elements[ 1 ] !== 0 || m.elements[ 3 ] !== 0;
+		}
+
+		function getTransformScaleX( m ) {
+			var te = m.elements;
+			return Math.sqrt( te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] )
+		}
+
+		function getTransformScaleY( m ) {
+			var te = m.elements;
+			return Math.sqrt( te[ 3 ] * te[ 3 ] + te[ 4 ] * te[ 4 ] )
 		}
 		}
 
 
 		//
 		//
@@ -691,6 +974,14 @@ THREE.SVGLoader.prototype = {
 
 
 		var paths = [];
 		var paths = [];
 
 
+		var transformStack = [];
+
+		var tempTransform1 = new THREE.Matrix3();
+		var tempTransform2 = new THREE.Matrix3();
+		var tempTransform3 = new THREE.Matrix3();
+
+		var currentTransform = new THREE.Matrix3();
+
 		console.time( 'THREE.SVGLoader: DOMParser' );
 		console.time( 'THREE.SVGLoader: DOMParser' );
 
 
 		var xml = new DOMParser().parseFromString( text, 'image/svg+xml' ); // application/xml
 		var xml = new DOMParser().parseFromString( text, 'image/svg+xml' ); // application/xml
@@ -703,6 +994,7 @@ THREE.SVGLoader.prototype = {
 
 
 		// console.log( paths );
 		// console.log( paths );
 
 
+
 		console.timeEnd( 'THREE.SVGLoader: Parse' );
 		console.timeEnd( 'THREE.SVGLoader: Parse' );
 
 
 		return paths;
 		return paths;

+ 8 - 0
examples/js/loaders/TGALoader.js

@@ -22,6 +22,7 @@ THREE.TGALoader.prototype = {
 
 
 		var loader = new THREE.FileLoader( this.manager );
 		var loader = new THREE.FileLoader( this.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setResponseType( 'arraybuffer' );
+		loader.setPath( this.path );
 
 
 		loader.load( url, function ( buffer ) {
 		loader.load( url, function ( buffer ) {
 
 
@@ -535,6 +536,13 @@ THREE.TGALoader.prototype = {
 
 
 		return canvas;
 		return canvas;
 
 
+	},
+
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
 	}
 	}
 
 
 };
 };

+ 7 - 1
examples/js/nodes/Nodes.js

@@ -2,7 +2,7 @@
 
 
 // core
 // core
 
 
-export { GLNode } from './core/GLNode.js';
+export { Node } from './core/Node.js';
 export { TempNode } from './core/TempNode.js';
 export { TempNode } from './core/TempNode.js';
 export { InputNode } from './core/InputNode.js';
 export { InputNode } from './core/InputNode.js';
 export { ConstNode } from './core/ConstNode.js';
 export { ConstNode } from './core/ConstNode.js';
@@ -10,6 +10,7 @@ export { VarNode } from './core/VarNode.js';
 export { StructNode } from './core/StructNode.js';
 export { StructNode } from './core/StructNode.js';
 export { AttributeNode } from './core/AttributeNode.js';
 export { AttributeNode } from './core/AttributeNode.js';
 export { FunctionNode } from './core/FunctionNode.js';
 export { FunctionNode } from './core/FunctionNode.js';
+export { ExpressionNode } from './core/ExpressionNode.js';
 export { FunctionCallNode } from './core/FunctionCallNode.js';
 export { FunctionCallNode } from './core/FunctionCallNode.js';
 export { NodeLib } from './core/NodeLib.js';
 export { NodeLib } from './core/NodeLib.js';
 export { NodeUtils } from './core/NodeUtils.js';
 export { NodeUtils } from './core/NodeUtils.js';
@@ -32,6 +33,7 @@ export { CubeTextureNode } from './inputs/CubeTextureNode.js';
 export { ScreenNode } from './inputs/ScreenNode.js';
 export { ScreenNode } from './inputs/ScreenNode.js';
 export { ReflectorNode } from './inputs/ReflectorNode.js';
 export { ReflectorNode } from './inputs/ReflectorNode.js';
 export { PropertyNode } from './inputs/PropertyNode.js';
 export { PropertyNode } from './inputs/PropertyNode.js';
+export { RTTNode } from './inputs/RTTNode.js';
 
 
 // accessors
 // accessors
 
 
@@ -51,10 +53,12 @@ export { Math1Node } from './math/Math1Node.js';
 export { Math2Node } from './math/Math2Node.js';
 export { Math2Node } from './math/Math2Node.js';
 export { Math3Node } from './math/Math3Node.js';
 export { Math3Node } from './math/Math3Node.js';
 export { OperatorNode } from './math/OperatorNode.js';
 export { OperatorNode } from './math/OperatorNode.js';
+export { CondNode } from './math/CondNode.js';
 
 
 // procedural
 // procedural
 
 
 export { NoiseNode } from './procedural/NoiseNode.js';
 export { NoiseNode } from './procedural/NoiseNode.js';
+export { CheckerNode } from './procedural/CheckerNode.js';
 
 
 // bsdfs
 // bsdfs
 
 
@@ -78,6 +82,7 @@ export { TimerNode } from './utils/TimerNode.js';
 export { VelocityNode } from './utils/VelocityNode.js';
 export { VelocityNode } from './utils/VelocityNode.js';
 export { UVTransformNode } from './utils/UVTransformNode.js';
 export { UVTransformNode } from './utils/UVTransformNode.js';
 export { MaxMIPLevelNode } from './utils/MaxMIPLevelNode.js';
 export { MaxMIPLevelNode } from './utils/MaxMIPLevelNode.js';
+export { ColorSpaceNode } from './utils/ColorSpaceNode.js';
 
 
 // effects
 // effects
 
 
@@ -103,4 +108,5 @@ export { MeshStandardNodeMaterial } from './materials/MeshStandardNodeMaterial.j
 
 
 // postprocessing
 // postprocessing
 
 
+export { NodePostProcessing } from './postprocessing/NodePostProcessing.js';
 //export { NodePass } from './postprocessing/NodePass.js';
 //export { NodePass } from './postprocessing/NodePass.js';

+ 43 - 25
examples/js/nodes/THREE.Nodes.js

@@ -1,8 +1,8 @@
-import { 
+import {
 
 
 	// core
 	// core
-	
-	GLNode,
+
+	Node,
 	TempNode,
 	TempNode,
 	InputNode,
 	InputNode,
 	ConstNode,
 	ConstNode,
@@ -10,15 +10,16 @@ import {
 	StructNode,
 	StructNode,
 	AttributeNode,
 	AttributeNode,
 	FunctionNode,
 	FunctionNode,
+	ExpressionNode,
 	FunctionCallNode,
 	FunctionCallNode,
 	NodeLib,
 	NodeLib,
 	NodeUtils,
 	NodeUtils,
 	NodeFrame,
 	NodeFrame,
 	NodeUniform,
 	NodeUniform,
 	NodeBuilder,
 	NodeBuilder,
-	
+
 	// inputs
 	// inputs
-	
+
 	IntNode,
 	IntNode,
 	FloatNode,
 	FloatNode,
 	Vector2Node,
 	Vector2Node,
@@ -32,9 +33,10 @@ import {
 	ScreenNode,
 	ScreenNode,
 	ReflectorNode,
 	ReflectorNode,
 	PropertyNode,
 	PropertyNode,
-	
+	RTTNode,
+
 	// accessors
 	// accessors
-	
+
 	UVNode,
 	UVNode,
 	ColorsNode,
 	ColorsNode,
 	PositionNode,
 	PositionNode,
@@ -44,33 +46,35 @@ import {
 	ReflectNode,
 	ReflectNode,
 	ScreenUVNode,
 	ScreenUVNode,
 	ResolutionNode,
 	ResolutionNode,
-	
+
 	// math
 	// math
-	
+
 	Math1Node,
 	Math1Node,
 	Math2Node,
 	Math2Node,
 	Math3Node,
 	Math3Node,
 	OperatorNode,
 	OperatorNode,
-	
+	CondNode,
+
 	// procedural
 	// procedural
-	
+
 	NoiseNode,
 	NoiseNode,
-	
+	CheckerNode,
+
 	// bsdfs
 	// bsdfs
-	
+
 	BlinnShininessExponentNode,
 	BlinnShininessExponentNode,
 	BlinnExponentToRoughnessNode,
 	BlinnExponentToRoughnessNode,
 	RoughnessToBlinnExponentNode,
 	RoughnessToBlinnExponentNode,
-	
+
 	// misc
 	// misc
-	
+
 	TextureCubeUVNode,
 	TextureCubeUVNode,
 	TextureCubeNode,
 	TextureCubeNode,
 	NormalMapNode,
 	NormalMapNode,
 	BumpMapNode,
 	BumpMapNode,
-	
+
 	// utils
 	// utils
-	
+
 	BypassNode,
 	BypassNode,
 	JoinNode,
 	JoinNode,
 	SwitchNode,
 	SwitchNode,
@@ -78,34 +82,39 @@ import {
 	VelocityNode,
 	VelocityNode,
 	UVTransformNode,
 	UVTransformNode,
 	MaxMIPLevelNode,
 	MaxMIPLevelNode,
-	
+	ColorSpaceNode,
+
 	// effects
 	// effects
-	
+
 	BlurNode,
 	BlurNode,
 	ColorAdjustmentNode,
 	ColorAdjustmentNode,
 	LuminanceNode,
 	LuminanceNode,
 
 
 	// material nodes
 	// material nodes
-	
+
 	RawNode,
 	RawNode,
 	SpriteNode,
 	SpriteNode,
 	PhongNode,
 	PhongNode,
 	StandardNode,
 	StandardNode,
 	MeshStandardNode,
 	MeshStandardNode,
-	
+
 	// materials
 	// materials
-	
+
 	NodeMaterial,
 	NodeMaterial,
 	SpriteNodeMaterial,
 	SpriteNodeMaterial,
 	PhongNodeMaterial,
 	PhongNodeMaterial,
 	StandardNodeMaterial,
 	StandardNodeMaterial,
-	MeshStandardNodeMaterial
-	
+	MeshStandardNodeMaterial,
+
+	// post-processing
+
+	NodePostProcessing
+
 } from './Nodes.js';
 } from './Nodes.js';
 
 
 // core
 // core
 
 
-THREE.GLNode = GLNode;
+THREE.Node = Node;
 THREE.TempNode = TempNode;
 THREE.TempNode = TempNode;
 THREE.InputNode = InputNode;
 THREE.InputNode = InputNode;
 THREE.ConstNode = ConstNode;
 THREE.ConstNode = ConstNode;
@@ -113,6 +122,7 @@ THREE.VarNode = VarNode;
 THREE.StructNode = StructNode;
 THREE.StructNode = StructNode;
 THREE.AttributeNode = AttributeNode;
 THREE.AttributeNode = AttributeNode;
 THREE.FunctionNode = FunctionNode;
 THREE.FunctionNode = FunctionNode;
+THREE.ExpressionNode = ExpressionNode;
 THREE.FunctionCallNode = FunctionCallNode;
 THREE.FunctionCallNode = FunctionCallNode;
 THREE.NodeLib = NodeLib;
 THREE.NodeLib = NodeLib;
 THREE.NodeUtils = NodeUtils;
 THREE.NodeUtils = NodeUtils;
@@ -135,6 +145,7 @@ THREE.CubeTextureNode = CubeTextureNode;
 THREE.ScreenNode = ScreenNode;
 THREE.ScreenNode = ScreenNode;
 THREE.ReflectorNode = ReflectorNode;
 THREE.ReflectorNode = ReflectorNode;
 THREE.PropertyNode = PropertyNode;
 THREE.PropertyNode = PropertyNode;
+THREE.RTTNode = RTTNode;
 
 
 // accessors
 // accessors
 
 
@@ -154,10 +165,12 @@ THREE.Math1Node = Math1Node;
 THREE.Math2Node = Math2Node;
 THREE.Math2Node = Math2Node;
 THREE.Math3Node = Math3Node;
 THREE.Math3Node = Math3Node;
 THREE.OperatorNode = OperatorNode;
 THREE.OperatorNode = OperatorNode;
+THREE.CondNode = CondNode;
 
 
 // procedural
 // procedural
 
 
 THREE.NoiseNode = NoiseNode;
 THREE.NoiseNode = NoiseNode;
+THREE.CheckerNode = CheckerNode;
 
 
 // bsdfs
 // bsdfs
 
 
@@ -181,6 +194,7 @@ THREE.TimerNode = TimerNode;
 THREE.VelocityNode = VelocityNode;
 THREE.VelocityNode = VelocityNode;
 THREE.UVTransformNode = UVTransformNode;
 THREE.UVTransformNode = UVTransformNode;
 THREE.MaxMIPLevelNode = MaxMIPLevelNode;
 THREE.MaxMIPLevelNode = MaxMIPLevelNode;
+THREE.ColorSpaceNode = ColorSpaceNode;
 
 
 // effects
 // effects
 
 
@@ -203,3 +217,7 @@ THREE.SpriteNodeMaterial = SpriteNodeMaterial;
 THREE.PhongNodeMaterial = PhongNodeMaterial;
 THREE.PhongNodeMaterial = PhongNodeMaterial;
 THREE.StandardNodeMaterial = StandardNodeMaterial;
 THREE.StandardNodeMaterial = StandardNodeMaterial;
 THREE.MeshStandardNodeMaterial = MeshStandardNodeMaterial;
 THREE.MeshStandardNodeMaterial = MeshStandardNodeMaterial;
+
+// post-processing
+
+THREE.NodePostProcessing = NodePostProcessing;

+ 22 - 22
examples/js/nodes/accessors/CameraNode.js

@@ -6,7 +6,7 @@ import { TempNode } from '../core/TempNode.js';
 import { FunctionNode } from '../core/FunctionNode.js';
 import { FunctionNode } from '../core/FunctionNode.js';
 import { FloatNode } from '../inputs/FloatNode.js';
 import { FloatNode } from '../inputs/FloatNode.js';
 import { PositionNode } from '../accessors/PositionNode.js';
 import { PositionNode } from '../accessors/PositionNode.js';
- 
+
 function CameraNode( scope, camera ) {
 function CameraNode( scope, camera ) {
 
 
 	TempNode.call( this, 'v3' );
 	TempNode.call( this, 'v3' );
@@ -14,33 +14,33 @@ function CameraNode( scope, camera ) {
 	this.setScope( scope || CameraNode.POSITION );
 	this.setScope( scope || CameraNode.POSITION );
 	this.setCamera( camera );
 	this.setCamera( camera );
 
 
-};
+}
+
+CameraNode.Nodes = ( function () {
 
 
-CameraNode.Nodes = (function() {
-	
 	var depthColor = new FunctionNode( [
 	var depthColor = new FunctionNode( [
 		"float depthColor( float mNear, float mFar ) {",
 		"float depthColor( float mNear, float mFar ) {",
-		
+
 		"	#ifdef USE_LOGDEPTHBUF_EXT",
 		"	#ifdef USE_LOGDEPTHBUF_EXT",
-		
+
 		"		float depth = gl_FragDepthEXT / gl_FragCoord.w;",
 		"		float depth = gl_FragDepthEXT / gl_FragCoord.w;",
-		
+
 		"	#else",
 		"	#else",
-		
+
 		"		float depth = gl_FragCoord.z / gl_FragCoord.w;",
 		"		float depth = gl_FragCoord.z / gl_FragCoord.w;",
-		
+
 		"	#endif",
 		"	#endif",
-		
+
 		"	return 1.0 - smoothstep( mNear, mFar, depth );",
 		"	return 1.0 - smoothstep( mNear, mFar, depth );",
-		
+
 		"}"
 		"}"
 	].join( "\n" ) );
 	].join( "\n" ) );
-	
+
 	return {
 	return {
 		depthColor: depthColor
 		depthColor: depthColor
 	};
 	};
-	
-})();
+
+} )();
 
 
 CameraNode.POSITION = 'position';
 CameraNode.POSITION = 'position';
 CameraNode.DEPTH = 'depth';
 CameraNode.DEPTH = 'depth';
@@ -92,7 +92,7 @@ CameraNode.prototype.getType = function ( builder ) {
 	switch ( this.scope ) {
 	switch ( this.scope ) {
 
 
 		case CameraNode.DEPTH:
 		case CameraNode.DEPTH:
-		
+
 			return 'f';
 			return 'f';
 
 
 	}
 	}
@@ -107,7 +107,7 @@ CameraNode.prototype.isUnique = function ( builder ) {
 
 
 		case CameraNode.DEPTH:
 		case CameraNode.DEPTH:
 		case CameraNode.TO_VERTEX:
 		case CameraNode.TO_VERTEX:
-		
+
 			return true;
 			return true;
 
 
 	}
 	}
@@ -121,7 +121,7 @@ CameraNode.prototype.isShared = function ( builder ) {
 	switch ( this.scope ) {
 	switch ( this.scope ) {
 
 
 		case CameraNode.POSITION:
 		case CameraNode.POSITION:
-		
+
 			return false;
 			return false;
 
 
 	}
 	}
@@ -180,15 +180,15 @@ CameraNode.prototype.onUpdateFrame = function ( frame ) {
 };
 };
 
 
 CameraNode.prototype.copy = function ( source ) {
 CameraNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.setScope( source.scope );
 	this.setScope( source.scope );
 
 
 	if ( source.camera ) {
 	if ( source.camera ) {
-		
+
 		this.setCamera( source.camera );
 		this.setCamera( source.camera );
-		
+
 	}
 	}
 
 
 	switch ( source.scope ) {
 	switch ( source.scope ) {
@@ -201,7 +201,7 @@ CameraNode.prototype.copy = function ( source ) {
 			break;
 			break;
 
 
 	}
 	}
-	
+
 };
 };
 
 
 CameraNode.prototype.toJSON = function ( meta ) {
 CameraNode.prototype.toJSON = function ( meta ) {

+ 7 - 8
examples/js/nodes/accessors/ColorsNode.js

@@ -1,20 +1,19 @@
 /**
 /**
  * @author sunag / http://www.sunag.com.br/
  * @author sunag / http://www.sunag.com.br/
  */
  */
- 
+
 import { TempNode } from '../core/TempNode.js';
 import { TempNode } from '../core/TempNode.js';
-import { NodeLib } from '../core/NodeLib.js';
- 
+
 var vertexDict = [ 'color', 'color2' ],
 var vertexDict = [ 'color', 'color2' ],
 	fragmentDict = [ 'vColor', 'vColor2' ];
 	fragmentDict = [ 'vColor', 'vColor2' ];
- 
+
 function ColorsNode( index ) {
 function ColorsNode( index ) {
 
 
 	TempNode.call( this, 'v4', { shared: false } );
 	TempNode.call( this, 'v4', { shared: false } );
 
 
 	this.index = index || 0;
 	this.index = index || 0;
 
 
-};
+}
 
 
 ColorsNode.prototype = Object.create( TempNode.prototype );
 ColorsNode.prototype = Object.create( TempNode.prototype );
 ColorsNode.prototype.constructor = ColorsNode;
 ColorsNode.prototype.constructor = ColorsNode;
@@ -30,11 +29,11 @@ ColorsNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 ColorsNode.prototype.copy = function ( source ) {
 ColorsNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.index = source.index;
 	this.index = source.index;
-	
+
 };
 };
 
 
 ColorsNode.prototype.toJSON = function ( meta ) {
 ColorsNode.prototype.toJSON = function ( meta ) {

+ 6 - 6
examples/js/nodes/accessors/LightNode.js

@@ -10,7 +10,7 @@ function LightNode( scope ) {
 
 
 	this.scope = scope || LightNode.TOTAL;
 	this.scope = scope || LightNode.TOTAL;
 
 
-};
+}
 
 
 LightNode.TOTAL = 'total';
 LightNode.TOTAL = 'total';
 
 
@@ -22,24 +22,24 @@ LightNode.prototype.generate = function ( builder, output ) {
 
 
 	if ( builder.isCache( 'light' ) ) {
 	if ( builder.isCache( 'light' ) ) {
 
 
-		return builder.format( 'reflectedLight.directDiffuse', this.getType( builder ), output );
+		return builder.format( 'reflectedLight.directDiffuse', this.type, output );
 
 
 	} else {
 	} else {
 
 
 		console.warn( "THREE.LightNode is only compatible in \"light\" channel." );
 		console.warn( "THREE.LightNode is only compatible in \"light\" channel." );
 
 
-		return builder.format( 'vec3( 0.0 )', this.getType( builder ), output );
+		return builder.format( 'vec3( 0.0 )', this.type, output );
 
 
 	}
 	}
 
 
 };
 };
 
 
 LightNode.prototype.copy = function ( source ) {
 LightNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.scope = source.scope;
 	this.scope = source.scope;
-	
+
 };
 };
 
 
 LightNode.prototype.toJSON = function ( meta ) {
 LightNode.prototype.toJSON = function ( meta ) {

+ 7 - 7
examples/js/nodes/accessors/NormalNode.js

@@ -4,14 +4,14 @@
 
 
 import { TempNode } from '../core/TempNode.js';
 import { TempNode } from '../core/TempNode.js';
 import { NodeLib } from '../core/NodeLib.js';
 import { NodeLib } from '../core/NodeLib.js';
- 
+
 function NormalNode( scope ) {
 function NormalNode( scope ) {
 
 
 	TempNode.call( this, 'v3' );
 	TempNode.call( this, 'v3' );
 
 
 	this.scope = scope || NormalNode.LOCAL;
 	this.scope = scope || NormalNode.LOCAL;
 
 
-};
+}
 
 
 NormalNode.LOCAL = 'local';
 NormalNode.LOCAL = 'local';
 NormalNode.WORLD = 'world';
 NormalNode.WORLD = 'world';
@@ -45,7 +45,7 @@ NormalNode.prototype.generate = function ( builder, output ) {
 
 
 			builder.requires.normal = true;
 			builder.requires.normal = true;
 
 
-			result = builder.isShader( 'vertex' ) ? 'normal' : 'vObjectNormal';
+			result = 'normal';
 
 
 			break;
 			break;
 
 
@@ -54,7 +54,7 @@ NormalNode.prototype.generate = function ( builder, output ) {
 			builder.requires.worldNormal = true;
 			builder.requires.worldNormal = true;
 
 
 			result = builder.isShader( 'vertex' ) ? '( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz' : 'vWNormal';
 			result = builder.isShader( 'vertex' ) ? '( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz' : 'vWNormal';
-			
+
 			break;
 			break;
 
 
 		case NormalNode.VIEW:
 		case NormalNode.VIEW:
@@ -70,11 +70,11 @@ NormalNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 NormalNode.prototype.copy = function ( source ) {
 NormalNode.prototype.copy = function ( source ) {
-	
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.scope = source.scope;
 	this.scope = source.scope;
-	
+
 };
 };
 
 
 NormalNode.prototype.toJSON = function ( meta ) {
 NormalNode.prototype.toJSON = function ( meta ) {

+ 8 - 8
examples/js/nodes/accessors/PositionNode.js

@@ -4,14 +4,14 @@
 
 
 import { TempNode } from '../core/TempNode.js';
 import { TempNode } from '../core/TempNode.js';
 import { NodeLib } from '../core/NodeLib.js';
 import { NodeLib } from '../core/NodeLib.js';
- 
+
 function PositionNode( scope ) {
 function PositionNode( scope ) {
 
 
 	TempNode.call( this, 'v3' );
 	TempNode.call( this, 'v3' );
 
 
 	this.scope = scope || PositionNode.LOCAL;
 	this.scope = scope || PositionNode.LOCAL;
 
 
-};
+}
 
 
 PositionNode.LOCAL = 'local';
 PositionNode.LOCAL = 'local';
 PositionNode.WORLD = 'world';
 PositionNode.WORLD = 'world';
@@ -22,12 +22,12 @@ PositionNode.prototype = Object.create( TempNode.prototype );
 PositionNode.prototype.constructor = PositionNode;
 PositionNode.prototype.constructor = PositionNode;
 PositionNode.prototype.nodeType = "Position";
 PositionNode.prototype.nodeType = "Position";
 
 
-PositionNode.prototype.getType = function ( builder ) {
+PositionNode.prototype.getType = function ( ) {
 
 
 	switch ( this.scope ) {
 	switch ( this.scope ) {
 
 
 		case PositionNode.PROJECTION:
 		case PositionNode.PROJECTION:
-		
+
 			return 'v4';
 			return 'v4';
 
 
 	}
 	}
@@ -42,7 +42,7 @@ PositionNode.prototype.isShared = function ( builder ) {
 
 
 		case PositionNode.LOCAL:
 		case PositionNode.LOCAL:
 		case PositionNode.WORLD:
 		case PositionNode.WORLD:
-		
+
 			return false;
 			return false;
 
 
 	}
 	}
@@ -92,11 +92,11 @@ PositionNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 PositionNode.prototype.copy = function ( source ) {
 PositionNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.scope = source.scope;
 	this.scope = source.scope;
-	
+
 };
 };
 
 
 PositionNode.prototype.toJSON = function ( meta ) {
 PositionNode.prototype.toJSON = function ( meta ) {

+ 6 - 6
examples/js/nodes/accessors/ReflectNode.js

@@ -10,7 +10,7 @@ function ReflectNode( scope ) {
 
 
 	this.scope = scope || ReflectNode.CUBE;
 	this.scope = scope || ReflectNode.CUBE;
 
 
-};
+}
 
 
 ReflectNode.CUBE = 'cube';
 ReflectNode.CUBE = 'cube';
 ReflectNode.SPHERE = 'sphere';
 ReflectNode.SPHERE = 'sphere';
@@ -37,7 +37,7 @@ ReflectNode.prototype.getType = function ( builder ) {
 ReflectNode.prototype.generate = function ( builder, output ) {
 ReflectNode.prototype.generate = function ( builder, output ) {
 
 
 	if ( builder.isShader( 'fragment' ) ) {
 	if ( builder.isShader( 'fragment' ) ) {
-		
+
 		var result;
 		var result;
 
 
 		switch ( this.scope ) {
 		switch ( this.scope ) {
@@ -72,14 +72,14 @@ ReflectNode.prototype.generate = function ( builder, output ) {
 
 
 		}
 		}
 
 
-		return builder.format( result, this.getType( this.type ), output );
-	
+		return builder.format( result, this.getType( builder ), output );
+
 	} else {
 	} else {
-		
+
 		console.warn( "THREE.ReflectNode is not compatible with " + builder.shader + " shader." );
 		console.warn( "THREE.ReflectNode is not compatible with " + builder.shader + " shader." );
 
 
 		return builder.format( 'vec3( 0.0 )', this.type, output );
 		return builder.format( 'vec3( 0.0 )', this.type, output );
-		
+
 	}
 	}
 
 
 };
 };

+ 18 - 12
examples/js/nodes/accessors/ResolutionNode.js

@@ -3,14 +3,12 @@
  */
  */
 
 
 import { Vector2Node } from '../inputs/Vector2Node.js';
 import { Vector2Node } from '../inputs/Vector2Node.js';
- 
-function ResolutionNode( renderer ) {
 
 
-	Vector2Node.call( this );
+function ResolutionNode() {
 
 
-	this.renderer = renderer;
+	Vector2Node.call( this );
 
 
-};
+}
 
 
 ResolutionNode.prototype = Object.create( Vector2Node.prototype );
 ResolutionNode.prototype = Object.create( Vector2Node.prototype );
 ResolutionNode.prototype.constructor = ResolutionNode;
 ResolutionNode.prototype.constructor = ResolutionNode;
@@ -18,20 +16,28 @@ ResolutionNode.prototype.nodeType = "Resolution";
 
 
 ResolutionNode.prototype.updateFrame = function ( frame ) {
 ResolutionNode.prototype.updateFrame = function ( frame ) {
 
 
-	var size = this.renderer.getSize(),
-		pixelRatio = this.renderer.getPixelRatio();
+	if ( frame.renderer ) {
+
+		var size = frame.renderer.getSize(),
+			pixelRatio = frame.renderer.getPixelRatio();
+
+		this.x = size.width * pixelRatio;
+		this.y = size.height * pixelRatio;
+
+	} else {
 
 
-	this.x = size.width * pixelRatio;
-	this.y = size.height * pixelRatio;
+		console.warn( "ResolutionNode need a renderer in NodeFrame" );
+
+	}
 
 
 };
 };
 
 
 ResolutionNode.prototype.copy = function ( source ) {
 ResolutionNode.prototype.copy = function ( source ) {
-			
+
 	Vector2Node.prototype.copy.call( this, source );
 	Vector2Node.prototype.copy.call( this, source );
-	
+
 	this.renderer = source.renderer;
 	this.renderer = source.renderer;
-	
+
 };
 };
 
 
 ResolutionNode.prototype.toJSON = function ( meta ) {
 ResolutionNode.prototype.toJSON = function ( meta ) {

+ 7 - 6
examples/js/nodes/accessors/ScreenUVNode.js

@@ -3,14 +3,15 @@
  */
  */
 
 
 import { TempNode } from '../core/TempNode.js';
 import { TempNode } from '../core/TempNode.js';
- 
+import { ResolutionNode } from './ResolutionNode.js';
+
 function ScreenUVNode( resolution ) {
 function ScreenUVNode( resolution ) {
 
 
 	TempNode.call( this, 'v2' );
 	TempNode.call( this, 'v2' );
 
 
-	this.resolution = resolution;
+	this.resolution = resolution || new ResolutionNode();
 
 
-};
+}
 
 
 ScreenUVNode.prototype = Object.create( TempNode.prototype );
 ScreenUVNode.prototype = Object.create( TempNode.prototype );
 ScreenUVNode.prototype.constructor = ScreenUVNode;
 ScreenUVNode.prototype.constructor = ScreenUVNode;
@@ -37,11 +38,11 @@ ScreenUVNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 ScreenUVNode.prototype.copy = function ( source ) {
 ScreenUVNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.resolution = source.resolution;
 	this.resolution = source.resolution;
-	
+
 };
 };
 
 
 ScreenUVNode.prototype.toJSON = function ( meta ) {
 ScreenUVNode.prototype.toJSON = function ( meta ) {

+ 6 - 6
examples/js/nodes/accessors/UVNode.js

@@ -4,17 +4,17 @@
 
 
 import { TempNode } from '../core/TempNode.js';
 import { TempNode } from '../core/TempNode.js';
 import { NodeLib } from '../core/NodeLib.js';
 import { NodeLib } from '../core/NodeLib.js';
- 
+
 var vertexDict = [ 'uv', 'uv2' ],
 var vertexDict = [ 'uv', 'uv2' ],
 	fragmentDict = [ 'vUv', 'vUv2' ];
 	fragmentDict = [ 'vUv', 'vUv2' ];
- 
+
 function UVNode( index ) {
 function UVNode( index ) {
 
 
 	TempNode.call( this, 'v2', { shared: false } );
 	TempNode.call( this, 'v2', { shared: false } );
 
 
 	this.index = index || 0;
 	this.index = index || 0;
 
 
-};
+}
 
 
 UVNode.prototype = Object.create( TempNode.prototype );
 UVNode.prototype = Object.create( TempNode.prototype );
 UVNode.prototype.constructor = UVNode;
 UVNode.prototype.constructor = UVNode;
@@ -31,11 +31,11 @@ UVNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 UVNode.prototype.copy = function ( source ) {
 UVNode.prototype.copy = function ( source ) {
-		
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.index = source.index;
 	this.index = source.index;
-	
+
 };
 };
 
 
 UVNode.prototype.toJSON = function ( meta ) {
 UVNode.prototype.toJSON = function ( meta ) {

+ 4 - 4
examples/js/nodes/bsdfs/BlinnExponentToRoughnessNode.js

@@ -11,7 +11,7 @@ function BlinnExponentToRoughnessNode( blinnExponent ) {
 
 
 	this.blinnExponent = blinnExponent || new BlinnShininessExponentNode();
 	this.blinnExponent = blinnExponent || new BlinnShininessExponentNode();
 
 
-};
+}
 
 
 BlinnExponentToRoughnessNode.prototype = Object.create( TempNode.prototype );
 BlinnExponentToRoughnessNode.prototype = Object.create( TempNode.prototype );
 BlinnExponentToRoughnessNode.prototype.constructor = BlinnExponentToRoughnessNode;
 BlinnExponentToRoughnessNode.prototype.constructor = BlinnExponentToRoughnessNode;
@@ -24,11 +24,11 @@ BlinnExponentToRoughnessNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 BlinnExponentToRoughnessNode.prototype.copy = function ( source ) {
 BlinnExponentToRoughnessNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.blinnExponent = source.blinnExponent;
 	this.blinnExponent = source.blinnExponent;
-	
+
 };
 };
 
 
 BlinnExponentToRoughnessNode.prototype.toJSON = function ( meta ) {
 BlinnExponentToRoughnessNode.prototype.toJSON = function ( meta ) {

+ 1 - 1
examples/js/nodes/bsdfs/BlinnShininessExponentNode.js

@@ -8,7 +8,7 @@ function BlinnShininessExponentNode() {
 
 
 	TempNode.call( this, 'f' );
 	TempNode.call( this, 'f' );
 
 
-};
+}
 
 
 BlinnShininessExponentNode.prototype = Object.create( TempNode.prototype );
 BlinnShininessExponentNode.prototype = Object.create( TempNode.prototype );
 BlinnShininessExponentNode.prototype.constructor = BlinnShininessExponentNode;
 BlinnShininessExponentNode.prototype.constructor = BlinnShininessExponentNode;

+ 12 - 11
examples/js/nodes/bsdfs/RoughnessToBlinnExponentNode.js

@@ -6,7 +6,7 @@ import { TempNode } from '../core/TempNode.js';
 import { FunctionNode } from '../core/FunctionNode.js';
 import { FunctionNode } from '../core/FunctionNode.js';
 import { MaxMIPLevelNode } from '../utils/MaxMIPLevelNode.js';
 import { MaxMIPLevelNode } from '../utils/MaxMIPLevelNode.js';
 import { BlinnShininessExponentNode } from './BlinnShininessExponentNode.js';
 import { BlinnShininessExponentNode } from './BlinnShininessExponentNode.js';
- 
+
 function RoughnessToBlinnExponentNode( texture ) {
 function RoughnessToBlinnExponentNode( texture ) {
 
 
 	TempNode.call( this, 'f' );
 	TempNode.call( this, 'f' );
@@ -16,9 +16,9 @@ function RoughnessToBlinnExponentNode( texture ) {
 	this.maxMIPLevel = new MaxMIPLevelNode( texture );
 	this.maxMIPLevel = new MaxMIPLevelNode( texture );
 	this.blinnShininessExponent = new BlinnShininessExponentNode();
 	this.blinnShininessExponent = new BlinnShininessExponentNode();
 
 
-};
+}
 
 
-RoughnessToBlinnExponentNode.Nodes = (function() {
+RoughnessToBlinnExponentNode.Nodes = ( function () {
 
 
 	var getSpecularMIPLevel = new FunctionNode( [
 	var getSpecularMIPLevel = new FunctionNode( [
 		// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
 		// taken from here: http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html
@@ -27,18 +27,19 @@ RoughnessToBlinnExponentNode.Nodes = (function() {
 		//	float envMapWidth = pow( 2.0, maxMIPLevelScalar );
 		//	float envMapWidth = pow( 2.0, maxMIPLevelScalar );
 		//	float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
 		//	float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
 
 
-		"	float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );",
+		"	float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );",
 
 
 		// clamp to allowable LOD ranges.
 		// clamp to allowable LOD ranges.
 		"	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );",
 		"	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );",
+
 		"}"
 		"}"
 	].join( "\n" ) );
 	].join( "\n" ) );
-	
+
 	return {
 	return {
 		getSpecularMIPLevel: getSpecularMIPLevel
 		getSpecularMIPLevel: getSpecularMIPLevel
 	};
 	};
-	
-})();
+
+} )();
 
 
 RoughnessToBlinnExponentNode.prototype = Object.create( TempNode.prototype );
 RoughnessToBlinnExponentNode.prototype = Object.create( TempNode.prototype );
 RoughnessToBlinnExponentNode.prototype.constructor = RoughnessToBlinnExponentNode;
 RoughnessToBlinnExponentNode.prototype.constructor = RoughnessToBlinnExponentNode;
@@ -49,7 +50,7 @@ RoughnessToBlinnExponentNode.prototype.generate = function ( builder, output ) {
 	if ( builder.isShader( 'fragment' ) ) {
 	if ( builder.isShader( 'fragment' ) ) {
 
 
 		this.maxMIPLevel.texture = this.texture;
 		this.maxMIPLevel.texture = this.texture;
-	
+
 		var getSpecularMIPLevel = builder.include( RoughnessToBlinnExponentNode.Nodes.getSpecularMIPLevel );
 		var getSpecularMIPLevel = builder.include( RoughnessToBlinnExponentNode.Nodes.getSpecularMIPLevel );
 
 
 		return builder.format( getSpecularMIPLevel + '( ' + this.blinnShininessExponent.build( builder, 'f' ) + ', ' + this.maxMIPLevel.build( builder, 'f' ) + ' )', this.type, output );
 		return builder.format( getSpecularMIPLevel + '( ' + this.blinnShininessExponent.build( builder, 'f' ) + ', ' + this.maxMIPLevel.build( builder, 'f' ) + ' )', this.type, output );
@@ -65,11 +66,11 @@ RoughnessToBlinnExponentNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 RoughnessToBlinnExponentNode.prototype.copy = function ( source ) {
 RoughnessToBlinnExponentNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.texture = source.texture;
 	this.texture = source.texture;
-	
+
 };
 };
 
 
 RoughnessToBlinnExponentNode.prototype.toJSON = function ( meta ) {
 RoughnessToBlinnExponentNode.prototype.toJSON = function ( meta ) {

+ 9 - 9
examples/js/nodes/core/AttributeNode.js

@@ -2,17 +2,17 @@
  * @author sunag / http://www.sunag.com.br/
  * @author sunag / http://www.sunag.com.br/
  */
  */
 
 
-import { GLNode } from './GLNode.js';
+import { Node } from './Node.js';
 
 
 function AttributeNode( name, type ) {
 function AttributeNode( name, type ) {
 
 
-	GLNode.call( this, type );
+	Node.call( this, type );
 
 
 	this.name = name;
 	this.name = name;
 
 
-};
+}
 
 
-AttributeNode.prototype = Object.create( GLNode.prototype );
+AttributeNode.prototype = Object.create( Node.prototype );
 AttributeNode.prototype.constructor = AttributeNode;
 AttributeNode.prototype.constructor = AttributeNode;
 AttributeNode.prototype.nodeType = "Attribute";
 AttributeNode.prototype.nodeType = "Attribute";
 
 
@@ -38,17 +38,17 @@ AttributeNode.prototype.generate = function ( builder, output ) {
 		name = builder.isShader( 'vertex' ) ? this.name : attribute.varying.name;
 		name = builder.isShader( 'vertex' ) ? this.name : attribute.varying.name;
 
 
 	console.log( attribute );
 	console.log( attribute );
-		
+
 	return builder.format( name, this.getType( builder ), output );
 	return builder.format( name, this.getType( builder ), output );
 
 
 };
 };
 
 
 AttributeNode.prototype.copy = function ( source ) {
 AttributeNode.prototype.copy = function ( source ) {
-			
-	GLNode.prototype.copy.call( this, source );
-	
+
+	Node.prototype.copy.call( this, source );
+
 	this.type = source.type;
 	this.type = source.type;
-	
+
 };
 };
 
 
 AttributeNode.prototype.toJSON = function ( meta ) {
 AttributeNode.prototype.toJSON = function ( meta ) {

+ 12 - 12
examples/js/nodes/core/ConstNode.js

@@ -4,13 +4,15 @@
 
 
 import { TempNode } from './TempNode.js';
 import { TempNode } from './TempNode.js';
 
 
+var declarationRegexp = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=?\s?(.*?)(\;|$)/i;
+
 function ConstNode( src, useDefine ) {
 function ConstNode( src, useDefine ) {
 
 
 	TempNode.call( this );
 	TempNode.call( this );
 
 
 	this.eval( src || ConstNode.PI, useDefine );
 	this.eval( src || ConstNode.PI, useDefine );
 
 
-};
+}
 
 
 ConstNode.PI = 'PI';
 ConstNode.PI = 'PI';
 ConstNode.PI2 = 'PI2';
 ConstNode.PI2 = 'PI2';
@@ -19,8 +21,6 @@ ConstNode.RECIPROCAL_PI2 = 'RECIPROCAL_PI2';
 ConstNode.LOG2 = 'LOG2';
 ConstNode.LOG2 = 'LOG2';
 ConstNode.EPSILON = 'EPSILON';
 ConstNode.EPSILON = 'EPSILON';
 
 
-ConstNode.rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=?\s?(.*?)(\;|$)/i;
-
 ConstNode.prototype = Object.create( TempNode.prototype );
 ConstNode.prototype = Object.create( TempNode.prototype );
 ConstNode.prototype.constructor = ConstNode;
 ConstNode.prototype.constructor = ConstNode;
 ConstNode.prototype.nodeType = "Const";
 ConstNode.prototype.nodeType = "Const";
@@ -37,9 +37,9 @@ ConstNode.prototype.eval = function ( src, useDefine ) {
 
 
 	var name, type, value = "";
 	var name, type, value = "";
 
 
-	var match = this.src.match( ConstNode.rDeclaration );
+	var match = this.src.match( declarationRegexp );
 
 
-	this.useDefine = useDefine || this.src.charAt(0) === '#';
+	this.useDefine = useDefine || this.src.charAt( 0 ) === '#';
 
 
 	if ( match && match.length > 1 ) {
 	if ( match && match.length > 1 ) {
 
 
@@ -74,10 +74,10 @@ ConstNode.prototype.build = function ( builder, output ) {
 
 
 			return 'const ' + this.type + ' ' + this.name + ' = ' + this.value + ';';
 			return 'const ' + this.type + ' ' + this.name + ' = ' + this.value + ';';
 
 
-		} else if (this.useDefine) {
-		
+		} else if ( this.useDefine ) {
+
 			return this.src;
 			return this.src;
-			
+
 		}
 		}
 
 
 	} else {
 	} else {
@@ -97,11 +97,11 @@ ConstNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 ConstNode.prototype.copy = function ( source ) {
 ConstNode.prototype.copy = function ( source ) {
-	
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
-	this.eval( source.src, source.useDefine );	
-	
+
+	this.eval( source.src, source.useDefine );
+
 };
 };
 
 
 ConstNode.prototype.toJSON = function ( meta ) {
 ConstNode.prototype.toJSON = function ( meta ) {

+ 17 - 0
examples/js/nodes/core/ExpressionNode.js

@@ -0,0 +1,17 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { FunctionNode } from './FunctionNode.js';
+
+function ExpressionNode( src, type, keywords, extensions, includes ) {
+
+	FunctionNode.call( this, src, includes, extensions, keywords, type );
+
+}
+
+ExpressionNode.prototype = Object.create( FunctionNode.prototype );
+ExpressionNode.prototype.constructor = ExpressionNode;
+ExpressionNode.prototype.nodeType = "Expression";
+
+export { ExpressionNode };

+ 5 - 5
examples/js/nodes/core/FunctionCallNode.js

@@ -3,14 +3,14 @@
  */
  */
 
 
 import { TempNode } from './TempNode.js';
 import { TempNode } from './TempNode.js';
- 
+
 function FunctionCallNode( func, inputs ) {
 function FunctionCallNode( func, inputs ) {
 
 
 	TempNode.call( this );
 	TempNode.call( this );
 
 
 	this.setFunction( func, inputs );
 	this.setFunction( func, inputs );
 
 
-};
+}
 
 
 FunctionCallNode.prototype = Object.create( TempNode.prototype );
 FunctionCallNode.prototype = Object.create( TempNode.prototype );
 FunctionCallNode.prototype.constructor = FunctionCallNode;
 FunctionCallNode.prototype.constructor = FunctionCallNode;
@@ -59,9 +59,9 @@ FunctionCallNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 FunctionCallNode.prototype.copy = function ( source ) {
 FunctionCallNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	for ( var prop in source.inputs ) {
 	for ( var prop in source.inputs ) {
 
 
 		this.inputs[ prop ] = source.inputs[ prop ];
 		this.inputs[ prop ] = source.inputs[ prop ];
@@ -69,7 +69,7 @@ FunctionCallNode.prototype.copy = function ( source ) {
 	}
 	}
 
 
 	this.value = source.value;
 	this.value = source.value;
-	
+
 };
 };
 
 
 FunctionCallNode.prototype.toJSON = function ( meta ) {
 FunctionCallNode.prototype.toJSON = function ( meta ) {

+ 25 - 26
examples/js/nodes/core/FunctionNode.js

@@ -6,32 +6,25 @@
 import { TempNode } from './TempNode.js';
 import { TempNode } from './TempNode.js';
 import { NodeLib } from './NodeLib.js';
 import { NodeLib } from './NodeLib.js';
 
 
-function FunctionNode( src, includesOrType, extensionsOrKeywords, keywordsOrExtensions, includes ) {
+var declarationRegexp = /^([a-z_0-9]+)\s([a-z_0-9]+)\s*\((.*?)\)/i,
+	propertiesRegexp = /[a-z_0-9]+/ig;
 
 
-	this.isMethod = typeof includesOrType !== "string";
-	this.useKeywords = true;
+function FunctionNode( src, includes, extensions, keywords, type ) {
 
 
-	TempNode.call( this, this.isMethod ? null : includesOrType );
+	this.isMethod = type === undefined;
 
 
-	if ( this.isMethod ) {
-		
-		this.eval( src, includesOrType, extensionsOrKeywords, keywordsOrExtensions );
-		
-	} else {
-		
-		this.eval( src, includes, keywordsOrExtensions, extensionsOrKeywords );
-
-	}
+	TempNode.call( this, type );
 
 
-};
+	this.eval( src, includes, extensions, keywords );
 
 
-FunctionNode.rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s*\((.*?)\)/i;
-FunctionNode.rProperties = /[a-z_0-9]+/ig;
+}
 
 
 FunctionNode.prototype = Object.create( TempNode.prototype );
 FunctionNode.prototype = Object.create( TempNode.prototype );
 FunctionNode.prototype.constructor = FunctionNode;
 FunctionNode.prototype.constructor = FunctionNode;
 FunctionNode.prototype.nodeType = "Function";
 FunctionNode.prototype.nodeType = "Function";
 
 
+FunctionNode.prototype.useKeywords = true;
+
 FunctionNode.prototype.isShared = function ( builder, output ) {
 FunctionNode.prototype.isShared = function ( builder, output ) {
 
 
 	return ! this.isMethod;
 	return ! this.isMethod;
@@ -50,9 +43,12 @@ FunctionNode.prototype.getInputByName = function ( name ) {
 
 
 	while ( i -- ) {
 	while ( i -- ) {
 
 
-		if ( this.inputs[ i ].name === name )
+		if ( this.inputs[ i ].name === name ) {
+
 			return this.inputs[ i ];
 			return this.inputs[ i ];
 
 
+		}
+
 	}
 	}
 
 
 };
 };
@@ -63,9 +59,12 @@ FunctionNode.prototype.getIncludeByName = function ( name ) {
 
 
 	while ( i -- ) {
 	while ( i -- ) {
 
 
-		if ( this.includes[ i ].name === name )
+		if ( this.includes[ i ].name === name ) {
+
 			return this.includes[ i ];
 			return this.includes[ i ];
 
 
+		}
+
 	}
 	}
 
 
 };
 };
@@ -86,9 +85,9 @@ FunctionNode.prototype.generate = function ( builder, output ) {
 
 
 	}
 	}
 
 
-	while ( match = FunctionNode.rProperties.exec( this.src ) ) {
+	while ( match = propertiesRegexp.exec( this.src ) ) {
 
 
-		var prop = match[ 0 ], 
+		var prop = match[ 0 ],
 			isGlobal = this.isMethod ? ! this.getInputByName( prop ) : true,
 			isGlobal = this.isMethod ? ! this.getInputByName( prop ) : true,
 			reference = prop;
 			reference = prop;
 
 
@@ -156,7 +155,7 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
 
 
 	if ( this.isMethod ) {
 	if ( this.isMethod ) {
 
 
-		var match = this.src.match( FunctionNode.rDeclaration );
+		var match = this.src.match( declarationRegexp );
 
 
 		this.inputs = [];
 		this.inputs = [];
 
 
@@ -165,7 +164,7 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
 			this.type = match[ 1 ];
 			this.type = match[ 1 ];
 			this.name = match[ 2 ];
 			this.name = match[ 2 ];
 
 
-			var inputs = match[ 3 ].match( FunctionNode.rProperties );
+			var inputs = match[ 3 ].match( propertiesRegexp );
 
 
 			if ( inputs ) {
 			if ( inputs ) {
 
 
@@ -211,16 +210,16 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
 };
 };
 
 
 FunctionNode.prototype.copy = function ( source ) {
 FunctionNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.isMethod = source.isMethod;
 	this.isMethod = source.isMethod;
 	this.useKeywords = source.useKeywords;
 	this.useKeywords = source.useKeywords;
-	
+
 	this.eval( source.src, source.includes, source.extensions, source.keywords );
 	this.eval( source.src, source.includes, source.extensions, source.keywords );
 
 
 	if ( source.type !== undefined ) this.type = source.type;
 	if ( source.type !== undefined ) this.type = source.type;
-	
+
 };
 };
 
 
 FunctionNode.prototype.toJSON = function ( meta ) {
 FunctionNode.prototype.toJSON = function ( meta ) {

+ 5 - 5
examples/js/nodes/core/InputNode.js

@@ -13,7 +13,7 @@ function InputNode( type, params ) {
 
 
 	this.readonly = false;
 	this.readonly = false;
 
 
-};
+}
 
 
 InputNode.prototype = Object.create( TempNode.prototype );
 InputNode.prototype = Object.create( TempNode.prototype );
 InputNode.prototype.constructor = InputNode;
 InputNode.prototype.constructor = InputNode;
@@ -25,17 +25,17 @@ InputNode.prototype.isReadonly = function ( builder ) {
 };
 };
 
 
 InputNode.prototype.copy = function ( source ) {
 InputNode.prototype.copy = function ( source ) {
-	
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	if ( source.readonly !== undefined ) this.readonly = source.readonly;
 	if ( source.readonly !== undefined ) this.readonly = source.readonly;
-	
+
 };
 };
 
 
 InputNode.prototype.createJSONNode = function ( meta ) {
 InputNode.prototype.createJSONNode = function ( meta ) {
 
 
 	var data = TempNode.prototype.createJSONNode.call( this, meta );
 	var data = TempNode.prototype.createJSONNode.call( this, meta );
-	
+
 	if ( this.readonly === true ) data.readonly = this.readonly;
 	if ( this.readonly === true ) data.readonly = this.readonly;
 
 
 	return data;
 	return data;

+ 45 - 41
examples/js/nodes/core/GLNode.js → examples/js/nodes/core/Node.js

@@ -2,7 +2,7 @@
  * @author sunag / http://www.sunag.com.br/
  * @author sunag / http://www.sunag.com.br/
  */
  */
 
 
-function GLNode( type ) {
+function Node( type ) {
 
 
 	this.uuid = THREE.Math.generateUUID();
 	this.uuid = THREE.Math.generateUUID();
 
 
@@ -12,31 +12,31 @@ function GLNode( type ) {
 
 
 	this.userData = {};
 	this.userData = {};
 
 
-};
+}
+
+Node.prototype = {
 
 
-GLNode.prototype = {
+	constructor: Node,
 
 
-	constructor: GLNode,
-	
 	isNode: true,
 	isNode: true,
-	
+
 	parse: function ( builder, settings ) {
 	parse: function ( builder, settings ) {
 
 
 		settings = settings || {};
 		settings = settings || {};
 
 
 		builder.parsing = true;
 		builder.parsing = true;
 
 
-		this.build( builder.addCache( settings.cache, settings.requires ).addSlot( settings.slot ), 'v4' );
+		this.build( builder.addFlow( settings.slot, settings.cache, settings.context ), 'v4' );
 
 
-		builder.clearVertexNodeCode()
+		builder.clearVertexNodeCode();
 		builder.clearFragmentNodeCode();
 		builder.clearFragmentNodeCode();
 
 
-		builder.removeCache().removeSlot();
+		builder.removeFlow();
 
 
 		builder.parsing = false;
 		builder.parsing = false;
 
 
 	},
 	},
-	
+
 	parseAndBuildCode: function ( builder, output, settings ) {
 	parseAndBuildCode: function ( builder, output, settings ) {
 
 
 		settings = settings || {};
 		settings = settings || {};
@@ -44,21 +44,21 @@ GLNode.prototype = {
 		this.parse( builder, settings );
 		this.parse( builder, settings );
 
 
 		return this.buildCode( builder, output, settings );
 		return this.buildCode( builder, output, settings );
-	
+
 	},
 	},
-	
+
 	buildCode: function ( builder, output, settings ) {
 	buildCode: function ( builder, output, settings ) {
 
 
 		settings = settings || {};
 		settings = settings || {};
 
 
-		var data = { result: this.build( builder.addCache( settings.cache, settings.context ).addSlot( settings.slot ), output ) };
+		var data = { result: this.build( builder.addFlow( settings.slot, settings.cache, settings.context ), output ) };
 
 
 		data.code = builder.clearNodeCode();
 		data.code = builder.clearNodeCode();
 
 
-		builder.removeCache().removeSlot();
+		builder.removeFlow();
 
 
 		return data;
 		return data;
-	
+
 	},
 	},
 
 
 	build: function ( builder, output, uuid ) {
 	build: function ( builder, output, uuid ) {
@@ -67,7 +67,11 @@ GLNode.prototype = {
 
 
 		var data = builder.getNodeData( uuid || this );
 		var data = builder.getNodeData( uuid || this );
 
 
-		if ( builder.parsing ) this.appendDepsNode( builder, data, output );
+		if ( builder.parsing ) {
+
+			this.appendDepsNode( builder, data, output );
+
+		}
 
 
 		if ( builder.nodes.indexOf( this ) === - 1 ) {
 		if ( builder.nodes.indexOf( this ) === - 1 ) {
 
 
@@ -82,9 +86,9 @@ GLNode.prototype = {
 		}
 		}
 
 
 		return this.generate( builder, output, uuid );
 		return this.generate( builder, output, uuid );
-	
+
 	},
 	},
-	
+
 	appendDepsNode: function ( builder, data, output ) {
 	appendDepsNode: function ( builder, data, output ) {
 
 
 		data.deps = ( data.deps || 0 ) + 1;
 		data.deps = ( data.deps || 0 ) + 1;
@@ -97,29 +101,29 @@ GLNode.prototype = {
 			data.output = output;
 			data.output = output;
 
 
 		}
 		}
-	
+
 	},
 	},
-	
-	setName: function( name ) {
-		
+
+	setName: function ( name ) {
+
 		this.name = name;
 		this.name = name;
-		
+
 		return this;
 		return this;
-		
+
 	},
 	},
-	
-	getName: function( builder ) {
-		
+
+	getName: function ( builder ) {
+
 		return this.name;
 		return this.name;
-		
+
 	},
 	},
-	
+
 	getType: function ( builder, output ) {
 	getType: function ( builder, output ) {
 
 
 		return output === 'sampler2D' || output === 'samplerCube' ? output : this.type;
 		return output === 'sampler2D' || output === 'samplerCube' ? output : this.type;
-	
+
 	},
 	},
-	
+
 	getJSONNode: function ( meta ) {
 	getJSONNode: function ( meta ) {
 
 
 		var isRootObject = ( meta === undefined || typeof meta === 'string' );
 		var isRootObject = ( meta === undefined || typeof meta === 'string' );
@@ -129,17 +133,17 @@ GLNode.prototype = {
 			return meta.nodes[ this.uuid ];
 			return meta.nodes[ this.uuid ];
 
 
 		}
 		}
-	
+
 	},
 	},
-	
+
 	copy: function ( source ) {
 	copy: function ( source ) {
 
 
 		if ( source.name !== undefined ) this.name = source.name;
 		if ( source.name !== undefined ) this.name = source.name;
-	
+
 		if ( source.userData !== undefined ) this.userData = JSON.parse( JSON.stringify( source.userData ) );
 		if ( source.userData !== undefined ) this.userData = JSON.parse( JSON.stringify( source.userData ) );
-	
+
 	},
 	},
-	
+
 	createJSONNode: function ( meta ) {
 	createJSONNode: function ( meta ) {
 
 
 		var isRootObject = ( meta === undefined || typeof meta === 'string' );
 		var isRootObject = ( meta === undefined || typeof meta === 'string' );
@@ -162,15 +166,15 @@ GLNode.prototype = {
 		}
 		}
 
 
 		return data;
 		return data;
-	
+
 	},
 	},
-	
+
 	toJSON: function ( meta ) {
 	toJSON: function ( meta ) {
 
 
 		return this.getJSONNode( meta ) || this.createJSONNode( meta );
 		return this.getJSONNode( meta ) || this.createJSONNode( meta );
-	
+
 	}
 	}
-	
+
 };
 };
 
 
-export { GLNode };
+export { Node };

+ 260 - 309
examples/js/nodes/core/NodeBuilder.js

@@ -37,16 +37,17 @@ var elements = NodeUtils.elements,
 		m3: 'mat3',
 		m3: 'mat3',
 		m4: 'mat4'
 		m4: 'mat4'
 	};
 	};
- 
+
 function NodeBuilder() {
 function NodeBuilder() {
 
 
-	this.caches = [];
 	this.slots = [];
 	this.slots = [];
+	this.caches = [];
+	this.contexts = [];
 
 
 	this.keywords = {};
 	this.keywords = {};
-	
+
 	this.nodeData = {};
 	this.nodeData = {};
-	
+
 	this.requires = {
 	this.requires = {
 		uv: [],
 		uv: [],
 		color: [],
 		color: [],
@@ -59,11 +60,11 @@ function NodeBuilder() {
 		functions: [],
 		functions: [],
 		structs: []
 		structs: []
 	};
 	};
-	
+
 	this.attributes = {};
 	this.attributes = {};
-	
+
 	this.prefixCode = [
 	this.prefixCode = [
-		"#ifdef GL_EXT_shader_texture_lod",
+		"#ifdef TEXTURE_LOD_EXT",
 
 
 		"	#define texCube(a, b) textureCube(a, b)",
 		"	#define texCube(a, b) textureCube(a, b)",
 		"	#define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)",
 		"	#define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)",
@@ -81,35 +82,36 @@ function NodeBuilder() {
 
 
 		"#endif",
 		"#endif",
 
 
-		"#include <packing>"
+		"#include <packing>",
+		"#include <common>"
 
 
 	].join( "\n" );
 	].join( "\n" );
-	
+
 	this.parsCode = {
 	this.parsCode = {
 		vertex: '',
 		vertex: '',
 		fragment: ''
 		fragment: ''
 	};
 	};
-	
+
 	this.code = {
 	this.code = {
 		vertex: '',
 		vertex: '',
 		fragment: ''
 		fragment: ''
 	};
 	};
-	
+
 	this.nodeCode = {
 	this.nodeCode = {
 		vertex: '',
 		vertex: '',
 		fragment: ''
 		fragment: ''
 	};
 	};
-	
+
 	this.resultCode = {
 	this.resultCode = {
 		vertex: '',
 		vertex: '',
 		fragment: ''
 		fragment: ''
 	};
 	};
-	
+
 	this.finalCode = {
 	this.finalCode = {
 		vertex: '',
 		vertex: '',
 		fragment: ''
 		fragment: ''
 	};
 	};
-	
+
 	this.inputs = {
 	this.inputs = {
 		uniforms: {
 		uniforms: {
 			list: [],
 			list: [],
@@ -122,45 +124,43 @@ function NodeBuilder() {
 			fragment: []
 			fragment: []
 		}
 		}
 	};
 	};
-	
+
 	// send to material
 	// send to material
-	
+
 	this.defines = {};
 	this.defines = {};
-	
+
 	this.uniforms = {};
 	this.uniforms = {};
-	
+
 	this.extensions = {};
 	this.extensions = {};
-	
+
 	this.updaters = [];
 	this.updaters = [];
-	
+
 	this.nodes = [];
 	this.nodes = [];
-	
+
 	// --
 	// --
-	
+
 	this.parsing = false;
 	this.parsing = false;
 	this.optimize = true;
 	this.optimize = true;
 
 
-	this.update();
-
-};
+}
 
 
 NodeBuilder.prototype = {
 NodeBuilder.prototype = {
 
 
 	constructor: NodeBuilder,
 	constructor: NodeBuilder,
 
 
-	build: function( vertex, fragment ) {
-		
+	build: function ( vertex, fragment ) {
+
 		this.buildShader( 'vertex', vertex );
 		this.buildShader( 'vertex', vertex );
 		this.buildShader( 'fragment', fragment );
 		this.buildShader( 'fragment', fragment );
-		
+
 		if ( this.requires.uv[ 0 ] ) {
 		if ( this.requires.uv[ 0 ] ) {
 
 
 			this.addVaryCode( 'varying vec2 vUv;' );
 			this.addVaryCode( 'varying vec2 vUv;' );
-		
+
 			this.addVertexFinalCode( 'vUv = uv;' );
 			this.addVertexFinalCode( 'vUv = uv;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.uv[ 1 ] ) {
 		if ( this.requires.uv[ 1 ] ) {
 
 
 			this.addVaryCode( 'varying vec2 vUv2;' );
 			this.addVaryCode( 'varying vec2 vUv2;' );
@@ -169,7 +169,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vUv2 = uv2;' );
 			this.addVertexFinalCode( 'vUv2 = uv2;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.color[ 0 ] ) {
 		if ( this.requires.color[ 0 ] ) {
 
 
 			this.addVaryCode( 'varying vec4 vColor;' );
 			this.addVaryCode( 'varying vec4 vColor;' );
@@ -178,7 +178,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vColor = color;' );
 			this.addVertexFinalCode( 'vColor = color;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.color[ 1 ] ) {
 		if ( this.requires.color[ 1 ] ) {
 
 
 			this.addVaryCode( 'varying vec4 vColor2;' );
 			this.addVaryCode( 'varying vec4 vColor2;' );
@@ -187,7 +187,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vColor2 = color2;' );
 			this.addVertexFinalCode( 'vColor2 = color2;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.position ) {
 		if ( this.requires.position ) {
 
 
 			this.addVaryCode( 'varying vec3 vPosition;' );
 			this.addVaryCode( 'varying vec3 vPosition;' );
@@ -195,15 +195,15 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vPosition = transformed;' );
 			this.addVertexFinalCode( 'vPosition = transformed;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.worldPosition ) {
 		if ( this.requires.worldPosition ) {
 
 
 			this.addVaryCode( 'varying vec3 vWPosition;' );
 			this.addVaryCode( 'varying vec3 vWPosition;' );
-			
+
 			this.addVertexFinalCode( 'vWPosition = ( modelMatrix * vec4( transformed, 1.0 ) ).xyz;' );
 			this.addVertexFinalCode( 'vWPosition = ( modelMatrix * vec4( transformed, 1.0 ) ).xyz;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.normal ) {
 		if ( this.requires.normal ) {
 
 
 			this.addVaryCode( 'varying vec3 vObjectNormal;' );
 			this.addVaryCode( 'varying vec3 vObjectNormal;' );
@@ -211,7 +211,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vObjectNormal = normal;' );
 			this.addVertexFinalCode( 'vObjectNormal = normal;' );
 
 
 		}
 		}
-		
+
 		if ( this.requires.worldNormal ) {
 		if ( this.requires.worldNormal ) {
 
 
 			this.addVaryCode( 'varying vec3 vWNormal;' );
 			this.addVaryCode( 'varying vec3 vWNormal;' );
@@ -219,67 +219,98 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vWNormal = ( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz;' );
 			this.addVertexFinalCode( 'vWNormal = ( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz;' );
 
 
 		}
 		}
-		
+
 		return this;
 		return this;
-		
+
 	},
 	},
-	
-	buildShader: function( shader, node ) {
-		
-		this.resultCode[shader] = node.build( this.setShader( shader ), 'v4' );
-		
+
+	buildShader: function ( shader, node ) {
+
+		this.resultCode[ shader ] = node.build( this.setShader( shader ), 'v4' );
+
 	},
 	},
-	
-	setMaterial: function( material, renderer ) {
-		
+
+	setMaterial: function ( material, renderer ) {
+
 		this.material = material;
 		this.material = material;
 		this.renderer = renderer;
 		this.renderer = renderer;
-		
+
 		this.requires.lights = material.lights;
 		this.requires.lights = material.lights;
 		this.requires.fog = material.fog;
 		this.requires.fog = material.fog;
-		
+
+		this.mergeDefines( material.defines );
+
 		return this;
 		return this;
-		
+
 	},
 	},
-	
-	addCache: function ( name, context ) {
 
 
-		this.caches.push( {
-			name: name || '',
-			context: context || {}
-		} );
+	addFlow: function ( slot, cache, context ) {
 
 
-		return this.update();
+		return this.addSlot( slot ).addCache( cache ).addContext( context );
+
+	},
+
+	removeFlow: function () {
+
+		return this.removeSlot().removeCache().removeContext();
+
+	},
+
+	addCache: function ( name ) {
+
+		this.cache = name || '';
+		this.caches.push( this.cache );
+
+		return this;
 
 
 	},
 	},
 
 
 	removeCache: function () {
 	removeCache: function () {
 
 
 		this.caches.pop();
 		this.caches.pop();
+		this.cache = this.caches[ this.caches.length - 1 ] || '';
+
+		return this;
+
+	},
+
+	addContext: function ( context ) {
+
+		this.context = Object.assign( {}, this.context, context );
+		this.contexts.push( this.context );
+
+		return this;
+
+	},
 
 
-		return this.update();
+	removeContext: function () {
+
+		this.contexts.pop();
+		this.context = this.contexts[ this.contexts.length - 1 ] || {};
+
+		return this;
 
 
 	},
 	},
 
 
 	addSlot: function ( name ) {
 	addSlot: function ( name ) {
 
 
-		this.slots.push( {
-			name: name || ''
-		} );
+		this.slot = name || '';
+		this.slots.push( this.slot );
 
 
-		return this.update();
+		return this;
 
 
 	},
 	},
 
 
 	removeSlot: function () {
 	removeSlot: function () {
 
 
 		this.slots.pop();
 		this.slots.pop();
+		this.slot = this.slots[ this.slots.length - 1 ] || '';
 
 
-		return this.update();
+		return this;
 
 
 	},
 	},
 
 
-	
+
 	addVertexCode: function ( code ) {
 	addVertexCode: function ( code ) {
 
 
 		this.addCode( code, 'vertex' );
 		this.addCode( code, 'vertex' );
@@ -291,14 +322,14 @@ NodeBuilder.prototype = {
 		this.addCode( code, 'fragment' );
 		this.addCode( code, 'fragment' );
 
 
 	},
 	},
-	
+
 	addCode: function ( code, shader ) {
 	addCode: function ( code, shader ) {
 
 
-		this.code[shader || this.shader] += code + '\n';
+		this.code[ shader || this.shader ] += code + '\n';
 
 
 	},
 	},
-	
-	
+
+
 	addVertexNodeCode: function ( code ) {
 	addVertexNodeCode: function ( code ) {
 
 
 		this.addNodeCode( code, 'vertex' );
 		this.addNodeCode( code, 'vertex' );
@@ -310,37 +341,37 @@ NodeBuilder.prototype = {
 		this.addNodeCode( code, 'fragment' );
 		this.addNodeCode( code, 'fragment' );
 
 
 	},
 	},
-	
+
 	addNodeCode: function ( code, shader ) {
 	addNodeCode: function ( code, shader ) {
 
 
-		this.nodeCode[shader || this.shader] += code + '\n';
+		this.nodeCode[ shader || this.shader ] += code + '\n';
 
 
 	},
 	},
-	
+
 	clearNodeCode: function ( shader ) {
 	clearNodeCode: function ( shader ) {
 
 
 		shader = shader || this.shader;
 		shader = shader || this.shader;
-	
-		var code = this.nodeCode[shader];
-		
-		this.nodeCode[shader] = '';
+
+		var code = this.nodeCode[ shader ];
+
+		this.nodeCode[ shader ] = '';
 
 
 		return code;
 		return code;
-		
+
 	},
 	},
-	
-	clearVertexNodeCode: function (  ) {
+
+	clearVertexNodeCode: function ( ) {
 
 
 		return this.clearNodeCode( 'vertex' );
 		return this.clearNodeCode( 'vertex' );
 
 
 	},
 	},
-	
-	clearFragmentNodeCode: function (  ) {
+
+	clearFragmentNodeCode: function ( ) {
 
 
 		return this.clearNodeCode( 'fragment' );
 		return this.clearNodeCode( 'fragment' );
 
 
 	},
 	},
-	
+
 	addVertexFinalCode: function ( code ) {
 	addVertexFinalCode: function ( code ) {
 
 
 		this.addFinalCode( code, 'vertex' );
 		this.addFinalCode( code, 'vertex' );
@@ -352,79 +383,50 @@ NodeBuilder.prototype = {
 		this.addFinalCode( code, 'fragment' );
 		this.addFinalCode( code, 'fragment' );
 
 
 	},
 	},
-	
+
 	addFinalCode: function ( code, shader ) {
 	addFinalCode: function ( code, shader ) {
 
 
-		this.finalCode[shader || this.shader] += code + '\n';
+		this.finalCode[ shader || this.shader ] += code + '\n';
 
 
 	},
 	},
-	
-	
+
+
 	addVertexParsCode: function ( code ) {
 	addVertexParsCode: function ( code ) {
 
 
 		this.addParsCode( code, 'vertex' );
 		this.addParsCode( code, 'vertex' );
 
 
 	},
 	},
-	
+
 	addFragmentParsCode: function ( code ) {
 	addFragmentParsCode: function ( code ) {
 
 
 		this.addParsCode( code, 'fragment' );
 		this.addParsCode( code, 'fragment' );
 
 
 	},
 	},
-	
+
 	addParsCode: function ( code, shader ) {
 	addParsCode: function ( code, shader ) {
 
 
-		this.parsCode[shader || this.shader] += code + '\n';
+		this.parsCode[ shader || this.shader ] += code + '\n';
 
 
 	},
 	},
-	
-	
+
+
 	addVaryCode: function ( code ) {
 	addVaryCode: function ( code ) {
 
 
 		this.addVertexParsCode( code );
 		this.addVertexParsCode( code );
 		this.addFragmentParsCode( code );
 		this.addFragmentParsCode( code );
 
 
 	},
 	},
-	
-	
-	isCache: function ( name ) {
 
 
-		var i = this.caches.length;
 
 
-		while ( i -- ) {
-
-			if ( this.caches[ i ].name === name ) return true;
-
-		}
+	isCache: function ( name ) {
 
 
-		return false;
+		return this.caches.indexOf( name ) !== - 1;
 
 
 	},
 	},
 
 
 	isSlot: function ( name ) {
 	isSlot: function ( name ) {
 
 
-		var i = this.slots.length;
-
-		while ( i -- ) {
-
-			if ( this.slots[ i ].name === name ) return true;
-
-		}
-
-		return false;
-
-	},
-
-	update: function () {
-
-		var cache = this.caches[ this.caches.length - 1 ];
-		var slot = this.slots[ this.slots.length - 1 ];
-
-		this.slot = slot ? slot.name : '';
-		this.cache = cache ? cache.name : '';
-		this.context = cache ? cache.context : {};
-
-		return this;
+		return this.slots.indexOf( name ) !== - 1;
 
 
 	},
 	},
 
 
@@ -433,7 +435,7 @@ NodeBuilder.prototype = {
 		this.defines[ name ] = value === undefined ? 1 : value;
 		this.defines[ name ] = value === undefined ? 1 : value;
 
 
 	},
 	},
-	
+
 	isDefined: function ( name ) {
 	isDefined: function ( name ) {
 
 
 		return this.defines[ name ] !== undefined;
 		return this.defines[ name ] !== undefined;
@@ -443,8 +445,8 @@ NodeBuilder.prototype = {
 	getVar: function ( uuid, type, ns, shader ) {
 	getVar: function ( uuid, type, ns, shader ) {
 
 
 		shader = shader || 'varying';
 		shader = shader || 'varying';
-	
-		var vars = this.getVars(shader),
+
+		var vars = this.getVars( shader ),
 			data = vars[ uuid ];
 			data = vars[ uuid ];
 
 
 		if ( ! data ) {
 		if ( ! data ) {
@@ -462,13 +464,13 @@ NodeBuilder.prototype = {
 		return data;
 		return data;
 
 
 	},
 	},
-	
+
 	getTempVar: function ( uuid, type, ns ) {
 	getTempVar: function ( uuid, type, ns ) {
 
 
 		return this.getVar( uuid, type, ns, this.shader );
 		return this.getVar( uuid, type, ns, this.shader );
 
 
 	},
 	},
-	
+
 	getAttribute: function ( name, type ) {
 	getAttribute: function ( name, type ) {
 
 
 		if ( ! this.attributes[ name ] ) {
 		if ( ! this.attributes[ name ] ) {
@@ -485,45 +487,45 @@ NodeBuilder.prototype = {
 		return this.attributes[ name ];
 		return this.attributes[ name ];
 
 
 	},
 	},
-	
-	getCode: function( shader ) {
-		
+
+	getCode: function ( shader ) {
+
 		return [
 		return [
 			this.prefixCode,
 			this.prefixCode,
 			this.parsCode[ shader ],
 			this.parsCode[ shader ],
-			this.getVarListCode( this.getVars('varying'), 'varying' ),
-			this.getVarListCode( this.inputs.uniforms[shader], 'uniform' ),
+			this.getVarListCode( this.getVars( 'varying' ), 'varying' ),
+			this.getVarListCode( this.inputs.uniforms[ shader ], 'uniform' ),
 			this.getIncludesCode( 'consts', shader ),
 			this.getIncludesCode( 'consts', shader ),
 			this.getIncludesCode( 'structs', shader ),
 			this.getIncludesCode( 'structs', shader ),
 			this.getIncludesCode( 'functions', shader ),
 			this.getIncludesCode( 'functions', shader ),
 			'void main() {',
 			'void main() {',
-				this.getVarListCode( this.getVars(shader) ),
-				this.code[ shader ], 
-				this.resultCode[ shader ],
-				this.finalCode[ shader ],
+			this.getVarListCode( this.getVars( shader ) ),
+			this.code[ shader ],
+			this.resultCode[ shader ],
+			this.finalCode[ shader ],
 			'}'
 			'}'
 		].join( "\n" );
 		].join( "\n" );
-		
+
 	},
 	},
-	
+
 	getVarListCode: function ( vars, prefix ) {
 	getVarListCode: function ( vars, prefix ) {
 
 
 		prefix = prefix || '';
 		prefix = prefix || '';
-	
+
 		var code = '';
 		var code = '';
 
 
 		for ( var i = 0, l = vars.length; i < l; ++ i ) {
 		for ( var i = 0, l = vars.length; i < l; ++ i ) {
 
 
-			var nVar = vars[i],
+			var nVar = vars[ i ],
 				type = nVar.type,
 				type = nVar.type,
 				name = nVar.name;
 				name = nVar.name;
-			
+
 			var formatType = this.getFormatByType( type );
 			var formatType = this.getFormatByType( type );
 
 
 			if ( formatType === undefined ) {
 			if ( formatType === undefined ) {
-				
+
 				throw new Error( "Node pars " + formatType + " not found." );
 				throw new Error( "Node pars " + formatType + " not found." );
-				
+
 			}
 			}
 
 
 			code += prefix + ' ' + formatType + ' ' + name + ';\n';
 			code += prefix + ' ' + formatType + ' ' + name + ';\n';
@@ -533,21 +535,21 @@ NodeBuilder.prototype = {
 		return code;
 		return code;
 
 
 	},
 	},
-	
+
 	getVars: function ( shader ) {
 	getVars: function ( shader ) {
 
 
 		return this.inputs.vars[ shader || this.shader ];
 		return this.inputs.vars[ shader || this.shader ];
 
 
 	},
 	},
-	
+
 	getNodeData: function ( node ) {
 	getNodeData: function ( node ) {
 
 
 		var uuid = node.isNode ? node.uuid : node;
 		var uuid = node.isNode ? node.uuid : node;
-	
+
 		return this.nodeData[ uuid ] = this.nodeData[ uuid ] || {};
 		return this.nodeData[ uuid ] = this.nodeData[ uuid ] || {};
 
 
 	},
 	},
-	
+
 	createUniform: function ( shader, type, node, ns, needsUpdate ) {
 	createUniform: function ( shader, type, node, ns, needsUpdate ) {
 
 
 		var uniforms = this.inputs.uniforms,
 		var uniforms = this.inputs.uniforms,
@@ -555,40 +557,47 @@ NodeBuilder.prototype = {
 
 
 		var uniform = new NodeUniform( {
 		var uniform = new NodeUniform( {
 			type: type,
 			type: type,
-			name: ns ? ns : 'nVu' + index + '_' + THREE.Math.generateUUID().substr(0, 8),
+			name: ns ? ns : 'nVu' + index,
 			node: node,
 			node: node,
 			needsUpdate: needsUpdate
 			needsUpdate: needsUpdate
 		} );
 		} );
 
 
 		uniforms.list.push( uniform );
 		uniforms.list.push( uniform );
 
 
-		uniforms[shader].push( uniform );
-		uniforms[shader][ uniform.name ] = uniform;
-		
+		uniforms[ shader ].push( uniform );
+		uniforms[ shader ][ uniform.name ] = uniform;
+
 		this.uniforms[ uniform.name ] = uniform;
 		this.uniforms[ uniform.name ] = uniform;
-		
+
 		return uniform;
 		return uniform;
 
 
 	},
 	},
-	
+
 	createVertexUniform: function ( type, node, ns, needsUpdate ) {
 	createVertexUniform: function ( type, node, ns, needsUpdate ) {
 
 
 		return this.createUniform( 'vertex', type, node, ns, needsUpdate );
 		return this.createUniform( 'vertex', type, node, ns, needsUpdate );
 
 
 	},
 	},
-	
+
 	createFragmentUniform: function ( type, node, ns, needsUpdate ) {
 	createFragmentUniform: function ( type, node, ns, needsUpdate ) {
 
 
 		return this.createUniform( 'fragment', type, node, ns, needsUpdate );
 		return this.createUniform( 'fragment', type, node, ns, needsUpdate );
 
 
 	},
 	},
-	
+
 	include: function ( node, parent, source ) {
 	include: function ( node, parent, source ) {
 
 
 		var includesStruct;
 		var includesStruct;
 
 
 		node = typeof node === 'string' ? NodeLib.get( node ) : node;
 		node = typeof node === 'string' ? NodeLib.get( node ) : node;
 
 
+		if ( this.context.include === false ) {
+
+			return node.name;
+
+		}
+
+
 		if ( node instanceof FunctionNode ) {
 		if ( node instanceof FunctionNode ) {
 
 
 			includesStruct = this.includes.functions;
 			includesStruct = this.includes.functions;
@@ -596,17 +605,17 @@ NodeBuilder.prototype = {
 		} else if ( node instanceof ConstNode ) {
 		} else if ( node instanceof ConstNode ) {
 
 
 			includesStruct = this.includes.consts;
 			includesStruct = this.includes.consts;
-			
+
 		} else if ( node instanceof StructNode ) {
 		} else if ( node instanceof StructNode ) {
 
 
 			includesStruct = this.includes.structs;
 			includesStruct = this.includes.structs;
 
 
 		}
 		}
-		
+
 		var includes = includesStruct[ this.shader ] = includesStruct[ this.shader ] || [];
 		var includes = includesStruct[ this.shader ] = includesStruct[ this.shader ] || [];
 
 
-		if (node) {
-		
+		if ( node ) {
+
 			var included = includes[ node.name ];
 			var included = includes[ node.name ];
 
 
 			if ( ! included ) {
 			if ( ! included ) {
@@ -645,13 +654,13 @@ NodeBuilder.prototype = {
 				included.src = source;
 				included.src = source;
 
 
 			}
 			}
-			
+
 			return node.name;
 			return node.name;
-			
+
 		} else {
 		} else {
-			
-			throw new Error("Include not found.");
-			
+
+			throw new Error( "Include not found." );
+
 		}
 		}
 
 
 	},
 	},
@@ -661,7 +670,7 @@ NodeBuilder.prototype = {
 		return color.replace( 'r', 'x' ).replace( 'g', 'y' ).replace( 'b', 'z' ).replace( 'a', 'w' );
 		return color.replace( 'r', 'x' ).replace( 'g', 'y' ).replace( 'b', 'z' ).replace( 'a', 'w' );
 
 
 	},
 	},
-	
+
 	colorToVector: function ( color ) {
 	colorToVector: function ( color ) {
 
 
 		return color.replace( /c/g, 'v3' );
 		return color.replace( /c/g, 'v3' );
@@ -670,10 +679,10 @@ NodeBuilder.prototype = {
 
 
 	getIncludes: function ( type, shader ) {
 	getIncludes: function ( type, shader ) {
 
 
-		return this.includes[type][shader || this.shader];
+		return this.includes[ type ][ shader || this.shader ];
 
 
 	},
 	},
-	
+
 	getIncludesCode: function () {
 	getIncludesCode: function () {
 
 
 		function sortByPosition( a, b ) {
 		function sortByPosition( a, b ) {
@@ -685,10 +694,10 @@ NodeBuilder.prototype = {
 		return function getIncludesCode( type, shader ) {
 		return function getIncludesCode( type, shader ) {
 
 
 			var includes = this.getIncludes( type, shader );
 			var includes = this.getIncludes( type, shader );
-	
+
 			if ( ! includes ) return '';
 			if ( ! includes ) return '';
 
 
-			var code = '', 
+			var code = '',
 				includes = includes.sort( sortByPosition );
 				includes = includes.sort( sortByPosition );
 
 
 			for ( var i = 0; i < includes.length; i ++ ) {
 			for ( var i = 0; i < includes.length; i ++ ) {
@@ -702,7 +711,7 @@ NodeBuilder.prototype = {
 		};
 		};
 
 
 	}(),
 	}(),
-	
+
 	getConstructorFromLength: function ( len ) {
 	getConstructorFromLength: function ( len ) {
 
 
 		return constructors[ len - 1 ];
 		return constructors[ len - 1 ];
@@ -718,7 +727,7 @@ NodeBuilder.prototype = {
 	getTypeLength: function ( type ) {
 	getTypeLength: function ( type ) {
 
 
 		if ( type === 'f' ) return 1;
 		if ( type === 'f' ) return 1;
-	
+
 		return parseInt( this.colorToVector( type ).substr( 1 ) );
 		return parseInt( this.colorToVector( type ).substr( 1 ) );
 
 
 	},
 	},
@@ -730,109 +739,109 @@ NodeBuilder.prototype = {
 		return 'v' + len;
 		return 'v' + len;
 
 
 	},
 	},
-	
-	findNode: function() {
-		
-		for(var i = 0; i < arguments.length; i++) {
-			
-			var nodeCandidate = arguments[i];
-			
-			if (nodeCandidate !== undefined && nodeCandidate.isNode) {
-				
+
+	findNode: function () {
+
+		for ( var i = 0; i < arguments.length; i ++ ) {
+
+			var nodeCandidate = arguments[ i ];
+
+			if ( nodeCandidate !== undefined && nodeCandidate.isNode ) {
+
 				return nodeCandidate;
 				return nodeCandidate;
-				
+
 			}
 			}
-			
+
 		}
 		}
-		
-	},
-	
-	resolve: function() {
-		
-		for(var i = 0; i < arguments.length; i++) {
-			
-			var nodeCandidate = arguments[i];
-			
-			if (nodeCandidate !== undefined) {
-				
-				if (nodeCandidate.isNode) {
-				
+
+	},
+
+	resolve: function () {
+
+		for ( var i = 0; i < arguments.length; i ++ ) {
+
+			var nodeCandidate = arguments[ i ];
+
+			if ( nodeCandidate !== undefined ) {
+
+				if ( nodeCandidate.isNode ) {
+
 					return nodeCandidate;
 					return nodeCandidate;
-					
-				} else if (nodeCandidate.isTexture) {
-					
-					switch( nodeCandidate.mapping ) {
-					
+
+				} else if ( nodeCandidate.isTexture ) {
+
+					switch ( nodeCandidate.mapping ) {
+
 						case THREE.CubeReflectionMapping:
 						case THREE.CubeReflectionMapping:
 						case THREE.CubeRefractionMapping:
 						case THREE.CubeRefractionMapping:
 
 
 							return new CubeTextureNode( nodeCandidate );
 							return new CubeTextureNode( nodeCandidate );
 
 
 							break;
 							break;
-						
+
 						case THREE.CubeUVReflectionMapping:
 						case THREE.CubeUVReflectionMapping:
 						case THREE.CubeUVRefractionMapping:
 						case THREE.CubeUVRefractionMapping:
 
 
 							return new TextureCubeNode( new TextureNode( nodeCandidate ) );
 							return new TextureCubeNode( new TextureNode( nodeCandidate ) );
 
 
 							break;
 							break;
-							
+
 						default:
 						default:
-						
+
 							return new TextureNode( nodeCandidate );
 							return new TextureNode( nodeCandidate );
-						
+
 					}
 					}
-					
-				} else if (nodeCandidate.isVector2) {
-					
+
+				} else if ( nodeCandidate.isVector2 ) {
+
 					return new Vector2Node( nodeCandidate );
 					return new Vector2Node( nodeCandidate );
-					
-				} else if (nodeCandidate.isVector3) {
-					
+
+				} else if ( nodeCandidate.isVector3 ) {
+
 					return new Vector3Node( nodeCandidate );
 					return new Vector3Node( nodeCandidate );
-					
-				} else if (nodeCandidate.isVector4) {
-					
+
+				} else if ( nodeCandidate.isVector4 ) {
+
 					return new Vector4Node( nodeCandidate );
 					return new Vector4Node( nodeCandidate );
-					
+
 				}
 				}
-				
+
 			}
 			}
-			
+
 		}
 		}
-		
+
 	},
 	},
 
 
 	format: function ( code, from, to ) {
 	format: function ( code, from, to ) {
 
 
-		var typeToType = this.colorToVector( to + ' = ' + from );
+		var typeToType = this.colorToVector( to + ' <- ' + from );
 
 
 		switch ( typeToType ) {
 		switch ( typeToType ) {
 
 
-			case 'f = v2': return code + '.x';
-			case 'f = v3': return code + '.x';
-			case 'f = v4': return code + '.x';
-			case 'f = i': return 'float( ' + code + ' )';
+			case 'f <- v2' : return code + '.x';
+			case 'f <- v3' : return code + '.x';
+			case 'f <- v4' : return code + '.x';
+			case 'f <- i' : return 'float( ' + code + ' )';
 
 
-			case 'v2 = f': return 'vec2( ' + code + ' )';
-			case 'v2 = v3': return code + '.xy';
-			case 'v2 = v4': return code + '.xy';
-			case 'v2 = i': return 'vec2( float( ' + code + ' ) )';
+			case 'v2 <- f' : return 'vec2( ' + code + ' )';
+			case 'v2 <- v3': return code + '.xy';
+			case 'v2 <- v4': return code + '.xy';
+			case 'v2 <- i' : return 'vec2( float( ' + code + ' ) )';
 
 
-			case 'v3 = f': return 'vec3( ' + code + ' )';
-			case 'v3 = v2': return 'vec3( ' + code + ', 0.0 )';
-			case 'v3 = v4': return code + '.xyz';
-			case 'v3 = i': return 'vec2( float( ' + code + ' ) )';
+			case 'v3 <- f' : return 'vec3( ' + code + ' )';
+			case 'v3 <- v2': return 'vec3( ' + code + ', 0.0 )';
+			case 'v3 <- v4': return code + '.xyz';
+			case 'v3 <- i' : return 'vec2( float( ' + code + ' ) )';
 
 
-			case 'v4 = f': return 'vec4( ' + code + ' )';
-			case 'v4 = v2': return 'vec4( ' + code + ', 0.0, 1.0 )';
-			case 'v4 = v3': return 'vec4( ' + code + ', 1.0 )';
-			case 'v4 = i': return 'vec4( float( ' + code + ' ) )';
+			case 'v4 <- f' : return 'vec4( ' + code + ' )';
+			case 'v4 <- v2': return 'vec4( ' + code + ', 0.0, 1.0 )';
+			case 'v4 <- v3': return 'vec4( ' + code + ', 1.0 )';
+			case 'v4 <- i' : return 'vec4( float( ' + code + ' ) )';
 
 
-			case 'i = f': return 'int( ' + code + ' )';
-			case 'i = v2': return 'int( ' + code + '.x )';
-			case 'i = v3': return 'int( ' + code + '.x )';
-			case 'i = v4': return 'int( ' + code + '.x )';
+			case 'i <- f' : return 'int( ' + code + ' )';
+			case 'i <- v2' : return 'int( ' + code + '.x )';
+			case 'i <- v3' : return 'int( ' + code + '.x )';
+			case 'i <- v4' : return 'int( ' + code + '.x )';
 
 
 		}
 		}
 
 
@@ -845,7 +854,7 @@ NodeBuilder.prototype = {
 		return convertFormatToType[ format ] || format;
 		return convertFormatToType[ format ] || format;
 
 
 	},
 	},
-	
+
 	getFormatByType: function ( type ) {
 	getFormatByType: function ( type ) {
 
 
 		return convertTypeToFormat[ type ] || type;
 		return convertTypeToFormat[ type ] || type;
@@ -887,93 +896,35 @@ NodeBuilder.prototype = {
 		return this;
 		return this;
 
 
 	},
 	},
-	
-	mergeUniform: function ( uniforms ) {
-
-		for ( var name in uniforms ) {
-
-			this.uniforms[ name ] = uniforms[ name ];
-
-		}
-
-	},
-
-	getTexelDecodingFunctionFromTexture: function( code, texture ) {
-
-		var gammaOverrideLinear = this.getTextureEncodingFromMap( texture, this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false ) )
-
-		return this.getTexelDecodingFunction( code, gammaOverrideLinear );
-
-	},
-
-	getTexelDecodingFunction: function( value, encoding ) {
-
-		var components = this.getEncodingComponents( encoding );
 
 
-		return components[ 0 ] + 'ToLinear' + components[ 1 ].replace( 'value', value );
+	mergeDefines: function ( defines ) {
 
 
-	},
+		for ( var name in defines ) {
 
 
-	getTexelEncodingFunction: function( value, encoding ) {
+			this.defines[ name ] = defines[ name ];
 
 
-		var components = this.getEncodingComponents( encoding );
+		}
 
 
-		return 'LinearTo' + components[ 0 ] + components[ 1 ].replace( 'value', value );
+		return this.defines;
 
 
 	},
 	},
 
 
-	getEncodingComponents: function( encoding ) {
+	mergeUniform: function ( uniforms ) {
 
 
-		switch ( encoding ) {
+		for ( var name in uniforms ) {
 
 
-			case THREE.LinearEncoding:
-				return [ 'Linear', '( value )' ];
-			case THREE.sRGBEncoding:
-				return [ 'sRGB', '( value )' ];
-			case THREE.RGBEEncoding:
-				return [ 'RGBE', '( value )' ];
-			case THREE.RGBM7Encoding:
-				return [ 'RGBM', '( value, 7.0 )' ];
-			case THREE.RGBM16Encoding:
-				return [ 'RGBM', '( value, 16.0 )' ];
-			case THREE.RGBDEncoding:
-				return [ 'RGBD', '( value, 256.0 )' ];
-			case THREE.GammaEncoding:
-				return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
-			default:
-				throw new Error( 'unsupported encoding: ' + encoding );
+			this.uniforms[ name ] = uniforms[ name ];
 
 
 		}
 		}
 
 
-	},
-
-	getEncodingComponents: function( encoding ) {
-
-		switch ( encoding ) {
-
-			case THREE.LinearEncoding:
-				return [ 'Linear', '( value )' ];
-			case THREE.sRGBEncoding:
-				return [ 'sRGB', '( value )' ];
-			case THREE.RGBEEncoding:
-				return [ 'RGBE', '( value )' ];
-			case THREE.RGBM7Encoding:
-				return [ 'RGBM', '( value, 7.0 )' ];
-			case THREE.RGBM16Encoding:
-				return [ 'RGBM', '( value, 16.0 )' ];
-			case THREE.RGBDEncoding:
-				return [ 'RGBD', '( value, 256.0 )' ];
-			case THREE.GammaEncoding:
-				return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];
-			default:
-				throw new Error( 'unsupported encoding: ' + encoding );
-
-		}
+		return this.uniforms;
 
 
 	},
 	},
-	
+
 	getTextureEncodingFromMap: function ( map, gammaOverrideLinear ) {
 	getTextureEncodingFromMap: function ( map, gammaOverrideLinear ) {
 
 
+		gammaOverrideLinear = gammaOverrideLinear !== undefined ? gammaOverrideLinear : this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false );
+
 		var encoding;
 		var encoding;
 
 
 		if ( ! map ) {
 		if ( ! map ) {

+ 23 - 7
examples/js/nodes/core/NodeFrame.js

@@ -6,9 +6,9 @@ function NodeFrame( time ) {
 
 
 	this.time = time !== undefined ? time : 0;
 	this.time = time !== undefined ? time : 0;
 
 
-	this.frameId = 0;
+	this.id = 0;
 
 
-};
+}
 
 
 NodeFrame.prototype = {
 NodeFrame.prototype = {
 
 
@@ -16,7 +16,7 @@ NodeFrame.prototype = {
 
 
 	update: function ( delta ) {
 	update: function ( delta ) {
 
 
-		++this.frameId;
+		++ this.id;
 
 
 		this.time += delta;
 		this.time += delta;
 		this.delta = delta;
 		this.delta = delta;
@@ -24,19 +24,35 @@ NodeFrame.prototype = {
 		return this;
 		return this;
 
 
 	},
 	},
-	
+
+	setRenderer: function ( renderer ) {
+
+		this.renderer = renderer;
+
+		return this;
+
+	},
+
+	setRenderTexture: function ( renderTexture ) {
+
+		this.renderTexture = renderTexture;
+
+		return this;
+
+	},
+
 	updateNode: function ( node ) {
 	updateNode: function ( node ) {
 
 
-		if ( node.frameId === this.frameId ) return this;
+		if ( node.frameId === this.id ) return this;
 
 
 		node.updateFrame( this );
 		node.updateFrame( this );
 
 
-		node.frameId = this.frameId;
+		node.frameId = this.id;
 
 
 		return this;
 		return this;
 
 
 	}
 	}
-	
+
 };
 };
 
 
 export { NodeFrame };
 export { NodeFrame };

+ 6 - 6
examples/js/nodes/core/NodeUniform.js

@@ -11,26 +11,26 @@ function NodeUniform( params ) {
 	this.node = params.node;
 	this.node = params.node;
 	this.needsUpdate = params.needsUpdate;
 	this.needsUpdate = params.needsUpdate;
 
 
-};
+}
 
 
 Object.defineProperties( NodeUniform.prototype, {
 Object.defineProperties( NodeUniform.prototype, {
-	
+
 	value: {
 	value: {
-		
+
 		get: function () {
 		get: function () {
 
 
 			return this.node.value;
 			return this.node.value;
 
 
 		},
 		},
-		
+
 		set: function ( val ) {
 		set: function ( val ) {
 
 
 			this.node.value = val;
 			this.node.value = val;
 
 
 		}
 		}
-		
+
 	}
 	}
-	
+
 } );
 } );
 
 
 export { NodeUniform };
 export { NodeUniform };

+ 9 - 9
examples/js/nodes/core/NodeUtils.js

@@ -13,37 +13,37 @@ var NodeUtils = {
 			if ( subProperty ) {
 			if ( subProperty ) {
 
 
 				return {
 				return {
-					
+
 					get: function () {
 					get: function () {
 
 
 						return this[ proxy ][ property ][ subProperty ];
 						return this[ proxy ][ property ][ subProperty ];
 
 
 					},
 					},
-					
+
 					set: function ( val ) {
 					set: function ( val ) {
 
 
 						this[ proxy ][ property ][ subProperty ] = val;
 						this[ proxy ][ property ][ subProperty ] = val;
 
 
 					}
 					}
-					
+
 				};
 				};
 
 
 			} else {
 			} else {
 
 
 				return {
 				return {
-					
+
 					get: function () {
 					get: function () {
 
 
 						return this[ proxy ][ property ];
 						return this[ proxy ][ property ];
 
 
 					},
 					},
-					
+
 					set: function ( val ) {
 					set: function ( val ) {
 
 
 						this[ proxy ][ property ] = val;
 						this[ proxy ][ property ] = val;
 
 
 					}
 					}
-					
+
 				};
 				};
 
 
 			}
 			}
@@ -57,8 +57,8 @@ var NodeUtils = {
 			for ( var i = 0; i < list.length; ++ i ) {
 			for ( var i = 0; i < list.length; ++ i ) {
 
 
 				var data = list[ i ].split( "." ),
 				var data = list[ i ].split( "." ),
-					property = data[0],
-					subProperty = data[1];
+					property = data[ 0 ],
+					subProperty = data[ 1 ];
 
 
 				shortcuts[ property ] = applyShortcut( proxy, property, subProperty );
 				shortcuts[ property ] = applyShortcut( proxy, property, subProperty );
 
 
@@ -69,7 +69,7 @@ var NodeUtils = {
 		};
 		};
 
 
 	}()
 	}()
-	
+
 };
 };
 
 
 export { NodeUtils };
 export { NodeUtils };

+ 28 - 28
examples/js/nodes/core/StructNode.js

@@ -3,18 +3,17 @@
  */
  */
 
 
 import { TempNode } from './TempNode.js';
 import { TempNode } from './TempNode.js';
-import { FunctionNode } from './FunctionNode.js';
+
+var declarationRegexp = /^struct\s*([a-z_0-9]+)\s*{\s*((.|\n)*?)}/img,
+	propertiesRegexp = /\s*(\w*?)\s*(\w*?)(\=|\;)/img;
 
 
 function StructNode( src ) {
 function StructNode( src ) {
 
 
-	TempNode.call( this);
+	TempNode.call( this );
 
 
 	this.eval( src );
 	this.eval( src );
 
 
-};
-
-StructNode.rDeclaration = /^struct\s*([a-z_0-9]+)\s*{\s*((.|\n)*?)}/img;
-StructNode.rProperties = /\s*(\w*?)\s*(\w*?)(\=|\;)/img;
+}
 
 
 StructNode.prototype = Object.create( TempNode.prototype );
 StructNode.prototype = Object.create( TempNode.prototype );
 StructNode.prototype.constructor = StructNode;
 StructNode.prototype.constructor = StructNode;
@@ -32,9 +31,12 @@ StructNode.prototype.getInputByName = function ( name ) {
 
 
 	while ( i -- ) {
 	while ( i -- ) {
 
 
-		if ( this.inputs[ i ].name === name )
+		if ( this.inputs[ i ].name === name ) {
+
 			return this.inputs[ i ];
 			return this.inputs[ i ];
 
 
+		}
+
 	}
 	}
 
 
 };
 };
@@ -47,7 +49,7 @@ StructNode.prototype.generate = function ( builder, output ) {
 
 
 	} else {
 	} else {
 
 
-		return builder.format( "(" + src + ")", this.getType( builder ), output );
+		return builder.format( '( ' + src + ' )', this.getType( builder ), output );
 
 
 	}
 	}
 
 
@@ -56,34 +58,32 @@ StructNode.prototype.generate = function ( builder, output ) {
 StructNode.prototype.eval = function ( src ) {
 StructNode.prototype.eval = function ( src ) {
 
 
 	this.src = src || '';
 	this.src = src || '';
-	
+
 	this.inputs = [];
 	this.inputs = [];
-	
-	var declaration = StructNode.rDeclaration.exec( this.src );
-	
-	if (declaration) {
-		
-		var properties = declaration[2], matchType, matchName;
-		
-		while ( matchType = FunctionNode.rProperties.exec( properties ) ) {
-			
-			matchName = FunctionNode.rProperties.exec( properties )[0];
-			
+
+	var declaration = declarationRegexp.exec( this.src );
+
+	if ( declaration ) {
+
+		var properties = declaration[ 2 ], match;
+
+		while ( match = propertiesRegexp.exec( properties ) ) {
+
 			this.inputs.push( {
 			this.inputs.push( {
-				name: matchName,
-				type: matchType
+				type: match[ 1 ],
+				name: match[ 2 ]
 			} );
 			} );
-			
+
 		}
 		}
-		
-		this.name = declaration[1];
+
+		this.name = declaration[ 1 ];
 
 
 	} else {
 	} else {
-		
+
 		this.name = '';
 		this.name = '';
-		
+
 	}
 	}
-	
+
 	this.type = this.name;
 	this.type = this.name;
 
 
 };
 };

+ 17 - 17
examples/js/nodes/core/TempNode.js

@@ -3,20 +3,20 @@
  * @author sunag / http://www.sunag.com.br/
  * @author sunag / http://www.sunag.com.br/
  */
  */
 
 
-import { GLNode } from './GLNode.js';
+import { Node } from './Node.js';
 
 
 function TempNode( type, params ) {
 function TempNode( type, params ) {
 
 
-	GLNode.call( this, type );
+	Node.call( this, type );
 
 
 	params = params || {};
 	params = params || {};
 
 
 	this.shared = params.shared !== undefined ? params.shared : true;
 	this.shared = params.shared !== undefined ? params.shared : true;
 	this.unique = params.unique !== undefined ? params.unique : false;
 	this.unique = params.unique !== undefined ? params.unique : false;
 
 
-};
+}
 
 
-TempNode.prototype = Object.create( GLNode.prototype );
+TempNode.prototype = Object.create( Node.prototype );
 TempNode.prototype.constructor = TempNode;
 TempNode.prototype.constructor = TempNode;
 
 
 TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 TempNode.prototype.build = function ( builder, output, uuid, ns ) {
@@ -35,36 +35,36 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 
 
 		uuid = builder.getUuid( uuid || this.getUuid(), ! isUnique );
 		uuid = builder.getUuid( uuid || this.getUuid(), ! isUnique );
 
 
-		var data = builder.getNodeData( uuid );
+		var data = builder.getNodeData( uuid ),
+			type = data.output || this.getType( builder );
 
 
 		if ( builder.parsing ) {
 		if ( builder.parsing ) {
 
 
-			if ( data.deps || 0 > 0 ) {
+			if ( ( data.deps || 0 ) > 0 ) {
 
 
 				this.appendDepsNode( builder, data, output );
 				this.appendDepsNode( builder, data, output );
 
 
-				return this.generate( builder, type, uuid );
+				return this.generate( builder, output, uuid );
 
 
 			}
 			}
 
 
-			return GLNode.prototype.build.call( this, builder, output, uuid );
+			return Node.prototype.build.call( this, builder, output, uuid );
 
 
 		} else if ( isUnique ) {
 		} else if ( isUnique ) {
 
 
-			data.name = data.name || GLNode.prototype.build.call( this, builder, output, uuid );
+			data.name = data.name || Node.prototype.build.call( this, builder, output, uuid );
 
 
 			return data.name;
 			return data.name;
 
 
-		} else if ( ! builder.optimize || data.deps == 1 ) {
+		} else if ( ! this.isShared( builder, type ) || ( ! builder.optimize || data.deps == 1 ) ) {
 
 
-			return GLNode.prototype.build.call( this, builder, output, uuid );
+			return Node.prototype.build.call( this, builder, output, uuid );
 
 
 		}
 		}
 
 
 		uuid = this.getUuid( false );
 		uuid = this.getUuid( false );
 
 
-		var name = this.getTemp( builder, uuid ),
-			type = data.output || this.getType( builder );
+		var name = this.getTemp( builder, uuid );
 
 
 		if ( name ) {
 		if ( name ) {
 
 
@@ -84,7 +84,7 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 
 
 	}
 	}
 
 
-	return GLNode.prototype.build.call( this, builder, output, uuid );
+	return Node.prototype.build.call( this, builder, output, uuid );
 
 
 };
 };
 
 
@@ -114,10 +114,10 @@ TempNode.prototype.getTemp = function ( builder, uuid ) {
 
 
 	uuid = uuid || this.uuid;
 	uuid = uuid || this.uuid;
 
 
-	var tempVar = builder.getVars()[uuid]
-	
+	var tempVar = builder.getVars()[ uuid ];
+
 	return tempVar ? tempVar.name : undefined;
 	return tempVar ? tempVar.name : undefined;
-	
+
 };
 };
 
 
 TempNode.prototype.generate = function ( builder, output, uuid, type, ns ) {
 TempNode.prototype.generate = function ( builder, output, uuid, type, ns ) {

+ 10 - 10
examples/js/nodes/core/VarNode.js

@@ -2,17 +2,17 @@
  * @author sunag / http://www.sunag.com.br/
  * @author sunag / http://www.sunag.com.br/
  */
  */
 
 
-import { GLNode } from './GLNode.js';
+import { Node } from './Node.js';
 
 
 function VarNode( type, value ) {
 function VarNode( type, value ) {
 
 
-	GLNode.call( this, type );
-	
+	Node.call( this, type );
+
 	this.value = value;
 	this.value = value;
 
 
-};
+}
 
 
-VarNode.prototype = Object.create( GLNode.prototype );
+VarNode.prototype = Object.create( Node.prototype );
 VarNode.prototype.constructor = VarNode;
 VarNode.prototype.constructor = VarNode;
 VarNode.prototype.nodeType = "Var";
 VarNode.prototype.nodeType = "Var";
 
 
@@ -31,18 +31,18 @@ VarNode.prototype.generate = function ( builder, output ) {
 		builder.addNodeCode( varying.name + ' = ' + this.value.build( builder, this.getType( builder ) ) + ';' );
 		builder.addNodeCode( varying.name + ' = ' + this.value.build( builder, this.getType( builder ) ) + ';' );
 
 
 	}
 	}
-	
+
 	return builder.format( varying.name, this.getType( builder ), output );
 	return builder.format( varying.name, this.getType( builder ), output );
 
 
 };
 };
 
 
 VarNode.prototype.copy = function ( source ) {
 VarNode.prototype.copy = function ( source ) {
-	
-	GLNode.prototype.copy.call( this, source );
-	
+
+	Node.prototype.copy.call( this, source );
+
 	this.type = source.type;
 	this.type = source.type;
 	this.value = source.value;
 	this.value = source.value;
-	
+
 };
 };
 
 
 VarNode.prototype.toJSON = function ( meta ) {
 VarNode.prototype.toJSON = function ( meta ) {

+ 15 - 15
examples/js/nodes/effects/BlurNode.js

@@ -24,10 +24,10 @@ function BlurNode( value, uv, radius, size ) {
 	this.horizontal = new FloatNode( 1 / 64 );
 	this.horizontal = new FloatNode( 1 / 64 );
 	this.vertical = new FloatNode( 1 / 64 );
 	this.vertical = new FloatNode( 1 / 64 );
 
 
-};
+}
+
+BlurNode.Nodes = ( function () {
 
 
-BlurNode.Nodes = (function() {
-	
 	var blurX = new FunctionNode( [
 	var blurX = new FunctionNode( [
 		"vec4 blurX( sampler2D texture, vec2 uv, float s ) {",
 		"vec4 blurX( sampler2D texture, vec2 uv, float s ) {",
 		"	vec4 sum = vec4( 0.0 );",
 		"	vec4 sum = vec4( 0.0 );",
@@ -40,10 +40,10 @@ BlurNode.Nodes = (function() {
 		"	sum += texture2D( texture, vec2( uv.x + 2.0 * s, uv.y ) ) * 0.12245;",
 		"	sum += texture2D( texture, vec2( uv.x + 2.0 * s, uv.y ) ) * 0.12245;",
 		"	sum += texture2D( texture, vec2( uv.x + 3.0 * s, uv.y ) ) * 0.0918;",
 		"	sum += texture2D( texture, vec2( uv.x + 3.0 * s, uv.y ) ) * 0.0918;",
 		"	sum += texture2D( texture, vec2( uv.x + 4.0 * s, uv.y ) ) * 0.051;",
 		"	sum += texture2D( texture, vec2( uv.x + 4.0 * s, uv.y ) ) * 0.051;",
-		"	return sum;",
+		"	return sum * .667;",
 		"}"
 		"}"
 	].join( "\n" ) );
 	].join( "\n" ) );
-	
+
 	var blurY = new FunctionNode( [
 	var blurY = new FunctionNode( [
 		"vec4 blurY( sampler2D texture, vec2 uv, float s ) {",
 		"vec4 blurY( sampler2D texture, vec2 uv, float s ) {",
 		"	vec4 sum = vec4( 0.0 );",
 		"	vec4 sum = vec4( 0.0 );",
@@ -56,16 +56,16 @@ BlurNode.Nodes = (function() {
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 2.0 * s ) ) * 0.12245;",
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 2.0 * s ) ) * 0.12245;",
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 3.0 * s ) ) * 0.0918;",
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 3.0 * s ) ) * 0.0918;",
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 4.0 * s ) ) * 0.051;",
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 4.0 * s ) ) * 0.051;",
-		"	return sum;",
+		"	return sum * .667;",
 		"}"
 		"}"
 	].join( "\n" ) );
 	].join( "\n" ) );
-	
+
 	return {
 	return {
 		blurX: blurX,
 		blurX: blurX,
 		blurY: blurY
 		blurY: blurY
 	};
 	};
-	
-})();
+
+} )();
 
 
 
 
 BlurNode.prototype = Object.create( TempNode.prototype );
 BlurNode.prototype = Object.create( TempNode.prototype );
@@ -98,7 +98,7 @@ BlurNode.prototype.generate = function ( builder, output ) {
 
 
 		var blurX = builder.include( BlurNode.Nodes.blurX ),
 		var blurX = builder.include( BlurNode.Nodes.blurX ),
 			blurY = builder.include( BlurNode.Nodes.blurY );
 			blurY = builder.include( BlurNode.Nodes.blurY );
-		
+
 		if ( this.blurX ) {
 		if ( this.blurX ) {
 
 
 			blurCode.push( blurX + '( ' + this.value.build( builder, 'sampler2D' ) + ', ' + this.uv.build( builder, 'v2' ) + ', ' + this.horizontal.build( builder, 'f' ) + ' )' );
 			blurCode.push( blurX + '( ' + this.value.build( builder, 'sampler2D' ) + ', ' + this.uv.build( builder, 'v2' ) + ', ' + this.horizontal.build( builder, 'f' ) + ' )' );
@@ -111,7 +111,7 @@ BlurNode.prototype.generate = function ( builder, output ) {
 
 
 		}
 		}
 
 
-		if ( blurCode.length == 2 ) code = '( ' + blurCode.join( ' + ' ) + '/ 2.0 )';
+		if ( blurCode.length == 2 ) code = '( ' + blurCode.join( ' + ' ) + ' / 2.0 )';
 		else if ( blurCode.length ) code = '( ' + blurCode[ 0 ] + ' )';
 		else if ( blurCode.length ) code = '( ' + blurCode[ 0 ] + ' )';
 		else code = 'vec4( 0.0 )';
 		else code = 'vec4( 0.0 )';
 
 
@@ -128,9 +128,9 @@ BlurNode.prototype.generate = function ( builder, output ) {
 };
 };
 
 
 BlurNode.prototype.copy = function ( source ) {
 BlurNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.value = source.value;
 	this.value = source.value;
 	this.uv = source.uv;
 	this.uv = source.uv;
 	this.radius = source.radius;
 	this.radius = source.radius;
@@ -139,7 +139,7 @@ BlurNode.prototype.copy = function ( source ) {
 
 
 	this.blurX = source.blurX;
 	this.blurX = source.blurX;
 	this.blurY = source.blurY;
 	this.blurY = source.blurY;
-					
+
 };
 };
 
 
 BlurNode.prototype.toJSON = function ( meta ) {
 BlurNode.prototype.toJSON = function ( meta ) {
@@ -165,4 +165,4 @@ BlurNode.prototype.toJSON = function ( meta ) {
 
 
 };
 };
 
 
-export { BlurNode };
+export { BlurNode };

+ 24 - 24
examples/js/nodes/effects/ColorAdjustmentNode.js

@@ -15,58 +15,58 @@ function ColorAdjustmentNode( rgb, adjustment, method ) {
 
 
 	this.method = method || ColorAdjustmentNode.SATURATION;
 	this.method = method || ColorAdjustmentNode.SATURATION;
 
 
-};
+}
+
+ColorAdjustmentNode.Nodes = ( function () {
 
 
-ColorAdjustmentNode.Nodes = (function() {
-	
 	var hue = new FunctionNode( [
 	var hue = new FunctionNode( [
 		"vec3 hue(vec3 rgb, float adjustment) {",
 		"vec3 hue(vec3 rgb, float adjustment) {",
-		
+
 		"	const mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);",
 		"	const mat3 RGBtoYIQ = mat3(0.299, 0.587, 0.114, 0.595716, -0.274453, -0.321263, 0.211456, -0.522591, 0.311135);",
 		"	const mat3 YIQtoRGB = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.107, 1.7046);",
 		"	const mat3 YIQtoRGB = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.107, 1.7046);",
-		
+
 		"	vec3 yiq = RGBtoYIQ * rgb;",
 		"	vec3 yiq = RGBtoYIQ * rgb;",
-		
+
 		"	float hue = atan(yiq.z, yiq.y) + adjustment;",
 		"	float hue = atan(yiq.z, yiq.y) + adjustment;",
 		"	float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);",
 		"	float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);",
-		
+
 		"	return YIQtoRGB * vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));",
 		"	return YIQtoRGB * vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));",
-		
+
 		"}"
 		"}"
 	].join( "\n" ) );
 	].join( "\n" ) );
-	
+
 	var saturation = new FunctionNode( [
 	var saturation = new FunctionNode( [
 		// Algorithm from Chapter 16 of OpenGL Shading Language
 		// Algorithm from Chapter 16 of OpenGL Shading Language
 		"vec3 saturation(vec3 rgb, float adjustment) {",
 		"vec3 saturation(vec3 rgb, float adjustment) {",
-		
+
 		"	vec3 intensity = vec3( luminance( rgb ) );",
 		"	vec3 intensity = vec3( luminance( rgb ) );",
-		
+
 		"	return mix( intensity, rgb, adjustment );",
 		"	return mix( intensity, rgb, adjustment );",
-		
+
 		"}"
 		"}"
 	].join( "\n" ), [ LuminanceNode.Nodes.luminance ] ); // include LuminanceNode function
 	].join( "\n" ), [ LuminanceNode.Nodes.luminance ] ); // include LuminanceNode function
-	
+
 	var vibrance = new FunctionNode( [
 	var vibrance = new FunctionNode( [
 		// Shader by Evan Wallace adapted by @lo-th
 		// Shader by Evan Wallace adapted by @lo-th
 		"vec3 vibrance(vec3 rgb, float adjustment) {",
 		"vec3 vibrance(vec3 rgb, float adjustment) {",
-		
+
 		"	float average = (rgb.r + rgb.g + rgb.b) / 3.0;",
 		"	float average = (rgb.r + rgb.g + rgb.b) / 3.0;",
-		
+
 		"	float mx = max(rgb.r, max(rgb.g, rgb.b));",
 		"	float mx = max(rgb.r, max(rgb.g, rgb.b));",
 		"	float amt = (mx - average) * (-3.0 * adjustment);",
 		"	float amt = (mx - average) * (-3.0 * adjustment);",
-		
+
 		"	return mix(rgb.rgb, vec3(mx), amt);",
 		"	return mix(rgb.rgb, vec3(mx), amt);",
-		
+
 		"}"
 		"}"
 	].join( "\n" ) );
 	].join( "\n" ) );
-	
+
 	return {
 	return {
 		hue: hue,
 		hue: hue,
 		saturation: saturation,
 		saturation: saturation,
 		vibrance: vibrance
 		vibrance: vibrance
 	};
 	};
-	
-})();
+
+} )();
 
 
 ColorAdjustmentNode.SATURATION = 'saturation';
 ColorAdjustmentNode.SATURATION = 'saturation';
 ColorAdjustmentNode.HUE = 'hue';
 ColorAdjustmentNode.HUE = 'hue';
@@ -99,16 +99,16 @@ ColorAdjustmentNode.prototype.generate = function ( builder, output ) {
 
 
 	}
 	}
 
 
-	var method = builder.include( ColorAdjustmentNode.Nodes[this.method] );
+	var method = builder.include( ColorAdjustmentNode.Nodes[ this.method ] );
 
 
 	return builder.format( method + '( ' + rgb + ', ' + adjustment + ' )', this.getType( builder ), output );
 	return builder.format( method + '( ' + rgb + ', ' + adjustment + ' )', this.getType( builder ), output );
 
 
 };
 };
 
 
 ColorAdjustmentNode.prototype.copy = function ( source ) {
 ColorAdjustmentNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.rgb = source.rgb;
 	this.rgb = source.rgb;
 	this.adjustment = source.adjustment;
 	this.adjustment = source.adjustment;
 	this.method = source.method;
 	this.method = source.method;
@@ -133,4 +133,4 @@ ColorAdjustmentNode.prototype.toJSON = function ( meta ) {
 
 
 };
 };
 
 
-export { ColorAdjustmentNode };
+export { ColorAdjustmentNode };

Some files were not shown because too many files changed in this diff