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 
-#### 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
 #### Before reporting a bug

+ 185 - 82
build/three.js

@@ -14722,7 +14722,7 @@
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 
-	function WebGLBufferRenderer( gl, extensions, info ) {
+	function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
 
 		var mode;
 
@@ -14742,16 +14742,26 @@
 
 		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 );
 
@@ -14823,6 +14833,8 @@
 
 		}
 
+		var isWebGL2 = typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext;
+
 		var precision = parameters.precision !== undefined ? parameters.precision : 'highp';
 		var maxPrecision = getMaxPrecision( precision );
 
@@ -14846,11 +14858,13 @@
 		var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
 
 		var vertexTextures = maxVertexTextures > 0;
-		var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
+		var floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
 		var floatVertexTextures = vertexTextures && floatFragmentTextures;
 
 		return {
 
+			isWebGL2: isWebGL2,
+
 			getMaxAnisotropy: getMaxAnisotropy,
 			getMaxPrecision: getMaxPrecision,
 
@@ -15123,18 +15137,7 @@
 
 			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 ) {
 
@@ -15286,7 +15289,7 @@
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 
-	function WebGLIndexedBufferRenderer( gl, extensions, info ) {
+	function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
 
 		var mode;
 
@@ -15315,16 +15318,26 @@
 
 		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 );
 
@@ -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;
 
@@ -16797,7 +16810,7 @@
 
 		//
 
-		var customExtensions = generateExtensions( material.extensions, parameters, extensions );
+		var customExtensions = capabilities.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );
 
 		var customDefines = generateDefines( defines );
 
@@ -16885,7 +16898,7 @@
 				parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
 
 				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 modelViewMatrix;',
@@ -16990,9 +17003,9 @@
 				parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
 
 				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 vec3 cameraPosition;',
@@ -17028,6 +17041,50 @@
 		vertexShader = unrollLoops( vertexShader );
 		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 fragmentGlsl = prefixFragment + fragmentShader;
 
@@ -17465,7 +17522,7 @@
 
 			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 );
 
 			}
@@ -18727,7 +18784,7 @@
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 
-	function WebGLState( gl, extensions, utils ) {
+	function WebGLState( gl, extensions, utils, capabilities ) {
 
 		function ColorBuffer() {
 
@@ -19039,7 +19096,7 @@
 		var enabledAttributes = new Uint8Array( maxVertexAttributes );
 		var attributeDivisors = new Uint8Array( maxVertexAttributes );
 
-		var capabilities = {};
+		var enabledCapabilities = {};
 
 		var compressedTextureFormats = null;
 
@@ -19156,9 +19213,9 @@
 
 			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;
 
 			}
@@ -19182,10 +19239,10 @@
 
 		function enable( id ) {
 
-			if ( capabilities[ id ] !== true ) {
+			if ( enabledCapabilities[ id ] !== true ) {
 
 				gl.enable( id );
-				capabilities[ id ] = true;
+				enabledCapabilities[ id ] = true;
 
 			}
 
@@ -19193,10 +19250,10 @@
 
 		function disable( id ) {
 
-			if ( capabilities[ id ] !== false ) {
+			if ( enabledCapabilities[ id ] !== false ) {
 
 				gl.disable( id );
-				capabilities[ id ] = false;
+				enabledCapabilities[ id ] = false;
 
 			}
 
@@ -19605,7 +19662,7 @@
 
 			}
 
-			capabilities = {};
+			enabledCapabilities = {};
 
 			compressedTextureFormats = null;
 
@@ -19674,7 +19731,6 @@
 
 	function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
 
-		var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
 		var _videoTextures = {};
 		var _canvas;
 
@@ -19743,6 +19799,8 @@
 
 		function textureNeedsPowerOfTwo( texture ) {
 
+			if ( capabilities.isWebGL2 ) return false;
+
 			return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
 				( 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
 
 		function filterFallback( f ) {
@@ -19960,7 +20042,8 @@
 					var image = cubeImage[ 0 ],
 						isPowerOfTwoImage = isPowerOfTwo( image ),
 						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 );
 
@@ -19970,11 +20053,11 @@
 
 							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 {
 
-								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 ) {
 
-										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 {
 
@@ -20000,7 +20083,7 @@
 
 								} 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 ( 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 ) {
 
@@ -20132,7 +20215,8 @@
 
 			var isPowerOfTwoImage = isPowerOfTwo( image ),
 				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 );
 
@@ -20142,21 +20226,21 @@
 
 				// populate depth texture with dummy data
 
-				var internalFormat = _gl.DEPTH_COMPONENT;
+				glInternalFormat = _gl.DEPTH_COMPONENT;
 
 				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
-					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
 					// 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/)
 				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
 					// 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 ) {
 
@@ -20205,7 +20289,7 @@
 					for ( var i = 0, il = mipmaps.length; i < il; 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 {
 
-					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;
 
 				}
@@ -20229,7 +20313,7 @@
 
 						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 {
 
@@ -20239,7 +20323,7 @@
 
 					} 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 ++ ) {
 
 						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 {
 
-					state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
+					state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
 					textureProperties.__maxMipLevel = 0;
 
 				}
@@ -20295,7 +20379,8 @@
 
 			var glFormat = utils.convert( renderTarget.texture.format );
 			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.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
@@ -20540,7 +20625,7 @@
 	 * @author thespite / http://www.twitter.com/thespite
 	 */
 
-	function WebGLUtils( gl, extensions ) {
+	function WebGLUtils( gl, extensions, capabilities ) {
 
 		function convert( p ) {
 
@@ -20572,6 +20657,8 @@
 
 			if ( p === HalfFloatType ) {
 
+				if ( capabilities.isWebGL2 ) return gl.HALF_FLOAT;
+
 				extension = extensions.get( 'OES_texture_half_float' );
 
 				if ( extension !== null ) return extension.HALF_FLOAT_OES;
@@ -20661,6 +20748,13 @@
 
 			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' );
 
 				if ( extension !== null ) {
@@ -20674,6 +20768,8 @@
 
 			if ( p === UnsignedInt248Type ) {
 
+				if ( capabilities.isWebGL2 ) return gl.UNSIGNED_INT_24_8;
+
 				extension = extensions.get( 'WEBGL_depth_texture' );
 
 				if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
@@ -21805,20 +21901,26 @@
 		function initGLContext() {
 
 			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 );
 
-			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.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
 
@@ -21835,8 +21937,8 @@
 
 			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;
 
@@ -22373,7 +22475,7 @@
 
 		function setupVertexAttributes( material, program, geometry ) {
 
-			if ( geometry && geometry.isInstancedBufferGeometry ) {
+			if ( geometry && geometry.isInstancedBufferGeometry & ! capabilities.isWebGL2 ) {
 
 				if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 
@@ -22802,8 +22904,6 @@
 							_vector3.setFromMatrixPosition( object.matrixWorld )
 								.applyMatrix4( _projScreenMatrix );
 
-							var material = object.material;
-
 						}
 
 						var geometry = objects.update( object );
@@ -23038,6 +23138,9 @@
 
 				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 );
 
 				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)
-						! ( 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.' );
 						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/
  */
 
-function WebGLBufferRenderer( gl, extensions, info ) {
+function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
 
 	var mode;
 
@@ -14736,16 +14736,26 @@ function WebGLBufferRenderer( gl, extensions, info ) {
 
 	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 );
 
@@ -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 maxPrecision = getMaxPrecision( precision );
 
@@ -14840,11 +14852,13 @@ function WebGLCapabilities( gl, extensions, parameters ) {
 	var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
 
 	var vertexTextures = maxVertexTextures > 0;
-	var floatFragmentTextures = !! extensions.get( 'OES_texture_float' );
+	var floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );
 	var floatVertexTextures = vertexTextures && floatFragmentTextures;
 
 	return {
 
+		isWebGL2: isWebGL2,
+
 		getMaxAnisotropy: getMaxAnisotropy,
 		getMaxPrecision: getMaxPrecision,
 
@@ -15117,18 +15131,7 @@ function WebGLGeometries( gl, attributes, info ) {
 
 		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 ) {
 
@@ -15280,7 +15283,7 @@ function WebGLGeometries( gl, attributes, info ) {
  * @author mrdoob / http://mrdoob.com/
  */
 
-function WebGLIndexedBufferRenderer( gl, extensions, info ) {
+function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
 
 	var mode;
 
@@ -15309,16 +15312,26 @@ function WebGLIndexedBufferRenderer( gl, extensions, info ) {
 
 	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 );
 
@@ -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;
 
@@ -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 );
 
@@ -16879,7 +16892,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 			parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',
 
 			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 modelViewMatrix;',
@@ -16984,9 +16997,9 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 			parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',
 
 			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 vec3 cameraPosition;',
@@ -17022,6 +17035,50 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters
 	vertexShader = unrollLoops( vertexShader );
 	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 fragmentGlsl = prefixFragment + fragmentShader;
 
@@ -17459,7 +17516,7 @@ function WebGLPrograms( renderer, extensions, capabilities ) {
 
 		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 );
 
 		}
@@ -18721,7 +18778,7 @@ function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {
  * @author mrdoob / http://mrdoob.com/
  */
 
-function WebGLState( gl, extensions, utils ) {
+function WebGLState( gl, extensions, utils, capabilities ) {
 
 	function ColorBuffer() {
 
@@ -19033,7 +19090,7 @@ function WebGLState( gl, extensions, utils ) {
 	var enabledAttributes = new Uint8Array( maxVertexAttributes );
 	var attributeDivisors = new Uint8Array( maxVertexAttributes );
 
-	var capabilities = {};
+	var enabledCapabilities = {};
 
 	var compressedTextureFormats = null;
 
@@ -19150,9 +19207,9 @@ function WebGLState( gl, extensions, utils ) {
 
 		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;
 
 		}
@@ -19176,10 +19233,10 @@ function WebGLState( gl, extensions, utils ) {
 
 	function enable( id ) {
 
-		if ( capabilities[ id ] !== true ) {
+		if ( enabledCapabilities[ id ] !== true ) {
 
 			gl.enable( id );
-			capabilities[ id ] = true;
+			enabledCapabilities[ id ] = true;
 
 		}
 
@@ -19187,10 +19244,10 @@ function WebGLState( gl, extensions, utils ) {
 
 	function disable( id ) {
 
-		if ( capabilities[ id ] !== false ) {
+		if ( enabledCapabilities[ id ] !== false ) {
 
 			gl.disable( id );
-			capabilities[ id ] = false;
+			enabledCapabilities[ id ] = false;
 
 		}
 
@@ -19599,7 +19656,7 @@ function WebGLState( gl, extensions, utils ) {
 
 		}
 
-		capabilities = {};
+		enabledCapabilities = {};
 
 		compressedTextureFormats = null;
 
@@ -19668,7 +19725,6 @@ function WebGLState( gl, extensions, utils ) {
 
 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
 
-	var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */
 	var _videoTextures = {};
 	var _canvas;
 
@@ -19737,6 +19793,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 	function textureNeedsPowerOfTwo( texture ) {
 
+		if ( capabilities.isWebGL2 ) return false;
+
 		return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||
 			( 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
 
 	function filterFallback( f ) {
@@ -19954,7 +20036,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 				var image = cubeImage[ 0 ],
 					isPowerOfTwoImage = isPowerOfTwo( image ),
 					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 );
 
@@ -19964,11 +20047,11 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 						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 {
 
-							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 ) {
 
-									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 {
 
@@ -19994,7 +20077,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 							} 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 ( 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 ) {
 
@@ -20126,7 +20209,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 		var isPowerOfTwoImage = isPowerOfTwo( image ),
 			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 );
 
@@ -20136,21 +20220,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 			// populate depth texture with dummy data
 
-			var internalFormat = _gl.DEPTH_COMPONENT;
+			glInternalFormat = _gl.DEPTH_COMPONENT;
 
 			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
-				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
 				// 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/)
 			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
 				// 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 ) {
 
@@ -20199,7 +20283,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 				for ( var i = 0, il = mipmaps.length; i < il; 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 {
 
-				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;
 
 			}
@@ -20223,7 +20307,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 					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 {
 
@@ -20233,7 +20317,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 				} 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 ++ ) {
 
 					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 {
 
-				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image );
+				state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
 				textureProperties.__maxMipLevel = 0;
 
 			}
@@ -20289,7 +20373,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 		var glFormat = utils.convert( renderTarget.texture.format );
 		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.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
@@ -20534,7 +20619,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
  * @author thespite / http://www.twitter.com/thespite
  */
 
-function WebGLUtils( gl, extensions ) {
+function WebGLUtils( gl, extensions, capabilities ) {
 
 	function convert( p ) {
 
@@ -20566,6 +20651,8 @@ function WebGLUtils( gl, extensions ) {
 
 		if ( p === HalfFloatType ) {
 
+			if ( capabilities.isWebGL2 ) return gl.HALF_FLOAT;
+
 			extension = extensions.get( 'OES_texture_half_float' );
 
 			if ( extension !== null ) return extension.HALF_FLOAT_OES;
@@ -20655,6 +20742,13 @@ function WebGLUtils( gl, extensions ) {
 
 		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' );
 
 			if ( extension !== null ) {
@@ -20668,6 +20762,8 @@ function WebGLUtils( gl, extensions ) {
 
 		if ( p === UnsignedInt248Type ) {
 
+			if ( capabilities.isWebGL2 ) return gl.UNSIGNED_INT_24_8;
+
 			extension = extensions.get( 'WEBGL_depth_texture' );
 
 			if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL;
@@ -21799,20 +21895,26 @@ function WebGLRenderer( parameters ) {
 	function initGLContext() {
 
 		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 );
 
-		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.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) );
 
@@ -21829,8 +21931,8 @@ function WebGLRenderer( parameters ) {
 
 		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;
 
@@ -22367,7 +22469,7 @@ function WebGLRenderer( parameters ) {
 
 	function setupVertexAttributes( material, program, geometry ) {
 
-		if ( geometry && geometry.isInstancedBufferGeometry ) {
+		if ( geometry && geometry.isInstancedBufferGeometry & ! capabilities.isWebGL2 ) {
 
 			if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) {
 
@@ -22796,8 +22898,6 @@ function WebGLRenderer( parameters ) {
 						_vector3.setFromMatrixPosition( object.matrixWorld )
 							.applyMatrix4( _projScreenMatrix );
 
-						var material = object.material;
-
 					}
 
 					var geometry = objects.update( object );
@@ -23032,6 +23132,9 @@ function WebGLRenderer( parameters ) {
 
 			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 );
 
 			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)
-					! ( 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.' );
 					return;

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

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

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

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

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

@@ -55,7 +55,7 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:null update]( camera )</h3>
+		<h3>[method:null update]( [param:PerspectiveCamera camera] )</h3>
 		<p>
 		Update the stereo cameras based on the camera passed in.
 		</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>
 		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
 		<h3>[method:null onUpload]( [param:Function callback] ) </h3>
@@ -185,25 +185,25 @@
 		<h3>[method:BufferAttribute setDynamic] ( [param:Boolean value] ) </h3>
 		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
 

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

@@ -91,13 +91,13 @@
 
 		<h2>Methods</h2>
 
-		<h3>[property:null computeGroups]( [page:Geometry geometry] )</h3>
+		<h3>[property:null computeGroups]( [param:Geometry geometry] )</h3>
 		<p>
 			Compute the parts of the geometry that have different materialIndex.
 			See [page:BufferGeometry.groups].
 		</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>
 
 

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

@@ -91,15 +91,15 @@
 			Set [page:InterleavedBuffer.dynamic dynamic] to value.
 		</p>
 
-		<h3>[method:InterleavedBuffer copy]( source ) </h3>
+		<h3>[method:InterleavedBuffer copy]( [param:InterleavedBuffer source] ) </h3>
 		<p>
 		 Copies another [name] to this [name].
 		</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>
 
-		<h3>[method:InterleavedBuffer set]( value, offset ) </h3>
+		<h3>[method:InterleavedBuffer set]( [param:TypedArray value], [param:Integer offset] ) </h3>
 		<p>
 			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 />

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

@@ -62,37 +62,37 @@
 
 		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
-		<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>
 
 

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

@@ -39,7 +39,7 @@
 		<h3>[property:Boolean frustumCulled]</h3>
 		<p>
 		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>
 
 		<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 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 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>
 		This creates a new raycaster object.<br />
@@ -144,7 +144,7 @@
 		Updates the ray with a new origin and direction.
 		</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>
 		[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 />

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

@@ -50,7 +50,7 @@
 		<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>
 			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]

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

@@ -51,7 +51,7 @@
 		<h2>Methods</h2>
 		<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>
 			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

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

@@ -52,10 +52,10 @@
 		</p>
 
 		<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>
@@ -104,26 +104,28 @@ scene.add( directionalLight );
 
 			*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
-			<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
 			updated each frame.<br /><br />
 
 			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:
-			<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.
 		</p>
 
 
-
 		<h2>Methods</h2>
 
 		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>
 
 
-		<h3>[property:String withCredentials]</h3>
-		<p>
-			Whether the XMLHttpRequest uses credentials - see [page:.setWithCredentials].
-			Default is *undefined*.
-		</p>
-
 		<h2>Methods</h2>
 
 		<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.
 		</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>
 

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

@@ -75,8 +75,8 @@ var material = new THREE.LineBasicMaterial( {
 		<p>
 			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.
 		</p>
 

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

@@ -70,8 +70,8 @@ var material = new THREE.LineDashedMaterial( {
 		<p>
 			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.
 		</p>
 

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

@@ -162,8 +162,7 @@
 
 		<h3>[property:Boolean needsUpdate]</h3>
 		<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.
 		</p>
 

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

@@ -151,8 +151,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 		<h2>Methods</h2>

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

@@ -107,8 +107,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 		<h2>Methods</h2>

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

@@ -177,8 +177,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 		<h2>Methods</h2>

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

@@ -68,8 +68,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 		<h2>Methods</h2>

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

@@ -247,8 +247,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 		<h2>Methods</h2>

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

@@ -274,8 +274,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 		<h2>Methods</h2>

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

@@ -55,7 +55,7 @@ var starField = new THREE.Points( starsGeometry, starsMaterial );
 scene.add( starField );
 		</code>
 
-		<h3>[name]( [page:Object parameters] )</h3>
+		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
 			[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 />

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

@@ -371,8 +371,9 @@ this.extensions = {
 		<h3>[property:Float linewidth]</h3>
 		<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>
 
 
@@ -443,8 +444,9 @@ this.extensions = {
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<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>
 
 

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

@@ -37,7 +37,7 @@ scene.add( sprite );
 		</code>
 
 
-		<h3>[name]( [page:Object parameters] )</h3>
+		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
 			[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 />

+ 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.
 		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 />
 
 		Creates a [name] bounded by min and max.
@@ -172,7 +172,7 @@
 		<h3>[method:Box2 set]( [param:Vector2 min], [param:Vector2 max] )</h3>
 		<p>
 			[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.
 		</p>

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

@@ -50,7 +50,7 @@
 			and [page:.y y] properties to this cylindrical.
 		</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]
 		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 ]].
 		</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>

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

@@ -54,12 +54,7 @@
 		and [page:Float t] = 1 will return [page:Float y].
 		</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>
 		[page:Float x] — Value to be mapped.<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>
 		<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>
 		[page:Float n11] - value to put in row 1, col 1.<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>
 		<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>
 		[page:Float tx] - offset x<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>
 		<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>
 			Set the [page:.elements elements] of this matrix to the supplied row-major values [page:Float n11],
 			[page:Float n12], ... [page:Float n44].

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

@@ -261,17 +261,7 @@ q.slerp( qb, t )
 		</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>
 		[page:Array dst] - 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>
 		<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>
 
 		<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.
 		</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>
 
 		<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].
 		</p>
 
-		<h3>[method:Texture clone]( [param:Texture texture] )</h3>
+		<h3>[method:Texture clone]()</h3>
 		<p>
 		Make copy of the texture. Note this is not a "deep copy", the image is shared.
 		</p>
 
-		<h3>[method:Texture toJSON]( meta )</h3>
+		<h3>[method:Texture toJSON]( [param:Object meta] )</h3>
 		<p>
 		meta -- optional object containing metadata.<br />
 		Convert the material to three.js JSON format.
@@ -250,7 +250,7 @@
 		Call [page:EventDispatcher EventDispatcher].dispatchEvent with a 'dispose' event type.
 		</p>
 
-		<h3>[method:null transformUv]( uv )</h3>
+		<h3>[method:null transformUv]( [param:Vector2 uv] )</h3>
 		<p>
 		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.

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

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

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

@@ -12,7 +12,7 @@
 		<h1>[name]</h1>
 
 		<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>
 
 		<h2>Example</h2>
@@ -26,9 +26,34 @@
 			// resource URL
 			'data/svgSample.svg',
 			// 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

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

@@ -21,7 +21,7 @@
 				<li>Complex or animated user interfaces</li>
 			</ul>
 			<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).
 			</p>
 			<p>

+ 2 - 0
docs/index.html

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

+ 6 - 6
editor/index.html

@@ -4,12 +4,12 @@
 		<title>three.js / editor</title>
 		<meta charset="utf-8">
 		<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>
 	<body ontouchstart="">
 		<link href="css/main.css" rel="stylesheet" />

+ 1 - 1
examples/canvas_ascii_effect.html

@@ -72,7 +72,7 @@
 				light.position.set( - 500, - 500, - 500 );
 				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 );
 
 				// Plane

+ 1 - 1
examples/canvas_camera_orthographic.html

@@ -58,7 +58,7 @@
 
 				// 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 } );
 
 				for ( var i = 0; i < 100; i ++ ) {

+ 1 - 1
examples/canvas_geometry_earth.html

@@ -72,7 +72,7 @@
 				var loader = new THREE.TextureLoader();
 				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 mesh = new THREE.Mesh( geometry, material );

+ 1 - 1
examples/canvas_geometry_hierarchy.html

@@ -52,7 +52,7 @@
 				scene = new THREE.Scene();
 				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 } );
 
 				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 );
 
 				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 );
 
 				mesh = new THREE.Mesh( geometry, materials );
 				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
 
-					var geometry = new THREE.ShapeGeometry( shape );
+					var geometry = new THREE.ShapeBufferGeometry( shape );
 					var material = new THREE.MeshBasicMaterial( { color: color, overdraw: 0.5 } );
 
 					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,
 					size: 80,

+ 1 - 1
examples/canvas_interactive_cubes.html

@@ -55,7 +55,7 @@
 				scene = new THREE.Scene();
 				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 ++ ) {
 

+ 1 - 1
examples/canvas_interactive_cubes_tween.html

@@ -54,7 +54,7 @@
 				scene = new THREE.Scene();
 				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 ++ ) {
 

+ 1 - 1
examples/canvas_interactive_voxelpainter.html

@@ -28,7 +28,7 @@
 
 			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 objects = [];

+ 42 - 21
examples/canvas_lines_colors.html

@@ -49,14 +49,11 @@
 		<script src="js/renderers/Projector.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/hilbert2D.js"></script>
 
 		<script>
 
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
 			var mouseX = 0, mouseY = 0;
 
 			var windowHalfX = window.innerWidth / 2;
@@ -81,37 +78,61 @@
 
 				// 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
 
-				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
 

+ 25 - 58
examples/canvas_lines_dashed.html

@@ -38,17 +38,13 @@
 
 		<script src="js/geometries/hilbert3D.js"></script>
 
-		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 		<script>
 
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
 			var renderer, scene, camera, stats;
 			var objects = [];
 
-
 			var WIDTH = window.innerWidth, HEIGHT = window.innerHeight;
 
 			init();
@@ -62,23 +58,43 @@
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0x111111 );
 
-				var subdivisions = 6;
+				var subdivisions = 3;
 				var recursion = 1;
 
 				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 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 );
 				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 );
 				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() {
 
 				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.scale.x = mesh.scale.y = mesh.scale.z = 1.5;

+ 1 - 1
examples/canvas_performance.html

@@ -53,7 +53,7 @@
 
 				// 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 } );
 
 				for ( var i = 0; i < 20; i ++ ) {

+ 1 - 1
examples/canvas_sandbox.html

@@ -56,7 +56,7 @@
 				group = new THREE.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' );
 				envMap.mapping = THREE.SphericalReflectionMapping;

+ 2 - 0
examples/files.js

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

+ 2 - 4
examples/index.html

@@ -296,11 +296,9 @@
 			link.setAttribute( 'target', 'viewer' );
 			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 ) {
 
-				build.bindMatrix = new THREE.Matrix4().fromArray( data.bindShapeMatrix ).transpose(); 
+				build.bindMatrix = new THREE.Matrix4().fromArray( data.bindShapeMatrix ).transpose();
 
 			} 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 ) {
 
 			var effect = getEffect( data.url );
@@ -1499,28 +1521,40 @@ THREE.ColladaLoader.prototype = {
 
 				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 {
 
-						texture.wrapS = THREE.RepeatWrapping;
-						texture.wrapT = THREE.RepeatWrapping;
+						console.warn( 'THREE.ColladaLoader: Loader for texture %s not found.', image );
 
-					}
+						return null;
 
-					return texture;
+					}
 
 				} 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;
 
@@ -3761,6 +3803,15 @@ THREE.ColladaLoader.prototype = {
 		var textureLoader = new THREE.TextureLoader( this.manager );
 		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 
+		var tgaLoader;
+
+		if ( THREE.TGALoader ) {
+
+			tgaLoader = new THREE.TGALoader( this.manager );
+			tgaLoader.setPath( path );
+
+		}
+
 		//
 
 		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 ) {
 
-						case EXTENSIONS.KHR_LIGHTS:
+						case EXTENSIONS.KHR_LIGHTS_PUNCTUAL:
 							extensions[ extensionName ] = new GLTFLightsExtension( json );
 							break;
 
@@ -237,7 +237,7 @@ THREE.GLTFLoader = ( function () {
 	var EXTENSIONS = {
 		KHR_BINARY_GLTF: 'KHR_binary_glTF',
 		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_UNLIT: 'KHR_materials_unlit',
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
@@ -270,21 +270,24 @@ THREE.GLTFLoader = ( function () {
 	 */
 	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 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':
 					lightNode = new THREE.DirectionalLight( color );
@@ -294,40 +297,34 @@ THREE.GLTFLoader = ( function () {
 
 				case 'point':
 					lightNode = new THREE.PointLight( color );
+					lightNode.distance = range;
 					break;
 
 				case 'spot':
 					lightNode = new THREE.SpotLight( color );
+					lightNode.distance = range;
 					// 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.add( lightNode.target );
 					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
 	};
 
-	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 = {
 		1028: THREE.BackSide, // Culling front
 		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
 	 *
@@ -2014,22 +2018,6 @@ THREE.GLTFLoader = ( function () {
 
 			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 sampler = samplers[ textureDef.sampler ] || {};
 
@@ -2222,7 +2210,7 @@ THREE.GLTFLoader = ( function () {
 			if ( material.emissiveMap ) material.emissiveMap.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 );
 
@@ -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 ( meshDef.extras !== undefined ) mesh.userData = meshDef.extras;
+					assignExtrasToUserData( mesh, meshDef );
 
 					meshes.push( mesh );
 
@@ -2707,7 +2691,8 @@ THREE.GLTFLoader = ( function () {
 		}
 
 		if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
-		if ( cameraDef.extras ) camera.userData = cameraDef.extras;
+
+		assignExtrasToUserData( camera, cameraDef );
 
 		return Promise.resolve( camera );
 
@@ -2956,11 +2941,11 @@ THREE.GLTFLoader = ( function () {
 				node = dependencies.cameras[ nodeDef.camera ];
 
 			} 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 {
 
@@ -2974,7 +2959,7 @@ THREE.GLTFLoader = ( function () {
 
 			}
 
-			if ( nodeDef.extras ) node.userData = nodeDef.extras;
+			assignExtrasToUserData( node, nodeDef );
 
 			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
 
@@ -3108,7 +3093,7 @@ THREE.GLTFLoader = ( function () {
 				var scene = new THREE.Scene();
 				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 );
 
@@ -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;
 
 			} );

+ 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 ) {
 
-		var loader = new THREE.FileLoader( this.manager );
+		var loader = new THREE.FileLoader( scope.manager );
 		loader.setResponseType( 'arraybuffer' );
 		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
 			// 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'
 
 			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 zz85 / http://joshuakoo.com/
+ * @author yomboprime / https://yombo.org
  */
 
 THREE.SVGLoader = function ( manager ) {
@@ -32,6 +33,10 @@ THREE.SVGLoader.prototype = {
 
 			if ( node.nodeType !== 1 ) return;
 
+			var transform = getNodeTransform( node );
+
+			var path = null;
+
 			switch ( node.nodeName ) {
 
 				case 'svg':
@@ -43,37 +48,37 @@ THREE.SVGLoader.prototype = {
 
 				case 'path':
 					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;
 
 				case 'rect':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseRectNode( node, style ) );
+					if ( isVisible( style ) ) path = parseRectNode( node, style );
 					break;
 
 				case 'polygon':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parsePolygonNode( node, style ) );
+					if ( isVisible( style ) ) path = parsePolygonNode( node, style );
 					break;
 
 				case 'polyline':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parsePolylineNode( node, style ) );
+					if ( isVisible( style ) ) path = parsePolylineNode( node, style );
 					break;
 
 				case 'circle':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseCircleNode( node, style ) );
+					if ( isVisible( style ) ) path = parseCircleNode( node, style );
 					break;
 
 				case 'ellipse':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseEllipseNode( node, style ) );
+					if ( isVisible( style ) ) path = parseEllipseNode( node, style );
 					break;
 
 				case 'line':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseLineNode( node, style ) );
+					if ( isVisible( style ) ) path = parseLineNode( node, style );
 					break;
 
 				default:
@@ -81,6 +86,14 @@ THREE.SVGLoader.prototype = {
 
 			}
 
+			if ( path ) {
+
+				transformPath( path, currentTransform );
+
+				paths.push( path );
+
+			}
+
 			var nodes = node.childNodes;
 
 			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 ) {
@@ -99,6 +118,10 @@ THREE.SVGLoader.prototype = {
 			var point = new THREE.Vector2();
 			var control = new THREE.Vector2();
 
+			var firstPoint = new THREE.Vector2();
+			var isFirstPoint = true;
+			var doSetFirstPoint = false;
+
 			var d = node.getAttribute( 'd' );
 
 			// console.log( d );
@@ -112,6 +135,11 @@ THREE.SVGLoader.prototype = {
 				var type = command.charAt( 0 );
 				var data = command.substr( 1 ).trim();
 
+				if ( isFirstPoint ) {
+					doSetFirstPoint = true;
+				}
+				isFirstPoint = false;
+
 				switch ( type ) {
 
 					case 'M':
@@ -121,7 +149,11 @@ THREE.SVGLoader.prototype = {
 							point.y = numbers[ j + 1 ];
 							control.x = point.x;
 							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;
 
@@ -249,7 +281,11 @@ THREE.SVGLoader.prototype = {
 							point.y += numbers[ j + 1 ];
 							control.x = point.x;
 							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;
 
@@ -375,21 +411,9 @@ THREE.SVGLoader.prototype = {
 						path.currentPath.autoClose = true;
 						if ( path.currentPath.curves.length > 0 ) {
 							// 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 );
+							isFirstPoint = true;
 						}
 						break;
 
@@ -400,6 +424,13 @@ THREE.SVGLoader.prototype = {
 
 				// console.log( type, parseFloats( data ), parseFloats( data ).length  )
 
+				if ( doSetFirstPoint ) {
+
+					firstPoint.copy( point );
+
+					doSetFirstPoint = false;
+
+				}
 			}
 
 			return path;
@@ -503,7 +534,13 @@ THREE.SVGLoader.prototype = {
 			if ( rx !== 0 || ry !== 0 ) {
 
 				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 );
 
 			}
@@ -683,6 +720,252 @@ THREE.SVGLoader.prototype = {
 
 			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 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' );
 
 		var xml = new DOMParser().parseFromString( text, 'image/svg+xml' ); // application/xml
@@ -703,6 +994,7 @@ THREE.SVGLoader.prototype = {
 
 		// console.log( paths );
 
+
 		console.timeEnd( 'THREE.SVGLoader: Parse' );
 
 		return paths;

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

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

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

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

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

@@ -1,8 +1,8 @@
-import { 
+import {
 
 	// core
-	
-	GLNode,
+
+	Node,
 	TempNode,
 	InputNode,
 	ConstNode,
@@ -10,15 +10,16 @@ import {
 	StructNode,
 	AttributeNode,
 	FunctionNode,
+	ExpressionNode,
 	FunctionCallNode,
 	NodeLib,
 	NodeUtils,
 	NodeFrame,
 	NodeUniform,
 	NodeBuilder,
-	
+
 	// inputs
-	
+
 	IntNode,
 	FloatNode,
 	Vector2Node,
@@ -32,9 +33,10 @@ import {
 	ScreenNode,
 	ReflectorNode,
 	PropertyNode,
-	
+	RTTNode,
+
 	// accessors
-	
+
 	UVNode,
 	ColorsNode,
 	PositionNode,
@@ -44,33 +46,35 @@ import {
 	ReflectNode,
 	ScreenUVNode,
 	ResolutionNode,
-	
+
 	// math
-	
+
 	Math1Node,
 	Math2Node,
 	Math3Node,
 	OperatorNode,
-	
+	CondNode,
+
 	// procedural
-	
+
 	NoiseNode,
-	
+	CheckerNode,
+
 	// bsdfs
-	
+
 	BlinnShininessExponentNode,
 	BlinnExponentToRoughnessNode,
 	RoughnessToBlinnExponentNode,
-	
+
 	// misc
-	
+
 	TextureCubeUVNode,
 	TextureCubeNode,
 	NormalMapNode,
 	BumpMapNode,
-	
+
 	// utils
-	
+
 	BypassNode,
 	JoinNode,
 	SwitchNode,
@@ -78,34 +82,39 @@ import {
 	VelocityNode,
 	UVTransformNode,
 	MaxMIPLevelNode,
-	
+	ColorSpaceNode,
+
 	// effects
-	
+
 	BlurNode,
 	ColorAdjustmentNode,
 	LuminanceNode,
 
 	// material nodes
-	
+
 	RawNode,
 	SpriteNode,
 	PhongNode,
 	StandardNode,
 	MeshStandardNode,
-	
+
 	// materials
-	
+
 	NodeMaterial,
 	SpriteNodeMaterial,
 	PhongNodeMaterial,
 	StandardNodeMaterial,
-	MeshStandardNodeMaterial
-	
+	MeshStandardNodeMaterial,
+
+	// post-processing
+
+	NodePostProcessing
+
 } from './Nodes.js';
 
 // core
 
-THREE.GLNode = GLNode;
+THREE.Node = Node;
 THREE.TempNode = TempNode;
 THREE.InputNode = InputNode;
 THREE.ConstNode = ConstNode;
@@ -113,6 +122,7 @@ THREE.VarNode = VarNode;
 THREE.StructNode = StructNode;
 THREE.AttributeNode = AttributeNode;
 THREE.FunctionNode = FunctionNode;
+THREE.ExpressionNode = ExpressionNode;
 THREE.FunctionCallNode = FunctionCallNode;
 THREE.NodeLib = NodeLib;
 THREE.NodeUtils = NodeUtils;
@@ -135,6 +145,7 @@ THREE.CubeTextureNode = CubeTextureNode;
 THREE.ScreenNode = ScreenNode;
 THREE.ReflectorNode = ReflectorNode;
 THREE.PropertyNode = PropertyNode;
+THREE.RTTNode = RTTNode;
 
 // accessors
 
@@ -154,10 +165,12 @@ THREE.Math1Node = Math1Node;
 THREE.Math2Node = Math2Node;
 THREE.Math3Node = Math3Node;
 THREE.OperatorNode = OperatorNode;
+THREE.CondNode = CondNode;
 
 // procedural
 
 THREE.NoiseNode = NoiseNode;
+THREE.CheckerNode = CheckerNode;
 
 // bsdfs
 
@@ -181,6 +194,7 @@ THREE.TimerNode = TimerNode;
 THREE.VelocityNode = VelocityNode;
 THREE.UVTransformNode = UVTransformNode;
 THREE.MaxMIPLevelNode = MaxMIPLevelNode;
+THREE.ColorSpaceNode = ColorSpaceNode;
 
 // effects
 
@@ -203,3 +217,7 @@ THREE.SpriteNodeMaterial = SpriteNodeMaterial;
 THREE.PhongNodeMaterial = PhongNodeMaterial;
 THREE.StandardNodeMaterial = StandardNodeMaterial;
 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 { FloatNode } from '../inputs/FloatNode.js';
 import { PositionNode } from '../accessors/PositionNode.js';
- 
+
 function CameraNode( scope, camera ) {
 
 	TempNode.call( this, 'v3' );
@@ -14,33 +14,33 @@ function CameraNode( scope, camera ) {
 	this.setScope( scope || CameraNode.POSITION );
 	this.setCamera( camera );
 
-};
+}
+
+CameraNode.Nodes = ( function () {
 
-CameraNode.Nodes = (function() {
-	
 	var depthColor = new FunctionNode( [
 		"float depthColor( float mNear, float mFar ) {",
-		
+
 		"	#ifdef USE_LOGDEPTHBUF_EXT",
-		
+
 		"		float depth = gl_FragDepthEXT / gl_FragCoord.w;",
-		
+
 		"	#else",
-		
+
 		"		float depth = gl_FragCoord.z / gl_FragCoord.w;",
-		
+
 		"	#endif",
-		
+
 		"	return 1.0 - smoothstep( mNear, mFar, depth );",
-		
+
 		"}"
 	].join( "\n" ) );
-	
+
 	return {
 		depthColor: depthColor
 	};
-	
-})();
+
+} )();
 
 CameraNode.POSITION = 'position';
 CameraNode.DEPTH = 'depth';
@@ -92,7 +92,7 @@ CameraNode.prototype.getType = function ( builder ) {
 	switch ( this.scope ) {
 
 		case CameraNode.DEPTH:
-		
+
 			return 'f';
 
 	}
@@ -107,7 +107,7 @@ CameraNode.prototype.isUnique = function ( builder ) {
 
 		case CameraNode.DEPTH:
 		case CameraNode.TO_VERTEX:
-		
+
 			return true;
 
 	}
@@ -121,7 +121,7 @@ CameraNode.prototype.isShared = function ( builder ) {
 	switch ( this.scope ) {
 
 		case CameraNode.POSITION:
-		
+
 			return false;
 
 	}
@@ -180,15 +180,15 @@ CameraNode.prototype.onUpdateFrame = function ( frame ) {
 };
 
 CameraNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.setScope( source.scope );
 
 	if ( source.camera ) {
-		
+
 		this.setCamera( source.camera );
-		
+
 	}
 
 	switch ( source.scope ) {
@@ -201,7 +201,7 @@ CameraNode.prototype.copy = function ( source ) {
 			break;
 
 	}
-	
+
 };
 
 CameraNode.prototype.toJSON = function ( meta ) {

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

@@ -1,20 +1,19 @@
 /**
  * @author sunag / http://www.sunag.com.br/
  */
- 
+
 import { TempNode } from '../core/TempNode.js';
-import { NodeLib } from '../core/NodeLib.js';
- 
+
 var vertexDict = [ 'color', 'color2' ],
 	fragmentDict = [ 'vColor', 'vColor2' ];
- 
+
 function ColorsNode( index ) {
 
 	TempNode.call( this, 'v4', { shared: false } );
 
 	this.index = index || 0;
 
-};
+}
 
 ColorsNode.prototype = Object.create( TempNode.prototype );
 ColorsNode.prototype.constructor = ColorsNode;
@@ -30,11 +29,11 @@ ColorsNode.prototype.generate = function ( builder, output ) {
 };
 
 ColorsNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.index = source.index;
-	
+
 };
 
 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;
 
-};
+}
 
 LightNode.TOTAL = 'total';
 
@@ -22,24 +22,24 @@ LightNode.prototype.generate = function ( builder, output ) {
 
 	if ( builder.isCache( 'light' ) ) {
 
-		return builder.format( 'reflectedLight.directDiffuse', this.getType( builder ), output );
+		return builder.format( 'reflectedLight.directDiffuse', this.type, output );
 
 	} else {
 
 		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 ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.scope = source.scope;
-	
+
 };
 
 LightNode.prototype.toJSON = function ( meta ) {

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

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

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

@@ -4,14 +4,14 @@
 
 import { TempNode } from '../core/TempNode.js';
 import { NodeLib } from '../core/NodeLib.js';
- 
+
 function PositionNode( scope ) {
 
 	TempNode.call( this, 'v3' );
 
 	this.scope = scope || PositionNode.LOCAL;
 
-};
+}
 
 PositionNode.LOCAL = 'local';
 PositionNode.WORLD = 'world';
@@ -22,12 +22,12 @@ PositionNode.prototype = Object.create( TempNode.prototype );
 PositionNode.prototype.constructor = PositionNode;
 PositionNode.prototype.nodeType = "Position";
 
-PositionNode.prototype.getType = function ( builder ) {
+PositionNode.prototype.getType = function ( ) {
 
 	switch ( this.scope ) {
 
 		case PositionNode.PROJECTION:
-		
+
 			return 'v4';
 
 	}
@@ -42,7 +42,7 @@ PositionNode.prototype.isShared = function ( builder ) {
 
 		case PositionNode.LOCAL:
 		case PositionNode.WORLD:
-		
+
 			return false;
 
 	}
@@ -92,11 +92,11 @@ PositionNode.prototype.generate = function ( builder, output ) {
 };
 
 PositionNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.scope = source.scope;
-	
+
 };
 
 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;
 
-};
+}
 
 ReflectNode.CUBE = 'cube';
 ReflectNode.SPHERE = 'sphere';
@@ -37,7 +37,7 @@ ReflectNode.prototype.getType = function ( builder ) {
 ReflectNode.prototype.generate = function ( builder, output ) {
 
 	if ( builder.isShader( 'fragment' ) ) {
-		
+
 		var result;
 
 		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 {
-		
+
 		console.warn( "THREE.ReflectNode is not compatible with " + builder.shader + " shader." );
 
 		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';
- 
-function ResolutionNode( renderer ) {
 
-	Vector2Node.call( this );
+function ResolutionNode() {
 
-	this.renderer = renderer;
+	Vector2Node.call( this );
 
-};
+}
 
 ResolutionNode.prototype = Object.create( Vector2Node.prototype );
 ResolutionNode.prototype.constructor = ResolutionNode;
@@ -18,20 +16,28 @@ ResolutionNode.prototype.nodeType = "Resolution";
 
 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 ) {
-			
+
 	Vector2Node.prototype.copy.call( this, source );
-	
+
 	this.renderer = source.renderer;
-	
+
 };
 
 ResolutionNode.prototype.toJSON = function ( meta ) {

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

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

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

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

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

@@ -8,7 +8,7 @@ function BlinnShininessExponentNode() {
 
 	TempNode.call( this, 'f' );
 
-};
+}
 
 BlinnShininessExponentNode.prototype = Object.create( TempNode.prototype );
 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 { MaxMIPLevelNode } from '../utils/MaxMIPLevelNode.js';
 import { BlinnShininessExponentNode } from './BlinnShininessExponentNode.js';
- 
+
 function RoughnessToBlinnExponentNode( texture ) {
 
 	TempNode.call( this, 'f' );
@@ -16,9 +16,9 @@ function RoughnessToBlinnExponentNode( texture ) {
 	this.maxMIPLevel = new MaxMIPLevelNode( texture );
 	this.blinnShininessExponent = new BlinnShininessExponentNode();
 
-};
+}
 
-RoughnessToBlinnExponentNode.Nodes = (function() {
+RoughnessToBlinnExponentNode.Nodes = ( function () {
 
 	var getSpecularMIPLevel = new FunctionNode( [
 		// 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 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.
 		"	return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );",
+
 		"}"
 	].join( "\n" ) );
-	
+
 	return {
 		getSpecularMIPLevel: getSpecularMIPLevel
 	};
-	
-})();
+
+} )();
 
 RoughnessToBlinnExponentNode.prototype = Object.create( TempNode.prototype );
 RoughnessToBlinnExponentNode.prototype.constructor = RoughnessToBlinnExponentNode;
@@ -49,7 +50,7 @@ RoughnessToBlinnExponentNode.prototype.generate = function ( builder, output ) {
 	if ( builder.isShader( 'fragment' ) ) {
 
 		this.maxMIPLevel.texture = this.texture;
-	
+
 		var getSpecularMIPLevel = builder.include( RoughnessToBlinnExponentNode.Nodes.getSpecularMIPLevel );
 
 		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 ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.texture = source.texture;
-	
+
 };
 
 RoughnessToBlinnExponentNode.prototype.toJSON = function ( meta ) {

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

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

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

@@ -4,13 +4,15 @@
 
 import { TempNode } from './TempNode.js';
 
+var declarationRegexp = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=?\s?(.*?)(\;|$)/i;
+
 function ConstNode( src, useDefine ) {
 
 	TempNode.call( this );
 
 	this.eval( src || ConstNode.PI, useDefine );
 
-};
+}
 
 ConstNode.PI = 'PI';
 ConstNode.PI2 = 'PI2';
@@ -19,8 +21,6 @@ ConstNode.RECIPROCAL_PI2 = 'RECIPROCAL_PI2';
 ConstNode.LOG2 = 'LOG2';
 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.constructor = ConstNode;
 ConstNode.prototype.nodeType = "Const";
@@ -37,9 +37,9 @@ ConstNode.prototype.eval = function ( src, useDefine ) {
 
 	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 ) {
 
@@ -74,10 +74,10 @@ ConstNode.prototype.build = function ( builder, output ) {
 
 			return 'const ' + this.type + ' ' + this.name + ' = ' + this.value + ';';
 
-		} else if (this.useDefine) {
-		
+		} else if ( this.useDefine ) {
+
 			return this.src;
-			
+
 		}
 
 	} else {
@@ -97,11 +97,11 @@ ConstNode.prototype.generate = function ( builder, output ) {
 };
 
 ConstNode.prototype.copy = function ( source ) {
-	
+
 	TempNode.prototype.copy.call( this, source );
-	
-	this.eval( source.src, source.useDefine );	
-	
+
+	this.eval( source.src, source.useDefine );
+
 };
 
 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';
- 
+
 function FunctionCallNode( func, inputs ) {
 
 	TempNode.call( this );
 
 	this.setFunction( func, inputs );
 
-};
+}
 
 FunctionCallNode.prototype = Object.create( TempNode.prototype );
 FunctionCallNode.prototype.constructor = FunctionCallNode;
@@ -59,9 +59,9 @@ FunctionCallNode.prototype.generate = function ( builder, output ) {
 };
 
 FunctionCallNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	for ( var prop in source.inputs ) {
 
 		this.inputs[ prop ] = source.inputs[ prop ];
@@ -69,7 +69,7 @@ FunctionCallNode.prototype.copy = function ( source ) {
 	}
 
 	this.value = source.value;
-	
+
 };
 
 FunctionCallNode.prototype.toJSON = function ( meta ) {

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

@@ -6,32 +6,25 @@
 import { TempNode } from './TempNode.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.constructor = FunctionNode;
 FunctionNode.prototype.nodeType = "Function";
 
+FunctionNode.prototype.useKeywords = true;
+
 FunctionNode.prototype.isShared = function ( builder, output ) {
 
 	return ! this.isMethod;
@@ -50,9 +43,12 @@ FunctionNode.prototype.getInputByName = function ( name ) {
 
 	while ( i -- ) {
 
-		if ( this.inputs[ i ].name === name )
+		if ( this.inputs[ i ].name === name ) {
+
 			return this.inputs[ i ];
 
+		}
+
 	}
 
 };
@@ -63,9 +59,12 @@ FunctionNode.prototype.getIncludeByName = function ( name ) {
 
 	while ( i -- ) {
 
-		if ( this.includes[ i ].name === name )
+		if ( this.includes[ i ].name === name ) {
+
 			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,
 			reference = prop;
 
@@ -156,7 +155,7 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
 
 	if ( this.isMethod ) {
 
-		var match = this.src.match( FunctionNode.rDeclaration );
+		var match = this.src.match( declarationRegexp );
 
 		this.inputs = [];
 
@@ -165,7 +164,7 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
 			this.type = match[ 1 ];
 			this.name = match[ 2 ];
 
-			var inputs = match[ 3 ].match( FunctionNode.rProperties );
+			var inputs = match[ 3 ].match( propertiesRegexp );
 
 			if ( inputs ) {
 
@@ -211,16 +210,16 @@ FunctionNode.prototype.eval = function ( src, includes, extensions, keywords ) {
 };
 
 FunctionNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.isMethod = source.isMethod;
 	this.useKeywords = source.useKeywords;
-	
+
 	this.eval( source.src, source.includes, source.extensions, source.keywords );
 
 	if ( source.type !== undefined ) this.type = source.type;
-	
+
 };
 
 FunctionNode.prototype.toJSON = function ( meta ) {

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

@@ -13,7 +13,7 @@ function InputNode( type, params ) {
 
 	this.readonly = false;
 
-};
+}
 
 InputNode.prototype = Object.create( TempNode.prototype );
 InputNode.prototype.constructor = InputNode;
@@ -25,17 +25,17 @@ InputNode.prototype.isReadonly = function ( builder ) {
 };
 
 InputNode.prototype.copy = function ( source ) {
-	
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	if ( source.readonly !== undefined ) this.readonly = source.readonly;
-	
+
 };
 
 InputNode.prototype.createJSONNode = function ( meta ) {
 
 	var data = TempNode.prototype.createJSONNode.call( this, meta );
-	
+
 	if ( this.readonly === true ) data.readonly = this.readonly;
 
 	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/
  */
 
-function GLNode( type ) {
+function Node( type ) {
 
 	this.uuid = THREE.Math.generateUUID();
 
@@ -12,31 +12,31 @@ function GLNode( type ) {
 
 	this.userData = {};
 
-};
+}
+
+Node.prototype = {
 
-GLNode.prototype = {
+	constructor: Node,
 
-	constructor: GLNode,
-	
 	isNode: true,
-	
+
 	parse: function ( builder, settings ) {
 
 		settings = settings || {};
 
 		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.removeCache().removeSlot();
+		builder.removeFlow();
 
 		builder.parsing = false;
 
 	},
-	
+
 	parseAndBuildCode: function ( builder, output, settings ) {
 
 		settings = settings || {};
@@ -44,21 +44,21 @@ GLNode.prototype = {
 		this.parse( builder, settings );
 
 		return this.buildCode( builder, output, settings );
-	
+
 	},
-	
+
 	buildCode: function ( builder, output, 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();
 
-		builder.removeCache().removeSlot();
+		builder.removeFlow();
 
 		return data;
-	
+
 	},
 
 	build: function ( builder, output, uuid ) {
@@ -67,7 +67,11 @@ GLNode.prototype = {
 
 		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 ) {
 
@@ -82,9 +86,9 @@ GLNode.prototype = {
 		}
 
 		return this.generate( builder, output, uuid );
-	
+
 	},
-	
+
 	appendDepsNode: function ( builder, data, output ) {
 
 		data.deps = ( data.deps || 0 ) + 1;
@@ -97,29 +101,29 @@ GLNode.prototype = {
 			data.output = output;
 
 		}
-	
+
 	},
-	
-	setName: function( name ) {
-		
+
+	setName: function ( name ) {
+
 		this.name = name;
-		
+
 		return this;
-		
+
 	},
-	
-	getName: function( builder ) {
-		
+
+	getName: function ( builder ) {
+
 		return this.name;
-		
+
 	},
-	
+
 	getType: function ( builder, output ) {
 
 		return output === 'sampler2D' || output === 'samplerCube' ? output : this.type;
-	
+
 	},
-	
+
 	getJSONNode: function ( meta ) {
 
 		var isRootObject = ( meta === undefined || typeof meta === 'string' );
@@ -129,17 +133,17 @@ GLNode.prototype = {
 			return meta.nodes[ this.uuid ];
 
 		}
-	
+
 	},
-	
+
 	copy: function ( source ) {
 
 		if ( source.name !== undefined ) this.name = source.name;
-	
+
 		if ( source.userData !== undefined ) this.userData = JSON.parse( JSON.stringify( source.userData ) );
-	
+
 	},
-	
+
 	createJSONNode: function ( meta ) {
 
 		var isRootObject = ( meta === undefined || typeof meta === 'string' );
@@ -162,15 +166,15 @@ GLNode.prototype = {
 		}
 
 		return data;
-	
+
 	},
-	
+
 	toJSON: function ( 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',
 		m4: 'mat4'
 	};
- 
+
 function NodeBuilder() {
 
-	this.caches = [];
 	this.slots = [];
+	this.caches = [];
+	this.contexts = [];
 
 	this.keywords = {};
-	
+
 	this.nodeData = {};
-	
+
 	this.requires = {
 		uv: [],
 		color: [],
@@ -59,11 +60,11 @@ function NodeBuilder() {
 		functions: [],
 		structs: []
 	};
-	
+
 	this.attributes = {};
-	
+
 	this.prefixCode = [
-		"#ifdef GL_EXT_shader_texture_lod",
+		"#ifdef TEXTURE_LOD_EXT",
 
 		"	#define texCube(a, b) textureCube(a, b)",
 		"	#define texCubeBias(a, b, c) textureCubeLodEXT(a, b, c)",
@@ -81,35 +82,36 @@ function NodeBuilder() {
 
 		"#endif",
 
-		"#include <packing>"
+		"#include <packing>",
+		"#include <common>"
 
 	].join( "\n" );
-	
+
 	this.parsCode = {
 		vertex: '',
 		fragment: ''
 	};
-	
+
 	this.code = {
 		vertex: '',
 		fragment: ''
 	};
-	
+
 	this.nodeCode = {
 		vertex: '',
 		fragment: ''
 	};
-	
+
 	this.resultCode = {
 		vertex: '',
 		fragment: ''
 	};
-	
+
 	this.finalCode = {
 		vertex: '',
 		fragment: ''
 	};
-	
+
 	this.inputs = {
 		uniforms: {
 			list: [],
@@ -122,45 +124,43 @@ function NodeBuilder() {
 			fragment: []
 		}
 	};
-	
+
 	// send to material
-	
+
 	this.defines = {};
-	
+
 	this.uniforms = {};
-	
+
 	this.extensions = {};
-	
+
 	this.updaters = [];
-	
+
 	this.nodes = [];
-	
+
 	// --
-	
+
 	this.parsing = false;
 	this.optimize = true;
 
-	this.update();
-
-};
+}
 
 NodeBuilder.prototype = {
 
 	constructor: NodeBuilder,
 
-	build: function( vertex, fragment ) {
-		
+	build: function ( vertex, fragment ) {
+
 		this.buildShader( 'vertex', vertex );
 		this.buildShader( 'fragment', fragment );
-		
+
 		if ( this.requires.uv[ 0 ] ) {
 
 			this.addVaryCode( 'varying vec2 vUv;' );
-		
+
 			this.addVertexFinalCode( 'vUv = uv;' );
 
 		}
-		
+
 		if ( this.requires.uv[ 1 ] ) {
 
 			this.addVaryCode( 'varying vec2 vUv2;' );
@@ -169,7 +169,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vUv2 = uv2;' );
 
 		}
-		
+
 		if ( this.requires.color[ 0 ] ) {
 
 			this.addVaryCode( 'varying vec4 vColor;' );
@@ -178,7 +178,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vColor = color;' );
 
 		}
-		
+
 		if ( this.requires.color[ 1 ] ) {
 
 			this.addVaryCode( 'varying vec4 vColor2;' );
@@ -187,7 +187,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vColor2 = color2;' );
 
 		}
-		
+
 		if ( this.requires.position ) {
 
 			this.addVaryCode( 'varying vec3 vPosition;' );
@@ -195,15 +195,15 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vPosition = transformed;' );
 
 		}
-		
+
 		if ( this.requires.worldPosition ) {
 
 			this.addVaryCode( 'varying vec3 vWPosition;' );
-			
+
 			this.addVertexFinalCode( 'vWPosition = ( modelMatrix * vec4( transformed, 1.0 ) ).xyz;' );
 
 		}
-		
+
 		if ( this.requires.normal ) {
 
 			this.addVaryCode( 'varying vec3 vObjectNormal;' );
@@ -211,7 +211,7 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vObjectNormal = normal;' );
 
 		}
-		
+
 		if ( this.requires.worldNormal ) {
 
 			this.addVaryCode( 'varying vec3 vWNormal;' );
@@ -219,67 +219,98 @@ NodeBuilder.prototype = {
 			this.addVertexFinalCode( 'vWNormal = ( modelMatrix * vec4( objectNormal, 0.0 ) ).xyz;' );
 
 		}
-		
+
 		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.renderer = renderer;
-		
+
 		this.requires.lights = material.lights;
 		this.requires.fog = material.fog;
-		
+
+		this.mergeDefines( material.defines );
+
 		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 () {
 
 		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 ) {
 
-		this.slots.push( {
-			name: name || ''
-		} );
+		this.slot = name || '';
+		this.slots.push( this.slot );
 
-		return this.update();
+		return this;
 
 	},
 
 	removeSlot: function () {
 
 		this.slots.pop();
+		this.slot = this.slots[ this.slots.length - 1 ] || '';
 
-		return this.update();
+		return this;
 
 	},
 
-	
+
 	addVertexCode: function ( code ) {
 
 		this.addCode( code, 'vertex' );
@@ -291,14 +322,14 @@ NodeBuilder.prototype = {
 		this.addCode( code, 'fragment' );
 
 	},
-	
+
 	addCode: function ( code, shader ) {
 
-		this.code[shader || this.shader] += code + '\n';
+		this.code[ shader || this.shader ] += code + '\n';
 
 	},
-	
-	
+
+
 	addVertexNodeCode: function ( code ) {
 
 		this.addNodeCode( code, 'vertex' );
@@ -310,37 +341,37 @@ NodeBuilder.prototype = {
 		this.addNodeCode( code, 'fragment' );
 
 	},
-	
+
 	addNodeCode: function ( code, shader ) {
 
-		this.nodeCode[shader || this.shader] += code + '\n';
+		this.nodeCode[ shader || this.shader ] += code + '\n';
 
 	},
-	
+
 	clearNodeCode: function ( shader ) {
 
 		shader = shader || this.shader;
-	
-		var code = this.nodeCode[shader];
-		
-		this.nodeCode[shader] = '';
+
+		var code = this.nodeCode[ shader ];
+
+		this.nodeCode[ shader ] = '';
 
 		return code;
-		
+
 	},
-	
-	clearVertexNodeCode: function (  ) {
+
+	clearVertexNodeCode: function ( ) {
 
 		return this.clearNodeCode( 'vertex' );
 
 	},
-	
-	clearFragmentNodeCode: function (  ) {
+
+	clearFragmentNodeCode: function ( ) {
 
 		return this.clearNodeCode( 'fragment' );
 
 	},
-	
+
 	addVertexFinalCode: function ( code ) {
 
 		this.addFinalCode( code, 'vertex' );
@@ -352,79 +383,50 @@ NodeBuilder.prototype = {
 		this.addFinalCode( code, 'fragment' );
 
 	},
-	
+
 	addFinalCode: function ( code, shader ) {
 
-		this.finalCode[shader || this.shader] += code + '\n';
+		this.finalCode[ shader || this.shader ] += code + '\n';
 
 	},
-	
-	
+
+
 	addVertexParsCode: function ( code ) {
 
 		this.addParsCode( code, 'vertex' );
 
 	},
-	
+
 	addFragmentParsCode: function ( code ) {
 
 		this.addParsCode( code, 'fragment' );
 
 	},
-	
+
 	addParsCode: function ( code, shader ) {
 
-		this.parsCode[shader || this.shader] += code + '\n';
+		this.parsCode[ shader || this.shader ] += code + '\n';
 
 	},
-	
-	
+
+
 	addVaryCode: function ( code ) {
 
 		this.addVertexParsCode( 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 ) {
 
-		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;
 
 	},
-	
+
 	isDefined: function ( name ) {
 
 		return this.defines[ name ] !== undefined;
@@ -443,8 +445,8 @@ NodeBuilder.prototype = {
 	getVar: function ( uuid, type, ns, shader ) {
 
 		shader = shader || 'varying';
-	
-		var vars = this.getVars(shader),
+
+		var vars = this.getVars( shader ),
 			data = vars[ uuid ];
 
 		if ( ! data ) {
@@ -462,13 +464,13 @@ NodeBuilder.prototype = {
 		return data;
 
 	},
-	
+
 	getTempVar: function ( uuid, type, ns ) {
 
 		return this.getVar( uuid, type, ns, this.shader );
 
 	},
-	
+
 	getAttribute: function ( name, type ) {
 
 		if ( ! this.attributes[ name ] ) {
@@ -485,45 +487,45 @@ NodeBuilder.prototype = {
 		return this.attributes[ name ];
 
 	},
-	
-	getCode: function( shader ) {
-		
+
+	getCode: function ( shader ) {
+
 		return [
 			this.prefixCode,
 			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( 'structs', shader ),
 			this.getIncludesCode( 'functions', shader ),
 			'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" );
-		
+
 	},
-	
+
 	getVarListCode: function ( vars, prefix ) {
 
 		prefix = prefix || '';
-	
+
 		var code = '';
 
 		for ( var i = 0, l = vars.length; i < l; ++ i ) {
 
-			var nVar = vars[i],
+			var nVar = vars[ i ],
 				type = nVar.type,
 				name = nVar.name;
-			
+
 			var formatType = this.getFormatByType( type );
 
 			if ( formatType === undefined ) {
-				
+
 				throw new Error( "Node pars " + formatType + " not found." );
-				
+
 			}
 
 			code += prefix + ' ' + formatType + ' ' + name + ';\n';
@@ -533,21 +535,21 @@ NodeBuilder.prototype = {
 		return code;
 
 	},
-	
+
 	getVars: function ( shader ) {
 
 		return this.inputs.vars[ shader || this.shader ];
 
 	},
-	
+
 	getNodeData: function ( node ) {
 
 		var uuid = node.isNode ? node.uuid : node;
-	
+
 		return this.nodeData[ uuid ] = this.nodeData[ uuid ] || {};
 
 	},
-	
+
 	createUniform: function ( shader, type, node, ns, needsUpdate ) {
 
 		var uniforms = this.inputs.uniforms,
@@ -555,40 +557,47 @@ NodeBuilder.prototype = {
 
 		var uniform = new NodeUniform( {
 			type: type,
-			name: ns ? ns : 'nVu' + index + '_' + THREE.Math.generateUUID().substr(0, 8),
+			name: ns ? ns : 'nVu' + index,
 			node: node,
 			needsUpdate: needsUpdate
 		} );
 
 		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;
-		
+
 		return uniform;
 
 	},
-	
+
 	createVertexUniform: function ( type, node, ns, needsUpdate ) {
 
 		return this.createUniform( 'vertex', type, node, ns, needsUpdate );
 
 	},
-	
+
 	createFragmentUniform: function ( type, node, ns, needsUpdate ) {
 
 		return this.createUniform( 'fragment', type, node, ns, needsUpdate );
 
 	},
-	
+
 	include: function ( node, parent, source ) {
 
 		var includesStruct;
 
 		node = typeof node === 'string' ? NodeLib.get( node ) : node;
 
+		if ( this.context.include === false ) {
+
+			return node.name;
+
+		}
+
+
 		if ( node instanceof FunctionNode ) {
 
 			includesStruct = this.includes.functions;
@@ -596,17 +605,17 @@ NodeBuilder.prototype = {
 		} else if ( node instanceof ConstNode ) {
 
 			includesStruct = this.includes.consts;
-			
+
 		} else if ( node instanceof StructNode ) {
 
 			includesStruct = this.includes.structs;
 
 		}
-		
+
 		var includes = includesStruct[ this.shader ] = includesStruct[ this.shader ] || [];
 
-		if (node) {
-		
+		if ( node ) {
+
 			var included = includes[ node.name ];
 
 			if ( ! included ) {
@@ -645,13 +654,13 @@ NodeBuilder.prototype = {
 				included.src = source;
 
 			}
-			
+
 			return node.name;
-			
+
 		} 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' );
 
 	},
-	
+
 	colorToVector: function ( color ) {
 
 		return color.replace( /c/g, 'v3' );
@@ -670,10 +679,10 @@ NodeBuilder.prototype = {
 
 	getIncludes: function ( type, shader ) {
 
-		return this.includes[type][shader || this.shader];
+		return this.includes[ type ][ shader || this.shader ];
 
 	},
-	
+
 	getIncludesCode: function () {
 
 		function sortByPosition( a, b ) {
@@ -685,10 +694,10 @@ NodeBuilder.prototype = {
 		return function getIncludesCode( type, shader ) {
 
 			var includes = this.getIncludes( type, shader );
-	
+
 			if ( ! includes ) return '';
 
-			var code = '', 
+			var code = '',
 				includes = includes.sort( sortByPosition );
 
 			for ( var i = 0; i < includes.length; i ++ ) {
@@ -702,7 +711,7 @@ NodeBuilder.prototype = {
 		};
 
 	}(),
-	
+
 	getConstructorFromLength: function ( len ) {
 
 		return constructors[ len - 1 ];
@@ -718,7 +727,7 @@ NodeBuilder.prototype = {
 	getTypeLength: function ( type ) {
 
 		if ( type === 'f' ) return 1;
-	
+
 		return parseInt( this.colorToVector( type ).substr( 1 ) );
 
 	},
@@ -730,109 +739,109 @@ NodeBuilder.prototype = {
 		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;
-				
+
 			}
-			
+
 		}
-		
-	},
-	
-	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;
-					
-				} else if (nodeCandidate.isTexture) {
-					
-					switch( nodeCandidate.mapping ) {
-					
+
+				} else if ( nodeCandidate.isTexture ) {
+
+					switch ( nodeCandidate.mapping ) {
+
 						case THREE.CubeReflectionMapping:
 						case THREE.CubeRefractionMapping:
 
 							return new CubeTextureNode( nodeCandidate );
 
 							break;
-						
+
 						case THREE.CubeUVReflectionMapping:
 						case THREE.CubeUVRefractionMapping:
 
 							return new TextureCubeNode( new TextureNode( nodeCandidate ) );
 
 							break;
-							
+
 						default:
-						
+
 							return new TextureNode( nodeCandidate );
-						
+
 					}
-					
-				} else if (nodeCandidate.isVector2) {
-					
+
+				} else if ( nodeCandidate.isVector2 ) {
+
 					return new Vector2Node( nodeCandidate );
-					
-				} else if (nodeCandidate.isVector3) {
-					
+
+				} else if ( nodeCandidate.isVector3 ) {
+
 					return new Vector3Node( nodeCandidate );
-					
-				} else if (nodeCandidate.isVector4) {
-					
+
+				} else if ( nodeCandidate.isVector4 ) {
+
 					return new Vector4Node( nodeCandidate );
-					
+
 				}
-				
+
 			}
-			
+
 		}
-		
+
 	},
 
 	format: function ( code, from, to ) {
 
-		var typeToType = this.colorToVector( to + ' = ' + from );
+		var typeToType = this.colorToVector( to + ' <- ' + from );
 
 		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;
 
 	},
-	
+
 	getFormatByType: function ( type ) {
 
 		return convertTypeToFormat[ type ] || type;
@@ -887,93 +896,35 @@ NodeBuilder.prototype = {
 		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 ) {
 
+		gammaOverrideLinear = gammaOverrideLinear !== undefined ? gammaOverrideLinear : this.context.gamma && ( this.renderer ? this.renderer.gammaInput : false );
+
 		var encoding;
 
 		if ( ! map ) {

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

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

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

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

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

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

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

@@ -3,18 +3,17 @@
  */
 
 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 ) {
 
-	TempNode.call( this);
+	TempNode.call( this );
 
 	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.constructor = StructNode;
@@ -32,9 +31,12 @@ StructNode.prototype.getInputByName = function ( name ) {
 
 	while ( i -- ) {
 
-		if ( this.inputs[ i ].name === name )
+		if ( this.inputs[ i ].name === name ) {
+
 			return this.inputs[ i ];
 
+		}
+
 	}
 
 };
@@ -47,7 +49,7 @@ StructNode.prototype.generate = function ( builder, output ) {
 
 	} 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 ) {
 
 	this.src = src || '';
-	
+
 	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( {
-				name: matchName,
-				type: matchType
+				type: match[ 1 ],
+				name: match[ 2 ]
 			} );
-			
+
 		}
-		
-		this.name = declaration[1];
+
+		this.name = declaration[ 1 ];
 
 	} else {
-		
+
 		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/
  */
 
-import { GLNode } from './GLNode.js';
+import { Node } from './Node.js';
 
 function TempNode( type, params ) {
 
-	GLNode.call( this, type );
+	Node.call( this, type );
 
 	params = params || {};
 
 	this.shared = params.shared !== undefined ? params.shared : true;
 	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.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 );
 
-		var data = builder.getNodeData( uuid );
+		var data = builder.getNodeData( uuid ),
+			type = data.output || this.getType( builder );
 
 		if ( builder.parsing ) {
 
-			if ( data.deps || 0 > 0 ) {
+			if ( ( data.deps || 0 ) > 0 ) {
 
 				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 ) {
 
-			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;
 
-		} 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 );
 
-		var name = this.getTemp( builder, uuid ),
-			type = data.output || this.getType( builder );
+		var name = this.getTemp( builder, uuid );
 
 		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;
 
-	var tempVar = builder.getVars()[uuid]
-	
+	var tempVar = builder.getVars()[ uuid ];
+
 	return tempVar ? tempVar.name : undefined;
-	
+
 };
 
 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/
  */
 
-import { GLNode } from './GLNode.js';
+import { Node } from './Node.js';
 
 function VarNode( type, value ) {
 
-	GLNode.call( this, type );
-	
+	Node.call( this, type );
+
 	this.value = value;
 
-};
+}
 
-VarNode.prototype = Object.create( GLNode.prototype );
+VarNode.prototype = Object.create( Node.prototype );
 VarNode.prototype.constructor = VarNode;
 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 ) ) + ';' );
 
 	}
-	
+
 	return builder.format( varying.name, this.getType( builder ), output );
 
 };
 
 VarNode.prototype.copy = function ( source ) {
-	
-	GLNode.prototype.copy.call( this, source );
-	
+
+	Node.prototype.copy.call( this, source );
+
 	this.type = source.type;
 	this.value = source.value;
-	
+
 };
 
 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.vertical = new FloatNode( 1 / 64 );
 
-};
+}
+
+BlurNode.Nodes = ( function () {
 
-BlurNode.Nodes = (function() {
-	
 	var blurX = new FunctionNode( [
 		"vec4 blurX( sampler2D texture, vec2 uv, float s ) {",
 		"	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 + 3.0 * s, uv.y ) ) * 0.0918;",
 		"	sum += texture2D( texture, vec2( uv.x + 4.0 * s, uv.y ) ) * 0.051;",
-		"	return sum;",
+		"	return sum * .667;",
 		"}"
 	].join( "\n" ) );
-	
+
 	var blurY = new FunctionNode( [
 		"vec4 blurY( sampler2D texture, vec2 uv, float s ) {",
 		"	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 + 3.0 * s ) ) * 0.0918;",
 		"	sum += texture2D( texture, vec2( uv.x, uv.y + 4.0 * s ) ) * 0.051;",
-		"	return sum;",
+		"	return sum * .667;",
 		"}"
 	].join( "\n" ) );
-	
+
 	return {
 		blurX: blurX,
 		blurY: blurY
 	};
-	
-})();
+
+} )();
 
 
 BlurNode.prototype = Object.create( TempNode.prototype );
@@ -98,7 +98,7 @@ BlurNode.prototype.generate = function ( builder, output ) {
 
 		var blurX = builder.include( BlurNode.Nodes.blurX ),
 			blurY = builder.include( BlurNode.Nodes.blurY );
-		
+
 		if ( this.blurX ) {
 
 			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 code = 'vec4( 0.0 )';
 
@@ -128,9 +128,9 @@ BlurNode.prototype.generate = function ( builder, output ) {
 };
 
 BlurNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.value = source.value;
 	this.uv = source.uv;
 	this.radius = source.radius;
@@ -139,7 +139,7 @@ BlurNode.prototype.copy = function ( source ) {
 
 	this.blurX = source.blurX;
 	this.blurY = source.blurY;
-					
+
 };
 
 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;
 
-};
+}
+
+ColorAdjustmentNode.Nodes = ( function () {
 
-ColorAdjustmentNode.Nodes = (function() {
-	
 	var hue = new FunctionNode( [
 		"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 YIQtoRGB = mat3(1.0, 0.9563, 0.6210, 1.0, -0.2721, -0.6474, 1.0, -1.107, 1.7046);",
-		
+
 		"	vec3 yiq = RGBtoYIQ * rgb;",
-		
+
 		"	float hue = atan(yiq.z, yiq.y) + adjustment;",
 		"	float chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);",
-		
+
 		"	return YIQtoRGB * vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));",
-		
+
 		"}"
 	].join( "\n" ) );
-	
+
 	var saturation = new FunctionNode( [
 		// Algorithm from Chapter 16 of OpenGL Shading Language
 		"vec3 saturation(vec3 rgb, float adjustment) {",
-		
+
 		"	vec3 intensity = vec3( luminance( rgb ) );",
-		
+
 		"	return mix( intensity, rgb, adjustment );",
-		
+
 		"}"
 	].join( "\n" ), [ LuminanceNode.Nodes.luminance ] ); // include LuminanceNode function
-	
+
 	var vibrance = new FunctionNode( [
 		// Shader by Evan Wallace adapted by @lo-th
 		"vec3 vibrance(vec3 rgb, float adjustment) {",
-		
+
 		"	float average = (rgb.r + rgb.g + rgb.b) / 3.0;",
-		
+
 		"	float mx = max(rgb.r, max(rgb.g, rgb.b));",
 		"	float amt = (mx - average) * (-3.0 * adjustment);",
-		
+
 		"	return mix(rgb.rgb, vec3(mx), amt);",
-		
+
 		"}"
 	].join( "\n" ) );
-	
+
 	return {
 		hue: hue,
 		saturation: saturation,
 		vibrance: vibrance
 	};
-	
-})();
+
+} )();
 
 ColorAdjustmentNode.SATURATION = 'saturation';
 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 );
 
 };
 
 ColorAdjustmentNode.prototype.copy = function ( source ) {
-			
+
 	TempNode.prototype.copy.call( this, source );
-	
+
 	this.rgb = source.rgb;
 	this.adjustment = source.adjustment;
 	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