Browse Source

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

gogoend 6 years ago
parent
commit
4ecf337ec7
100 changed files with 1760 additions and 833 deletions
  1. 1 1
      .github/ISSUE_TEMPLATE.md
  2. 0 1
      .npmignore
  3. 4 4
      build/three.js
  4. 287 411
      build/three.min.js
  5. 2 2
      build/three.module.js
  6. 5 0
      docs/api/en/animation/AnimationClip.html
  7. 5 0
      docs/api/en/animation/KeyframeTrack.html
  8. 1 1
      docs/api/en/audio/Audio.html
  9. 1 1
      docs/api/en/audio/AudioAnalyser.html
  10. 4 4
      docs/api/en/audio/AudioListener.html
  11. 2 2
      docs/api/en/audio/PositionalAudio.html
  12. 1 0
      docs/api/en/constants/Renderer.html
  13. 1 1
      docs/api/en/core/Object3D.html
  14. 4 1
      docs/api/en/extras/core/ShapePath.html
  15. 73 0
      docs/api/en/helpers/PositionalAudioHelper.html
  16. 7 0
      docs/api/en/materials/Material.html
  17. 2 2
      docs/api/en/objects/SkinnedMesh.html
  18. 35 16
      docs/api/en/renderers/WebGLRenderer.html
  19. 10 2
      docs/api/en/textures/DataTexture3D.html
  20. 3 0
      docs/api/zh/animation/AnimationClip.html
  21. 6 0
      docs/api/zh/animation/AnimationUtils.html
  22. 3 0
      docs/api/zh/animation/KeyframeTrack.html
  23. 1 1
      docs/api/zh/audio/Audio.html
  24. 1 1
      docs/api/zh/audio/AudioAnalyser.html
  25. 4 4
      docs/api/zh/audio/AudioListener.html
  26. 2 2
      docs/api/zh/audio/PositionalAudio.html
  27. 1 1
      docs/api/zh/core/Object3D.html
  28. 73 0
      docs/api/zh/helpers/PositionalAudioHelper.html
  29. 4 0
      docs/api/zh/materials/Material.html
  30. 1 0
      docs/examples/exporters/GLTFExporter.html
  31. 15 0
      docs/index.html
  32. 4 0
      docs/list.js
  33. 126 0
      docs/manual/en/introduction/How-to-dispose-of-objects.html
  34. 4 0
      docs/manual/en/introduction/Useful-links.html
  35. 20 0
      docs/manual/zh/introduction/How-to-dispose-of-objects.html
  36. 2 4
      editor/index.html
  37. 5 5
      editor/js/libs/ui.js
  38. 1 0
      examples/files.js
  39. 8 2
      examples/js/GPUComputationRenderer.js
  40. 39 14
      examples/js/Ocean.js
  41. 11 2
      examples/js/cameras/CinematicCamera.js
  42. 87 45
      examples/js/controls/FirstPersonControls.js
  43. 24 5
      examples/js/controls/OrbitControls.js
  44. 0 14
      examples/js/controls/TransformControls.js
  45. 11 3
      examples/js/crossfade/scenes.js
  46. 4 2
      examples/js/crossfade/transition.js
  47. 13 2
      examples/js/effects/AnaglyphEffect.js
  48. 26 6
      examples/js/effects/OutlineEffect.js
  49. 9 2
      examples/js/effects/ParallaxBarrierEffect.js
  50. 2 1
      examples/js/effects/StereoEffect.js
  51. 10 5
      examples/js/exporters/ColladaExporter.js
  52. 280 25
      examples/js/exporters/GLTFExporter.js
  53. 7 3
      examples/js/loaders/AssimpJSONLoader.js
  54. 1 1
      examples/js/loaders/ColladaLoader.js
  55. 14 4
      examples/js/loaders/EquirectangularToCubeGenerator.js
  56. 1 0
      examples/js/loaders/FBXLoader.js
  57. 26 13
      examples/js/loaders/GLTFLoader.js
  58. 57 67
      examples/js/loaders/LDrawLoader.js
  59. 19 4
      examples/js/loaders/SVGLoader.js
  60. 23 19
      examples/js/loaders/deprecated/LegacyGLTFLoader.js
  61. 1 0
      examples/js/nodes/Nodes.js
  62. 2 0
      examples/js/nodes/THREE.Nodes.js
  63. 2 2
      examples/js/nodes/accessors/CameraNode.js
  64. 1 1
      examples/js/nodes/accessors/NormalNode.js
  65. 1 1
      examples/js/nodes/accessors/PositionNode.js
  66. 1 1
      examples/js/nodes/core/FunctionNode.js
  67. 12 4
      examples/js/nodes/core/InputNode.js
  68. 28 18
      examples/js/nodes/core/NodeBuilder.js
  69. 23 9
      examples/js/nodes/core/TempNode.js
  70. 51 0
      examples/js/nodes/inputs/BoolNode.js
  71. 6 2
      examples/js/nodes/inputs/RTTNode.js
  72. 1 1
      examples/js/nodes/inputs/ScreenNode.js
  73. 1 0
      examples/js/nodes/materials/PhongNodeMaterial.js
  74. 1 0
      examples/js/nodes/materials/SpriteNodeMaterial.js
  75. 1 0
      examples/js/nodes/materials/StandardNodeMaterial.js
  76. 21 2
      examples/js/nodes/materials/nodes/PhongNode.js
  77. 23 6
      examples/js/nodes/materials/nodes/SpriteNode.js
  78. 22 3
      examples/js/nodes/materials/nodes/StandardNode.js
  79. 35 16
      examples/js/nodes/math/CondNode.js
  80. 4 2
      examples/js/nodes/postprocessing/NodePostProcessing.js
  81. 2 2
      examples/js/nodes/utils/ColorSpaceNode.js
  82. 3 3
      examples/js/nodes/utils/TimerNode.js
  83. 1 1
      examples/js/nodes/utils/VelocityNode.js
  84. 12 6
      examples/js/objects/Fire.js
  85. 1 1
      examples/js/objects/Lensflare.js
  86. 5 2
      examples/js/objects/Reflector.js
  87. 5 2
      examples/js/objects/Refractor.js
  88. 3 1
      examples/js/objects/Water.js
  89. 2 1
      examples/js/pmrem/PMREMCubeUVPacker.js
  90. 3 1
      examples/js/pmrem/PMREMGenerator.js
  91. 14 6
      examples/js/postprocessing/AdaptiveToneMappingPass.js
  92. 16 8
      examples/js/postprocessing/AfterimagePass.js
  93. 10 4
      examples/js/postprocessing/BloomPass.js
  94. 9 4
      examples/js/postprocessing/BokehPass.js
  95. 1 1
      examples/js/postprocessing/ClearPass.js
  96. 4 2
      examples/js/postprocessing/CubeTexturePass.js
  97. 5 2
      examples/js/postprocessing/DotScreenPass.js
  98. 23 7
      examples/js/postprocessing/EffectComposer.js
  99. 6 3
      examples/js/postprocessing/FilmPass.js
  100. 5 2
      examples/js/postprocessing/GlitchPass.js

+ 1 - 1
.github/ISSUE_TEMPLATE.md

@@ -19,7 +19,7 @@ Please also include a live example if possible. You can start from these templat
 ##### Three.js version
 
 - [ ] Dev
-- [ ] r100
+- [ ] r101
 - [ ] ...
 
 ##### Browser

+ 0 - 1
.npmignore

@@ -1,6 +1,5 @@
 examples/*
 !examples/js/
-src/
 test/
 utils/
 docs/

File diff suppressed because it is too large
+ 4 - 4
build/three.js


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


File diff suppressed because it is too large
+ 2 - 2
build/three.module.js


+ 5 - 0
docs/api/en/animation/AnimationClip.html

@@ -66,6 +66,11 @@
 		<h2>Methods</h2>
 
 
+		<h3>[method:AnimationClip clone]()</h3>
+		<p>
+			Returns a copy of this clip.
+		</p>
+
 		<h3>[method:this optimize]()</h3>
 		<p>
 			Optimizes each track by removing equivalent sequential keys (which are common in morph target

+ 5 - 0
docs/api/en/animation/KeyframeTrack.html

@@ -160,6 +160,11 @@
 		<h2>Methods</h2>
 
 
+		<h3>[method:KeyframeTrack clone]()</h3>
+		<p>
+			Returns a copy of this track.
+		</p>
+
 		<h3>[method:null createInterpolant]()</h3>
 		<p>
 			Creates a [page:LinearInterpolant LinearInterpolant], [page:CubicInterpolant CubicInterpolant]

+ 1 - 1
docs/api/en/audio/Audio.html

@@ -22,7 +22,7 @@
 		<h2>Example</h2>
 
 		<p>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
 			[example:webaudio_visualizer webaudio / visualizer ]
 		</p>
 

+ 1 - 1
docs/api/en/audio/AudioAnalyser.html

@@ -22,7 +22,7 @@
 		<h2>Example</h2>
 
 		<p>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
 			[example:webaudio_visualizer webaudio / visualizer ]
 		</p>
 

+ 4 - 4
docs/api/en/audio/AudioListener.html

@@ -13,8 +13,8 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-			The [name] represents a virtual [link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener] of the all positional and non-positional audio effects in the scene.</br>
-			A three.js application usually creates a single instance of [name]. It is a mandatory construtor parameter for audios entities like [page:Audio Audio] and [page:PositionalAudio PositionalAudio].</br>
+			The [name] represents a virtual [link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener] of the all positional and non-positional audio effects in the scene.<br />
+			A three.js application usually creates a single instance of [name]. It is a mandatory construtor parameter for audios entities like [page:Audio Audio] and [page:PositionalAudio PositionalAudio].<br />
 			In most cases, the listener object is a child of the camera. So the 3D transformation of the camera represents the 3D transformation of the listener.
 		</p>
 
@@ -22,8 +22,8 @@
 		<h2>Example</h2>
 
 		<p>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
-			[example:webaudio_timing webaudio / timing ]</br>
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
+			[example:webaudio_timing webaudio / timing ]<br />
 			[example:webaudio_visualizer webaudio / visualizer ]
 		</p>
 

+ 2 - 2
docs/api/en/audio/PositionalAudio.html

@@ -22,8 +22,8 @@
 		<h2>Example</h2>
 
 		<p>
-			[example:webaudio_orientation webaudio / orientation ]</br>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
+			[example:webaudio_orientation webaudio / orientation ]<br />
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
 			[example:webaudio_timing webaudio / timing ]
 		</p>
 

+ 1 - 0
docs/api/en/constants/Renderer.html

@@ -55,6 +55,7 @@
 		THREE.ReinhardToneMapping
 		THREE.Uncharted2ToneMapping
 		THREE.CineonToneMapping
+		THREE.ACESFilmicToneMapping
 		</code>
 		<p>
 		These define the WebGLRenderer's [page:WebGLRenderer.toneMapping toneMapping] property.

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

@@ -292,7 +292,7 @@
 		Converts the vector from local space to world space.
 		</p>
 
-		<h3>[method:null lookAt]( [param:Vector3 vector] )</br>
+		<h3>[method:null lookAt]( [param:Vector3 vector] )<br />
 		[method:null lookAt]( [param:Float x], [param:Float y], [param:Float z] )</h3>
 		<p>
 		vector - A vector representing a position in world space.<br /><br />

+ 4 - 1
docs/api/en/extras/core/ShapePath.html

@@ -44,6 +44,9 @@
 		The current [page:Path] that is being generated.
 		</p>
 
+		<h3>[property:Color color]</h3>
+		<p>[page:Color] of the shape, by default set to white (0xffffff).</p>
+
 		<h2>Methods</h2>
 
 		<h3>[method:null moveTo]( [param:Float x], [param:Float y] )</h3>
@@ -86,6 +89,6 @@
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/src/extras/core/Path.js src/extras/core/Path.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/src/extras/core/ShapePath.js src/extras/core/ShapePath.js]
 	</body>
 </html>

+ 73 - 0
docs/api/en/helpers/PositionalAudioHelper.html

@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Object3D] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">This helper displays the directional cone of a [page:PositionalAudio].</p>
+
+		<h2>Example</h2>
+
+		<div>[example:webaudio_orientation webaudio / orientation ]</div>
+
+		<h2>Code Example</h2>
+		<code>
+var positionalAudio = new THREE.PositionalAudio( listener );
+positionalAudio.setDirectionalCone( 180, 230, 0.1 );
+
+var helper = new PositionalAudioHelper( positionalAudio );
+positionalAudio.add( helper );
+		</code>
+
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:PositionalAudio audio], [param:Number range] )</h3>
+		<p>
+			[page:PositionalAudio audio] -- The [page:PositionalAudio] to be visualized. <br /><br/>
+
+			[page:Number range] -- (optional) The range of the directional cone. <br /><br/>
+
+			[page:Number divisionsInnerAngle] -- (optional) The amount of divisions of the inner part of the directional cone. <br /><br/>
+
+			[page:Number divisionsOuterAngle] -- (optional) The amount of divisions of the outer part of the directional cone. <br /><br/>
+		</p>
+
+
+		<h2>Properties</h2>
+		<p>See the base [page:Object3D] class for common properties.</p>
+
+		<h3>[property:PositionalAudio audio]</h3>
+		<p>[page:PositionalAudio] to be visualized.</p>
+
+		<h3>[property:Number range]</h3>
+		<p>The range of the directional cone.</p>
+
+		<h3>[property:Number divisionsInnerAngle]</h3>
+		<p>The amount of divisions of the inner part of the directional cone.</p>
+
+		<h3>[property:Number divisionsOuterAngle]</h3>
+		<p>The amount of divisions of the outer part of the directional cone.</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Object3D] class for common methods.</p>
+
+		<h3>[method:null dispose]()</h3>
+		<p>Disposes of the helper.</p>
+
+		<h3>[method:null update]()</h3>
+		<p>Updates the helper.</p>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 7 - 0
docs/api/en/materials/Material.html

@@ -261,6 +261,13 @@
 		Other options are [page:Materials THREE.VertexColors] and [page:Materials THREE.FaceColors].
 		</p>
 
+		<h3>[property:Boolean vertexTangents]</h3>
+		<p>
+		Defines whether precomputed vertex tangents, which must be provided in a vec4 "tangent" attribute,
+		are used. When disabled, tangents are derived automatically. Using precomputed tangents will give
+		more accurate normal map details in some cases, such as with mirrored UVs. Default is false.
+		</p>
+
 		<h3>[property:Boolean visible]</h3>
 		<p>
 		Defines whether this material is visible. Default is *true*.

+ 2 - 2
docs/api/en/objects/SkinnedMesh.html

@@ -91,8 +91,8 @@
 		<h2>Constructor</h2>
 		<h3>[name]( [param:BufferGeometry geometry], [param:Material material] )</h3>
 		<p>
-    [page:Geometry geometry] - an instance of [page:BufferGeometry].<br />
-    [page:Material material] - (optional) an instance of [page:Material]. Default is a new [page:MeshBasicMaterial].
+		[page:Geometry geometry] - an instance of [page:BufferGeometry].<br />
+		[page:Material material] - (optional) an instance of [page:Material]. Default is a new [page:MeshBasicMaterial].
 		</p>
 
 

+ 35 - 16
docs/api/en/renderers/WebGLRenderer.html

@@ -348,37 +348,56 @@
 		<h3>[method:RenderTarget getRenderTarget]()</h3>
 		<p>Returns the current RenderTarget, if any.</p>
 
-		<h3>[method:RenderTarget getCurrentViewport]()</h3>
-		<p>Returns the current viewport.</p>
+		<h3>[method:Vector4 getCurrentViewport]( [param:Vector4 target] )</h3>
+		<p>
+		[page:Vector4 target] — the result will be copied into this Vector4.<br /><br />
+
+		Returns the current viewport.
+		</p>
+
+		<h3>[method:Vector2 getDrawingBufferSize]( [param:Vector2 target] )</h3>
+		<p>
+		[page:Vector2 target] — the result will be copied into this Vector2.<br /><br />
 
-		<h3>[method:Object getDrawingBufferSize]()</h3>
-		<p>Returns an object containing the width and height of the renderer's drawing buffer, in pixels.</p>
+		Returns the width and height of the renderer's drawing buffer, in pixels.
+		</p>
 
 		<h3>[method:number getPixelRatio]()</h3>
 		<p>Returns current device pixel ratio used.</p>
 
-		<h3>[method:Object getSize]()</h3>
-		<p>Returns an object containing the width and height of the renderer's output canvas, in pixels.</p>
+		<h3>[method:Vector2 getSize]( [param:Vector2 target] )</h3>
+		<p>
+		[page:Vector2 target] — the result will be copied into this Vector2.<br /><br />
+
+		Returns the width and height of the renderer's output canvas, in pixels.
+		</p>
+
+		<h3>[method:Vector4 getViewport]( [param:Vector4 target] )</h3>
+		<p>
+		[page:Vector4 target] — the result will be copied into this Vector4.<br /><br />
+
+		Returns the viewport.
+		</p>
 
 		<h3>[method:null resetGLState]( )</h3>
 		<p>Reset the GL state to default. Called internally if the WebGL context is lost.</p>
 
-		<h3>[method:null readRenderTargetPixels]( [param:WebGLRenderTarget renderTarget], [param:Float x], [param:Float y], [param:Float width], [param:Float height], buffer )</h3>
-		<p>Reads the pixel data from the renderTarget into the buffer you pass in. This is a wrapper around [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/readPixels WebGLRenderingContext.readPixels]().<br />
-		See the [example:webgl_interactive_cubes_gpu interactive / cubes / gpu] example.
+		<h3>[method:null readRenderTargetPixels]( [param:WebGLRenderTarget renderTarget], [param:Float x], [param:Float y], [param:Float width], [param:Float height], [param:TypedArray buffer] )</h3>
+		<p>buffer - Uint8Array is the only destination type supported in all cases, other types are renderTarget and platform dependent. See [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.12 WebGL spec] for details.</p>
+		<p>Reads the pixel data from the renderTarget into the buffer you pass in. This is a wrapper around [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/readPixels WebGLRenderingContext.readPixels]().</p>
+		<p>See the [example:webgl_interactive_cubes_gpu interactive / cubes / gpu] example.
 		</p>
 
-		<h3>[method:null render]( [param:Scene scene], [param:Camera camera], [param:WebGLRenderTarget renderTarget], [param:Boolean forceClear] )</h3>
+
+		<h3>[method:null render]( [param:Scene scene], [param:Camera camera] )</h3>
 		<p>
 			Render a [page:Scene scene] using a [page:Camera camera].<br />
 
-			The render is done to the [page:WebGLRenderTarget renderTarget] (if specified) or to the canvas as usual.<br />
-
-			If [page:Boolean forceClear] is *true*, the depth, stencil and color buffers will be cleared
-			before rendering even if the renderer's [page:WebGLRenderer.autoClear autoClear] property is false.<br />
+			The render is done to a previously specified [page:WebGLRenderTarget renderTarget] set by calling [page:WebGLRenderer.setRenderTarget .setRenderTarget] or to the canvas as usual.<br />
 
-			Even with forceClear set to true you can prevent certain buffers being cleared by setting
-			either the [page:WebGLRenderer.autoClearColor autoClearColor], [page:WebGLRenderer.autoClearStencil autoClearStencil] or [page:WebGLRenderer.autoClearDepth autoClearDepth] properties to false.
+			By default render buffers are cleared before rendering but you can prevent this by setting the property [page:WebGLRenderer.autoClear autoClear] to false.
+			If you want to prevent only certain buffers being cleared you can set either the [page:WebGLRenderer.autoClearColor autoClearColor], [page:WebGLRenderer.autoClearStencil autoClearStencil] or
+			[page:WebGLRenderer.autoClearDepth autoClearDepth] properties to false. To forcibly clear one ore more buffers call [page:WebGLRenderer.clear .clear].
 		</p>
 
 		<h3>[method:null renderBufferDirect]( [param:Camera camera], [param:Fog fog], [param:Geometry geometry], [param:Material material], [param:Object3D object], [param:Object group] )</h3>

+ 10 - 2
docs/api/en/textures/DataTexture3D.html

@@ -32,10 +32,18 @@
 		<div>[example:webgl2_materials_texture3d WebGL2 / materials / texture3d]</div>
 		<div>[example:webgl2_materials_texture3d_volume WebGL2 / materials / texture3d / volume]</div>
 
-		<h2>Properties</h2>
+    <h2>Properties</h2>
 
 		<p>
-		See the base [page:Texture Texture] class for common properties.
+    See the base [page:Texture Texture] class for common properties.
+    </p>
+
+    <h3>[property:number wrapR]</h3>
+		<p>
+		This defines how the texture is wrapped in the depth direction.<br />
+		The default is [page:Textures THREE.ClampToEdgeWrapping], where the edge is clamped to the outer edge texels.
+		The other two choices are [page:Textures THREE.RepeatWrapping] and [page:Textures THREE.MirroredRepeatWrapping].
+		See the [page:Textures texture constants] page for details.
 		</p>
 
 		<h2>Methods</h2>

+ 3 - 0
docs/api/zh/animation/AnimationClip.html

@@ -62,6 +62,9 @@
 		<h2>方法</h2>
 
 
+		<h3>[method:AnimationClip clone]()</h3>
+		<p></p>
+
 		<h3>[method:this optimize]()</h3>
 		<p>
             通过移除等效的顺序键(在变形目标序列中很常见)来优化每一个轨道

+ 6 - 0
docs/api/zh/animation/AnimationUtils.html

@@ -38,12 +38,18 @@
             返回一个数组,时间和值可以根据此数组排序。
 		</p>
 
+		<h3>[method:Number insertKeyframe]( [param:KeyframeTrack track], [param:Number time] )</h3>
+		<p></p>
+
 		<h3>[method:Boolean isTypedArray]( object )</h3>
 		<p>
             如果该对象是类型化数组,返回*true*
 
 		</p>
 
+		<h3>[method:AnimationClip mergeMorphTargetTracks]( [param:AnimationClip clip], [param:Object3D root] )</h3>
+		<p></p>
+
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<p>
             将[page:AnimationUtils.getKeyframeOrder getKeyframeOrder]方法返回的数组排序。

+ 3 - 0
docs/api/zh/animation/KeyframeTrack.html

@@ -137,6 +137,9 @@
 		<h2>方法</h2>
 
 
+		<h3>[method:KeyframeTrack clone]()</h3>
+		<p></p>
+
 		<h3>[method:null createInterpolant]()</h3>
 		<p>
 			根据传入构造器中的插值类型参数,创建线性插值([page:LinearInterpolant LinearInterpolant]),立方插值([page:CubicInterpolant CubicInterpolant])或离散插值

+ 1 - 1
docs/api/zh/audio/Audio.html

@@ -22,7 +22,7 @@
 		<h2>例子</h2>
 
 		<p>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
 			[example:webaudio_visualizer webaudio / visualizer ]
 		</p>
 

+ 1 - 1
docs/api/zh/audio/AudioAnalyser.html

@@ -22,7 +22,7 @@
 		<h2>示例</h2>
 
 		<p>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
 			[example:webaudio_visualizer webaudio / visualizer ]
 		</p>
 

+ 4 - 4
docs/api/zh/audio/AudioListener.html

@@ -13,8 +13,8 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-			[name] 用一个虚拟的[link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener]表示在场景中所有的位置和非位置相关的音效.</br>
-			一个three.js程序通常创建一个[name]. 它是音频实体构造函数的必须参数,比如 [page:Audio Audio] and [page:PositionalAudio PositionalAudio].</br>
+			[name] 用一个虚拟的[link:https://developer.mozilla.org/de/docs/Web/API/AudioListener listener]表示在场景中所有的位置和非位置相关的音效.<br />
+			一个three.js程序通常创建一个[name]. 它是音频实体构造函数的必须参数,比如 [page:Audio Audio] and [page:PositionalAudio PositionalAudio].<br />
 			大多数情况下, listener对象是camera的子对象. Camera的3D变换表示了listener的3D变换.
 		</p>
 
@@ -22,8 +22,8 @@
 		<h2>示例</h2>
 
 		<p>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
-			[example:webaudio_timing webaudio / timing ]</br>
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
+			[example:webaudio_timing webaudio / timing ]<br />
 			[example:webaudio_visualizer webaudio / visualizer ]
 		</p>
 

+ 2 - 2
docs/api/zh/audio/PositionalAudio.html

@@ -22,8 +22,8 @@
 		<h2>示例</h2>
 
 		<p>
-			[example:webaudio_orientation webaudio / orientation ]</br>
-			[example:webaudio_sandbox webaudio / sandbox ]</br>
+			[example:webaudio_orientation webaudio / orientation ]<br />
+			[example:webaudio_sandbox webaudio / sandbox ]<br />
 			[example:webaudio_timing webaudio / timing ]
 		</p>
 

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

@@ -273,7 +273,7 @@
 		将局部空间向量转换为世界空间向量。
 	</p>
 
-	<h3>[method:null lookAt]( [param:Vector3 vector] )</br>
+	<h3>[method:null lookAt]( [param:Vector3 vector] )<br />
 		[method:null lookAt]( [param:Float x], [param:Float y], [param:Float z] )</h3>
 	<p>
 		vector - 一个表示世界空间中位置的向量。<br /><br />

+ 73 - 0
docs/api/zh/helpers/PositionalAudioHelper.html

@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Object3D] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">This helper displays the directional cone of a [page:PositionalAudio].</p>
+
+		<h2>Example</h2>
+
+		<div>[example:webaudio_orientation webaudio / orientation ]</div>
+
+		<h2>Code Example</h2>
+		<code>
+var positionalAudio = new THREE.PositionalAudio( listener );
+positionalAudio.setDirectionalCone( 180, 230, 0.1 );
+
+var helper = new PositionalAudioHelper( positionalAudio );
+positionalAudio.add( helper );
+		</code>
+
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:PositionalAudio audio], [param:Number range] )</h3>
+		<p>
+			[page:PositionalAudio audio] -- The [page:PositionalAudio] to be visualized. <br /><br/>
+
+			[page:Number range] -- (optional) The range of the directional cone. <br /><br/>
+
+			[page:Number divisionsInnerAngle] -- (optional) The amount of divisions of the inner part of the directional cone. <br /><br/>
+
+			[page:Number divisionsOuterAngle] -- (optional) The amount of divisions of the outer part of the directional cone. <br /><br/>
+		</p>
+
+
+		<h2>Properties</h2>
+		<p>See the base [page:Object3D] class for common properties.</p>
+
+		<h3>[property:PositionalAudio audio]</h3>
+		<p>[page:PositionalAudio] to be visualized.</p>
+
+		<h3>[property:Number range]</h3>
+		<p>The range of the directional cone.</p>
+
+		<h3>[property:Number divisionsInnerAngle]</h3>
+		<p>The amount of divisions of the inner part of the directional cone.</p>
+
+		<h3>[property:Number divisionsOuterAngle]</h3>
+		<p>The amount of divisions of the outer part of the directional cone.</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Object3D] class for common methods.</p>
+
+		<h3>[method:null dispose]()</h3>
+		<p>Disposes of the helper.</p>
+
+		<h3>[method:null update]()</h3>
+		<p>Updates the helper.</p>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 4 - 0
docs/api/zh/materials/Material.html

@@ -217,6 +217,10 @@
     其他选项有[page:Materials THREE.VertexColors] 和 [page:Materials THREE.FaceColors]。
 </p>
 
+<h3>[property:Boolean vertexTangents]</h3>
+<p> TODO.
+</p>
+
 <h3>[property:Boolean visible]</h3>
 <p> 此材质是否可见。默认为*true*。
 </p>

+ 1 - 0
docs/examples/exporters/GLTFExporter.html

@@ -29,6 +29,7 @@
 		</p>
 
 		<ul>
+			<li>KHR_lights_punctual</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_texture_transform</li>
 		</ul>

+ 15 - 0
docs/index.html

@@ -69,6 +69,8 @@
 
 				language = value;
 				createNavigation();
+				updateFilter();
+				autoChangeUrlLanguage( language );
 
 			}
 
@@ -226,6 +228,19 @@
 
 			}
 
+			// Auto change language url. If a reader open a document in English, when he click "zh", the document he read will auto change into Chinese version
+
+			function autoChangeUrlLanguage( language ) {
+
+				var hash = location.hash;
+				if ( hash === '' ) return;
+				var docType = hash.substr( 0, hash.indexOf( '/' ) + 1 );
+				var docLink = hash.substr( hash.indexOf( '/' ) + 1 );
+				docLink = docLink.substr( docLink.indexOf( '/' ) );
+				location.href = docType + language + docLink;
+
+			}
+
 
 			// Filtering
 

+ 4 - 0
docs/list.js

@@ -22,6 +22,7 @@ var list = {
 
 			"Next Steps": {
 				"How to update things": "manual/en/introduction/How-to-update-things",
+				"How to dispose of objects": "manual/en/introduction/How-to-dispose-of-objects",
 				"How to create VR content": "manual/en/introduction/How-to-create-VR-content",
 				"Matrix transformations": "manual/en/introduction/Matrix-transformations",
 				"Animation system": "manual/en/introduction/Animation-system"
@@ -196,6 +197,7 @@ var list = {
 				"FaceNormalsHelper": "api/en/helpers/FaceNormalsHelper",
 				"GridHelper": "api/en/helpers/GridHelper",
 				"PolarGridHelper": "api/en/helpers/PolarGridHelper",
+				"PositionalAudioHelper": "api/en/helpers/PositionalAudioHelper",
 				"HemisphereLightHelper": "api/en/helpers/HemisphereLightHelper",
 				"PlaneHelper": "api/en/helpers/PlaneHelper",
 				"PointLightHelper": "api/en/helpers/PointLightHelper",
@@ -447,6 +449,7 @@ var list = {
 
 			"进阶": {
 				"如何更新场景": "manual/zh/introduction/How-to-update-things",
+				"How to dispose of objects": "manual/zh/introduction/How-to-dispose-of-objects",
 				"如何创建VR内容": "manual/zh/introduction/How-to-create-VR-content",
 				"矩阵变换": "manual/zh/introduction/Matrix-transformations",
 				"动画系统": "manual/zh/introduction/Animation-system"
@@ -621,6 +624,7 @@ var list = {
 				"FaceNormalsHelper": "api/zh/helpers/FaceNormalsHelper",
 				"GridHelper": "api/zh/helpers/GridHelper",
 				"PolarGridHelper": "api/zh/helpers/PolarGridHelper",
+				"PositionalAudioHelper": "api/zh/helpers/PositionalAudioHelper",
 				"HemisphereLightHelper": "api/zh/helpers/HemisphereLightHelper",
 				"PlaneHelper": "api/zh/helpers/PlaneHelper",
 				"PointLightHelper": "api/zh/helpers/PointLightHelper",

+ 126 - 0
docs/manual/en/introduction/How-to-dispose-of-objects.html

@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="utf-8">
+	<base href="../../../" />
+	<script src="list.js"></script>
+	<script src="page.js"></script>
+	<link type="text/css" rel="stylesheet" href="page.css" />
+</head>
+
+<body>
+	<h1>[name]</h1>
+	<br />
+
+	<p>
+		One important aspect in order to improve performance and avoid memory leaks in your application is the disposal of unused library entities.
+		Whenever you create an instance of a *three.js* type, you allocate a certain amount of memory. However, *three.js* creates for specific objects
+		like geometries or materials WebGL related entities like buffers or shader programs which are necessary for rendering. It's important to
+		highlight that these objects are not released automatically. Instead, the application has to use a special API in order to free such resources.
+		This guide provides a brief overview about how this API is used and what objects are relevant in this context.
+	</p>
+
+	<h2>Geometries</h2>
+
+	<p>
+		A geometry usually represents vertex information defined as a collection of attributes. *three.js* internally creates an object of type [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]
+		for each attribute. These entities are only deleted if you call [page:BufferGeometry.dispose](). If a geometry becomes obsolete in your application,
+		execute the method to free all related resources.
+	</p>
+
+	<h2>Materials</h2>
+
+	<p>
+		A material defines how objects are rendered. *three.js* uses the information of a material definition in order to construct a shader program for rendering.
+		Shader programs can only be deleted if the respective material is disposed. For performance reasons, *three.js* tries to reuse existing
+		shader programs if possible. So a shader program is only deleted if all related materials are disposed. You can indicate the disposal of a material by
+		executing [page:Material.dispose]().
+	</p>
+
+	<h2>Textures</h2>
+
+	<p>
+		The disposal of a material has no effect on textures. They are handled separately since a single texture can be used by multiple materials at the same time.
+		Whenever you create an instance of [page:Texture], three.js internally creates an instance of [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture].
+		Similar to buffers, this object can only be deleted by calling [page:Texture.dispose]().
+	</p>
+
+	<h2>Render Targets</h2>
+
+	<p>
+		Objects of type [page:WebGLRenderTarget] not only allocate an instance of [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture] but also
+		[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer WebGLFramebuffer]s and [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer WebGLRenderbuffer]s
+		for realizing custom rendering destinations. These objects are only deallocated by executing [page:WebGLRenderTarget.dispose]().
+	</p>
+
+	<h2>Miscellaneous</h2>
+
+	<p>
+		There are other classes from the examples directory like controls or post processing passes which provide *dispose()* methods in order to remove internal event listeners
+		or render targets. In general, it's recommended to check the API or documentation of a class and watch for *dispose()*. If present, you should use it when cleaning things up.
+	</p>
+
+	<h2>FAQ</h2>
+
+	<h3>Why can't *three.js* dispose objects automatically?</h3>
+
+	<p>
+		This question was asked many times by the community so it's important to clarify this matter. Fact is that *three.js* does not know the lifetime or scope
+		of user-created entities like geometries or materials. This is the responsibility of the application. For example even if a material is currently not used for rendering,
+		it might base necessary for the next frame. So if the application decides that a certain object can be deleted, it has to	notify the engine via calling the respective
+		*dispose()* method.
+	</p>
+
+	<h3>Does removing a mesh from the scene also dispose its geometry and material?</h3>
+
+	<p>
+		No, you have to explicitly dispose the geometry and material via *dispose()*. Keep in mind that geometries and materials can be shared among 3D objects like meshes.
+	</p>
+
+	<h3>Does *three.js* provide information about the amount of cached objects?</h3>
+
+	<p>
+		Yes. It's possible to evaluate [page:WebGLRenderer.info], a special property of the renderer with a series of statistical information about the graphics board memory
+		and the rendering process. Among other things, it tells you have many textures, geometries and shader programs are internally stored. If you notice performance problems
+		in your application, it's a good idea to debug this property in order to easily identify a memory leak.
+	</p>
+
+	<p>
+		Internal resources for a texture are only allocated if the image has fully loaded. If you dispose a texture before the image was loaded,
+		nothing happens. No resources were allocated so there is also no need for clean up.
+	</p>
+
+	<h3>Why happens when you call *dispose()* on a texture but the image is not loaded yet?</h3>
+
+	<p>
+		Internal resources for a texture are only allocated if the image has fully loaded. If you dispose a texture before the image was loaded,
+		nothing happens. No resources were allocated so there is also no need for clean up.
+	</p>
+
+	<h3>What happens when I call *dispose()* and then use the respective object at a later point?</h3>
+
+	<p>
+		The deleted internal resources will be created again by the engine. So no runtime error will occur but you might notice a negative performance impact for the current frame,
+		especially when shader programs have to be compiled.
+	</p>
+
+	<h3>How should I manage *three.js* objects in my app? When do I know how to dispose things?</h3>
+
+	<p>
+		In general, there is no definite recommendation for this. It highly depends on the specific use case when calling *dispose()* is appropriate. It's important to highlight that
+		it's not always necessary to dispose objects all the time. A good example for this is a game which consists of multiple levels. A good place for object disposal is when
+		switching the level. The app could traverse through the old scene and dispose all obsolete materials, geometries and textures. As mentioned in the previous section, it does not
+		produce a runtime error if you dispose an object that is actually still in use. The worst thing that can happen is performance drop for a single frame.
+	</p>
+
+	<h2>Examples that demonstrate the usage of dispose()</h2>
+
+	<p>
+		[example:webgl_test_memory WebGL / test / memory]<br />
+		[example:webgl_test_memory2 WebGL / test / memory2]<br />
+	</p>
+
+</body>
+
+</html>

+ 4 - 0
docs/manual/en/introduction/Useful-links.html

@@ -125,6 +125,10 @@
 		<li>
 			[link:http://idflood.github.io/ThreeNodes.js/ ThreeNodes.js].
 		</li>
+		<li>
+			<a href="https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates" target="_blank">comment-tagged-templates</a> -
+			VSCode extension syntax highlighting for tagged template strings, like: glsl.js.
+		</li>
 	 </ul>
 
 	<h2>WebGL References</h2>

+ 20 - 0
docs/manual/zh/introduction/How-to-dispose-of-objects.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="utf-8">
+	<base href="../../../" />
+	<script src="list.js"></script>
+	<script src="page.js"></script>
+	<link type="text/css" rel="stylesheet" href="page.css" />
+</head>
+
+<body>
+	<h1>[name]</h1>
+	<br />
+
+	TODO
+
+</body>
+
+</html>

+ 2 - 4
editor/index.html

@@ -4,10 +4,8 @@
 		<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 = WebXR Device API (For Chrome M69+), origin = https://threejs.org, expires = 2019-01-23 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M69+)" data-expires="2019-01-23" content="ApibcCZfaeEIkwpe6CSIKZXC8ODly5nYX+QlUSgwhUUlMN1/Ko7dr5XUwZDFl9SiEGtOFFe2csLwnNg33ZBh+QMAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU02OSIsImV4cGlyeSI6MTU0ODIwMTU5OX0=">
-		<!-- Origin Trial Token, feature = WebXR Gamepad Support, origin = https://threejs.org, expires = 2019-01-23 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Gamepad Support" data-expires="2019-01-23" content="Agt5pp1xG96NMH+7RdcD7jvbkJiJTagqfKtC+28x/TBeQSh4tF7ad7uXL9Clqbts0vivamPTTkRkNdyfJtEezQ4AAABYeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkdhbWVwYWRTdXBwb3J0IiwiZXhwaXJ5IjoxNTQ4MjAxNTk5fQ==">
+		<!-- Origin Trial Token, feature = WebXR Device API (For Chrome M69+), origin = https://threejs.org, expires = 2019-03-06 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M69+)" data-expires="2019-03-06" content="AvDjbxYpoTgOL1PS0JEra7KFCehfTlKnXpU/ORSwNdCQ35cX70cTUkXOnQ26A5XJi3eXHSKpBPchdt5lbcxDuAIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU02OSIsImV4cGlyeSI6MTU1MTgzMDM5OX0=">
 	</head>
 	<body ontouchstart="">
 		<link href="css/main.css" rel="stylesheet" />

+ 5 - 5
editor/js/libs/ui.js

@@ -115,8 +115,8 @@ UI.Element.prototype = {
 // properties
 
 var properties = [ 'position', 'left', 'top', 'right', 'bottom', 'width', 'height', 'border', 'borderLeft',
-'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
-'background', 'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex' ];
+	'borderTop', 'borderRight', 'borderBottom', 'borderColor', 'display', 'overflow', 'margin', 'marginLeft', 'marginTop', 'marginRight', 'marginBottom', 'padding', 'paddingLeft', 'paddingTop', 'paddingRight', 'paddingBottom', 'color',
+	'background', 'backgroundColor', 'opacity', 'fontSize', 'fontWeight', 'textAlign', 'textDecoration', 'textTransform', 'cursor', 'zIndex' ];
 
 properties.forEach( function ( property ) {
 
@@ -863,9 +863,9 @@ UI.Integer.prototype.setValue = function ( value ) {
 };
 
 UI.Integer.prototype.setStep = function ( step ) {
-	
-	this.step = parseInt( step ); 
-	
+
+	this.step = parseInt( step );
+
 	return this;
 
 };

+ 1 - 0
examples/files.js

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

+ 8 - 2
examples/js/GPUComputationRenderer.js

@@ -277,7 +277,9 @@ function GPUComputationRenderer( sizeX, sizeY, renderer ) {
 		addResolutionDefine( material );
 
 		return material;
+
 	}
+
 	this.createShaderMaterial = createShaderMaterial;
 
 	this.createRenderTarget = function( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
@@ -316,7 +318,6 @@ function GPUComputationRenderer( sizeX, sizeY, renderer ) {
 
 	};
 
-
 	this.renderTexture = function( input, output ) {
 
 		// Takes a texture, and render out in rendertarget
@@ -333,10 +334,15 @@ function GPUComputationRenderer( sizeX, sizeY, renderer ) {
 
 	this.doRenderTarget = function( material, output ) {
 
+		var currentRenderTarget = renderer.getRenderTarget();
+
 		mesh.material = material;
-		renderer.render( scene, camera, output );
+		renderer.setRenderTarget( output );
+		renderer.render( scene, camera );
 		mesh.material = passThruShader;
 
+		renderer.setRenderTarget( currentRenderTarget );
+
 	};
 
 	// Shaders

+ 39 - 14
examples/js/Ocean.js

@@ -212,6 +212,8 @@ THREE.Ocean.prototype.generateMesh = function () {
 
 THREE.Ocean.prototype.render = function () {
 
+	var currentRenderTarget = this.renderer.getRenderTarget();
+
 	this.scene.overrideMaterial = null;
 
 	if ( this.changed )
@@ -223,9 +225,11 @@ THREE.Ocean.prototype.render = function () {
 	this.renderNormalMap();
 	this.scene.overrideMaterial = null;
 
+	this.renderer.setRenderTarget( currentRenderTarget );
+
 };
 
-THREE.Ocean.prototype.generateSeedPhaseTexture = function() {
+THREE.Ocean.prototype.generateSeedPhaseTexture = function () {
 
 	// Setup the seed texture
 	this.pingPhase = true;
@@ -234,7 +238,7 @@ THREE.Ocean.prototype.generateSeedPhaseTexture = function() {
 
 		for ( var j = 0; j < this.resolution; j ++ ) {
 
-			phaseArray[ i * this.resolution * 4 + j * 4 ] =  Math.random() * 2.0 * Math.PI;
+			phaseArray[ i * this.resolution * 4 + j * 4 ] = Math.random() * 2.0 * Math.PI;
 			phaseArray[ i * this.resolution * 4 + j * 4 + 1 ] = 0.0;
 			phaseArray[ i * this.resolution * 4 + j * 4 + 2 ] = 0.0;
 			phaseArray[ i * this.resolution * 4 + j * 4 + 3 ] = 0.0;
@@ -256,7 +260,10 @@ THREE.Ocean.prototype.renderInitialSpectrum = function () {
 	this.scene.overrideMaterial = this.materialInitialSpectrum;
 	this.materialInitialSpectrum.uniforms.u_wind.value.set( this.windX, this.windY );
 	this.materialInitialSpectrum.uniforms.u_size.value = this.size;
-	this.renderer.render( this.scene, this.oceanCamera, this.initialSpectrumFramebuffer, true );
+
+	this.renderer.setRenderTarget( this.initialSpectrumFramebuffer );
+	this.renderer.clear();
+	this.renderer.render( this.scene, this.oceanCamera );
 
 };
 
@@ -269,14 +276,15 @@ THREE.Ocean.prototype.renderWavePhase = function () {
 		this.materialPhase.uniforms.u_phases.value = this.pingPhaseTexture;
 		this.initial = false;
 
-	}else {
+	} else {
 
 		this.materialPhase.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer.texture : this.pongPhaseFramebuffer.texture;
 
 	}
 	this.materialPhase.uniforms.u_deltaTime.value = this.deltaTime;
 	this.materialPhase.uniforms.u_size.value = this.size;
-	this.renderer.render( this.scene, this.oceanCamera, this.pingPhase ? this.pongPhaseFramebuffer : this.pingPhaseFramebuffer );
+	this.renderer.setRenderTarget( this.pingPhase ? this.pongPhaseFramebuffer : this.pingPhaseFramebuffer );
+	this.renderer.render( this.scene, this.oceanCamera );
 	this.pingPhase = ! this.pingPhase;
 
 };
@@ -288,11 +296,13 @@ THREE.Ocean.prototype.renderSpectrum = function () {
 	this.materialSpectrum.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer.texture : this.pongPhaseFramebuffer.texture;
 	this.materialSpectrum.uniforms.u_choppiness.value = this.choppiness;
 	this.materialSpectrum.uniforms.u_size.value = this.size;
-	this.renderer.render( this.scene, this.oceanCamera, this.spectrumFramebuffer );
+
+	this.renderer.setRenderTarget( this.spectrumFramebuffer );
+	this.renderer.render( this.scene, this.oceanCamera );
 
 };
 
-THREE.Ocean.prototype.renderSpectrumFFT = function() {
+THREE.Ocean.prototype.renderSpectrumFFT = function () {
 
 	// GPU FFT using Stockham formulation
 	var iterations = Math.log( this.resolution ) / Math.log( 2 ); // log2
@@ -305,19 +315,25 @@ THREE.Ocean.prototype.renderSpectrumFFT = function() {
 
 			this.materialOceanHorizontal.uniforms.u_input.value = this.spectrumFramebuffer.texture;
 			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
-			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+			this.renderer.setRenderTarget( this.pingTransformFramebuffer );
+			this.renderer.render( this.scene, this.oceanCamera );
 
 		} else if ( i % 2 === 1 ) {
 
 			this.materialOceanHorizontal.uniforms.u_input.value = this.pingTransformFramebuffer.texture;
 			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
-			this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
+
+			this.renderer.setRenderTarget( this.pongTransformFramebuffer );
+			this.renderer.render( this.scene, this.oceanCamera );
 
 		} else {
 
 			this.materialOceanHorizontal.uniforms.u_input.value = this.pongTransformFramebuffer.texture;
 			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
-			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+			this.renderer.setRenderTarget( this.pingTransformFramebuffer );
+			this.renderer.render( this.scene, this.oceanCamera );
 
 		}
 
@@ -329,19 +345,25 @@ THREE.Ocean.prototype.renderSpectrumFFT = function() {
 
 			this.materialOceanVertical.uniforms.u_input.value = ( iterations % 2 === 0 ) ? this.pingTransformFramebuffer.texture : this.pongTransformFramebuffer.texture;
 			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
-			this.renderer.render( this.scene, this.oceanCamera, this.displacementMapFramebuffer );
+
+			this.renderer.setRenderTarget( this.displacementMapFramebuffer );
+			this.renderer.render( this.scene, this.oceanCamera );
 
 		} else if ( i % 2 === 1 ) {
 
 			this.materialOceanVertical.uniforms.u_input.value = this.pingTransformFramebuffer.texture;
 			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
-			this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
+
+			this.renderer.setRenderTarget( this.pongTransformFramebuffer );
+			this.renderer.render( this.scene, this.oceanCamera );
 
 		} else {
 
 			this.materialOceanVertical.uniforms.u_input.value = this.pongTransformFramebuffer.texture;
 			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
-			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+			this.renderer.setRenderTarget( this.pingTransformFramebuffer );
+			this.renderer.render( this.scene, this.oceanCamera );
 
 		}
 
@@ -354,6 +376,9 @@ THREE.Ocean.prototype.renderNormalMap = function () {
 	this.scene.overrideMaterial = this.materialNormal;
 	if ( this.changed ) this.materialNormal.uniforms.u_size.value = this.size;
 	this.materialNormal.uniforms.u_displacementMap.value = this.displacementMapFramebuffer.texture;
-	this.renderer.render( this.scene, this.oceanCamera, this.normalMapFramebuffer, true );
+
+	this.renderer.setRenderTarget( this.normalMapFramebuffer );
+	this.renderer.clear();
+	this.renderer.render( this.scene, this.oceanCamera );
 
 };

+ 11 - 2
examples/js/cameras/CinematicCamera.js

@@ -177,22 +177,31 @@ THREE.CinematicCamera.prototype.renderCinematic = function ( scene, renderer ) {
 
 	if ( this.postprocessing.enabled ) {
 
+		var currentRenderTarget = renderer.getRenderTarget();
+
 		renderer.clear();
 
 		// Render scene into texture
 
 		scene.overrideMaterial = null;
-		renderer.render( scene, camera, this.postprocessing.rtTextureColor, true );
+		renderer.setRenderTarget( this.postprocessing.rtTextureColor );
+		renderer.clear();
+		renderer.render( scene, camera );
 
 		// Render depth into texture
 
 		scene.overrideMaterial = this.materialDepth;
-		renderer.render( scene, camera, this.postprocessing.rtTextureDepth, true );
+		renderer.setRenderTarget( this.postprocessing.rtTextureDepth );
+		renderer.clear();
+		renderer.render( scene, camera );
 
 		// Render bokeh composite
 
+		renderer.setRenderTarget( null );
 		renderer.render( this.postprocessing.scene, this.postprocessing.camera );
 
+		renderer.setRenderTarget( currentRenderTarget );
+
 	}
 
 };

+ 87 - 45
examples/js/controls/FirstPersonControls.js

@@ -7,7 +7,6 @@
 THREE.FirstPersonControls = function ( object, domElement ) {
 
 	this.object = object;
-	this.target = new THREE.Vector3( 0, 0, 0 );
 
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
 
@@ -35,11 +34,6 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 	this.mouseX = 0;
 	this.mouseY = 0;
 
-	this.lat = 0;
-	this.lon = 0;
-	this.phi = 0;
-	this.theta = 0;
-
 	this.moveForward = false;
 	this.moveBackward = false;
 	this.moveLeft = false;
@@ -50,6 +44,17 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 	this.viewHalfX = 0;
 	this.viewHalfY = 0;
 
+	// private variables
+
+	var lat = 0;
+	var lon = 0;
+
+	var lookDirection = new THREE.Vector3();
+	var spherical = new THREE.Spherical();
+	var target = new THREE.Vector3();
+
+	//
+
 	if ( this.domElement !== document ) {
 
 		this.domElement.setAttribute( 'tabindex', - 1 );
@@ -184,74 +189,97 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 	};
 
-	this.update = function ( delta ) {
-
-		if ( this.enabled === false ) return;
-
-		if ( this.heightSpeed ) {
+	this.lookAt = function ( x, y, z ) {
 
-			var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
-			var heightDelta = y - this.heightMin;
+		if ( x.isVector3 ) {
 
-			this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
+			target.copy( x );
 
 		} else {
 
-			this.autoSpeedFactor = 0.0;
+			target.set( x, y, z );
 
 		}
 
-		var actualMoveSpeed = delta * this.movementSpeed;
+		this.object.lookAt( target );
 
-		if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
-		if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
+		setOrientation( this );
 
-		if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
-		if ( this.moveRight ) this.object.translateX( actualMoveSpeed );
+		return this;
 
-		if ( this.moveUp ) this.object.translateY( actualMoveSpeed );
-		if ( this.moveDown ) this.object.translateY( - actualMoveSpeed );
+	};
 
-		var actualLookSpeed = delta * this.lookSpeed;
+	this.update = function () {
 
-		if ( ! this.activeLook ) {
+		var targetPosition = new THREE.Vector3();
 
-			actualLookSpeed = 0;
+		return function update( delta ) {
 
-		}
+			if ( this.enabled === false ) return;
 
-		var verticalLookRatio = 1;
+			if ( this.heightSpeed ) {
 
-		if ( this.constrainVertical ) {
+				var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
+				var heightDelta = y - this.heightMin;
 
-			verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
+				this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
 
-		}
+			} else {
 
-		this.lon += this.mouseX * actualLookSpeed;
-		if ( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
+				this.autoSpeedFactor = 0.0;
 
-		this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
-		this.phi = THREE.Math.degToRad( 90 - this.lat );
+			}
 
-		this.theta = THREE.Math.degToRad( this.lon );
+			var actualMoveSpeed = delta * this.movementSpeed;
 
-		if ( this.constrainVertical ) {
+			if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
+			if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
 
-			this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax );
+			if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
+			if ( this.moveRight ) this.object.translateX( actualMoveSpeed );
 
-		}
+			if ( this.moveUp ) this.object.translateY( actualMoveSpeed );
+			if ( this.moveDown ) this.object.translateY( - actualMoveSpeed );
 
-		var targetPosition = this.target,
-			position = this.object.position;
+			var actualLookSpeed = delta * this.lookSpeed;
 
-		targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
-		targetPosition.y = position.y + 100 * Math.cos( this.phi );
-		targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
+			if ( ! this.activeLook ) {
 
-		this.object.lookAt( targetPosition );
+				actualLookSpeed = 0;
 
-	};
+			}
+
+			var verticalLookRatio = 1;
+
+			if ( this.constrainVertical ) {
+
+				verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
+
+			}
+
+			lon -= this.mouseX * actualLookSpeed;
+			if ( this.lookVertical ) lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
+
+			lat = Math.max( - 85, Math.min( 85, lat ) );
+
+			var phi = THREE.Math.degToRad( 90 - lat );
+			var theta = THREE.Math.degToRad( lon );
+
+			if ( this.constrainVertical ) {
+
+				phi = THREE.Math.mapLinear( phi, 0, Math.PI, this.verticalMin, this.verticalMax );
+
+			}
+
+			var position = this.object.position;
+
+			targetPosition.setFromSphericalCoords( 1, phi, theta ).add( position );
+
+			this.object.lookAt( targetPosition );
+
+		};
+
+	}();
 
 	function contextmenu( event ) {
 
@@ -295,6 +323,20 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 	}
 
+	function setOrientation( controls ) {
+
+		var quaternion = controls.object.quaternion;
+
+		lookDirection.set( 0, 0, - 1 ).applyQuaternion( quaternion );
+		spherical.setFromVector3( lookDirection );
+
+		lat = 90 - THREE.Math.radToDeg( spherical.phi );
+		lon = THREE.Math.radToDeg( spherical.theta );
+
+	}
+
 	this.handleResize();
 
+	setOrientation( this );
+
 };

+ 24 - 5
examples/js/controls/OrbitControls.js

@@ -537,32 +537,44 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 	function handleKeyDown( event ) {
 
-		//console.log( 'handleKeyDown' );
+		// console.log( 'handleKeyDown' );
+
+		var needsUpdate = false;
 
 		switch ( event.keyCode ) {
 
 			case scope.keys.UP:
 				pan( 0, scope.keyPanSpeed );
-				scope.update();
+				needsUpdate = true;
 				break;
 
 			case scope.keys.BOTTOM:
 				pan( 0, - scope.keyPanSpeed );
-				scope.update();
+				needsUpdate = true;
 				break;
 
 			case scope.keys.LEFT:
 				pan( scope.keyPanSpeed, 0 );
-				scope.update();
+				needsUpdate = true;
 				break;
 
 			case scope.keys.RIGHT:
 				pan( - scope.keyPanSpeed, 0 );
-				scope.update();
+				needsUpdate = true;
 				break;
 
 		}
 
+		if ( needsUpdate ) {
+
+			// prevent the browser from scrolling on cursor keys
+			event.preventDefault();
+
+			scope.update();
+
+		}
+
+
 	}
 
 	function handleTouchStartRotate( event ) {
@@ -673,8 +685,15 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		if ( scope.enabled === false ) return;
 
+		// Prevent the browser from scrolling.
+
 		event.preventDefault();
 
+		// Manually set the focus since calling preventDefault above
+		// prevents the browser from setting it automatically.
+
+		scope.domElement.focus ? scope.domElement.focus() : window.focus();
+
 		switch ( event.button ) {
 
 			case scope.mouseButtons.LEFT:

+ 0 - 14
examples/js/controls/TransformControls.js

@@ -113,7 +113,6 @@ THREE.TransformControls = function ( camera, domElement ) {
 		domElement.addEventListener( "touchend", onPointerUp, false );
 		domElement.addEventListener( "touchcancel", onPointerUp, false );
 		domElement.addEventListener( "touchleave", onPointerUp, false );
-		domElement.addEventListener( "contextmenu", onContext, false );
 
 	}
 
@@ -128,7 +127,6 @@ THREE.TransformControls = function ( camera, domElement ) {
 		domElement.removeEventListener( "touchend", onPointerUp );
 		domElement.removeEventListener( "touchcancel", onPointerUp );
 		domElement.removeEventListener( "touchleave", onPointerUp );
-		domElement.removeEventListener( "contextmenu", onContext );
 
 	};
 
@@ -517,12 +515,6 @@ THREE.TransformControls = function ( camera, domElement ) {
 
 	// mouse / touch event handlers
 
-	function onContext( event ) {
-
-		event.preventDefault();
-
-	}
-
 	function onPointerHover( event ) {
 
 		if ( !scope.enabled ) return;
@@ -535,8 +527,6 @@ THREE.TransformControls = function ( camera, domElement ) {
 
 		if ( !scope.enabled ) return;
 
-		event.preventDefault();
-
 		document.addEventListener( "mousemove", onPointerMove, false );
 
 		scope.pointerHover( getPointer( event ) );
@@ -548,8 +538,6 @@ THREE.TransformControls = function ( camera, domElement ) {
 
 		if ( !scope.enabled ) return;
 
-		event.preventDefault();
-
 		scope.pointerMove( getPointer( event ) );
 
 	}
@@ -558,8 +546,6 @@ THREE.TransformControls = function ( camera, domElement ) {
 
 		if ( !scope.enabled ) return;
 
-		event.preventDefault(); // Prevent MouseEvent on mobile
-
 		document.removeEventListener( "mousemove", onPointerMove, false );
 
 		scope.pointerUp( getPointer( event ) );

+ 11 - 3
examples/js/crossfade/scenes.js

@@ -101,11 +101,19 @@ function Scene( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
 
 		renderer.setClearColor( this.clearColor );
 
-		if ( rtt )
-			renderer.render( this.scene, this.camera, this.fbo, true );
-		else
+		if ( rtt ) {
+
+			renderer.setRenderTarget( this.fbo );
+			renderer.clear();
+			renderer.render( this.scene, this.camera );
+
+		} else {
+
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene, this.camera );
 
+		}
+
 	};
 
 }

+ 4 - 2
examples/js/crossfade/transition.js

@@ -1,4 +1,4 @@
-function Transition ( sceneA, sceneB ) {
+function Transition( sceneA, sceneB ) {
 
 	this.scene = new THREE.Scene();
 
@@ -157,7 +157,9 @@ function Transition ( sceneA, sceneB ) {
 
 			this.sceneA.render( delta, true );
 			this.sceneB.render( delta, true );
-			renderer.render( this.scene, this.cameraOrtho, null, true );
+			renderer.setRenderTarget( null );
+			renderer.clear();
+			renderer.render( this.scene, this.cameraOrtho );
 
 		}
 

+ 13 - 2
examples/js/effects/AnaglyphEffect.js

@@ -130,16 +130,27 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 
 	this.render = function ( scene, camera ) {
 
+		var currentRenderTarget = renderer.getRenderTarget();
+
 		scene.updateMatrixWorld();
 
 		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		_stereo.update( camera );
 
-		renderer.render( scene, _stereo.cameraL, _renderTargetL, true );
-		renderer.render( scene, _stereo.cameraR, _renderTargetR, true );
+		renderer.setRenderTarget( _renderTargetL );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraL );
+
+		renderer.setRenderTarget( _renderTargetR );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraR );
+
+		renderer.setRenderTarget( null );
 		renderer.render( _scene, _camera );
 
+		renderer.setRenderTarget( currentRenderTarget );
+
 	};
 
 	this.dispose = function () {

+ 26 - 6
examples/js/effects/OutlineEffect.js

@@ -402,11 +402,31 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	}
 
-	this.render = function ( scene, camera, renderTarget, forceClear ) {
+	this.render = function ( scene, camera ) {
+
+		var renderTarget;
+		var forceClear;
+
+		if ( arguments[ 2 ] !== undefined ) {
+
+			console.warn( 'THREE.OutlineEffect.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
+			renderTarget = arguments[ 2 ];
+
+		}
+
+		if ( arguments[ 3 ] !== undefined ) {
+
+			console.warn( 'THREE.OutlineEffect.render(): the forceClear argument has been removed. Use .clear() instead.' );
+			forceClear = arguments[ 3 ];
+
+		}
+
+		renderer.setRenderTarget( renderTarget );
+		if ( forceClear ) renderer.clear();
 
 		if ( this.enabled === false ) {
 
-			renderer.render( scene, camera, renderTarget, forceClear );
+			renderer.render( scene, camera );
 			return;
 
 		}
@@ -415,7 +435,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 		renderer.autoClear = this.autoClear;
 
 		// 1. render normally
-		renderer.render( scene, camera, renderTarget, forceClear );
+		renderer.render( scene, camera );
 
 		// 2. render outline
 		var currentSceneAutoUpdate = scene.autoUpdate;
@@ -429,7 +449,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 		scene.traverse( setOutlineMaterial );
 
-		renderer.render( scene, camera, renderTarget );
+		renderer.render( scene, camera );
 
 		scene.traverse( restoreOriginalMaterial );
 
@@ -478,9 +498,9 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	};
 
-	this.getSize = function () {
+	this.getSize = function ( target ) {
 
-		return renderer.getSize();
+		return renderer.getSize( target );
 
 	};
 

+ 9 - 2
examples/js/effects/ParallaxBarrierEffect.js

@@ -87,8 +87,15 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 		_stereo.update( camera );
 
-		renderer.render( scene, _stereo.cameraL, _renderTargetL, true );
-		renderer.render( scene, _stereo.cameraR, _renderTargetR, true );
+		renderer.setRenderTarget( _renderTargetL );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraL );
+
+		renderer.setRenderTarget( _renderTargetR );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraR );
+
+		renderer.setRenderTarget( null );
 		renderer.render( _scene, _camera );
 
 	};

+ 2 - 1
examples/js/effects/StereoEffect.js

@@ -9,6 +9,7 @@ THREE.StereoEffect = function ( renderer ) {
 
 	var _stereo = new THREE.StereoCamera();
 	_stereo.aspect = 0.5;
+	var size = new THREE.Vector2();
 
 	this.setEyeSeparation = function ( eyeSep ) {
 
@@ -30,7 +31,7 @@ THREE.StereoEffect = function ( renderer ) {
 
 		_stereo.update( camera );
 
-		var size = renderer.getSize();
+		renderer.getSize( size );
 
 		if ( renderer.autoClear ) renderer.clear();
 		renderer.setScissorTest( true );

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

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

+ 280 - 25
examples/js/exporters/GLTFExporter.js

@@ -365,7 +365,7 @@ THREE.GLTFExporter.prototype = {
 		 */
 		function applyTextureTransform( mapDef, texture ) {
 
-			var didTransform = false
+			var didTransform = false;
 			var transformDef = {};
 
 			if ( texture.offset.x !== 0 || texture.offset.y !== 0 ) {
@@ -385,7 +385,7 @@ THREE.GLTFExporter.prototype = {
 			if ( texture.repeat.x !== 1 || texture.repeat.y !== 1 ) {
 
 				transformDef.scale = texture.repeat.toArray();
-				didTransform = true;				
+				didTransform = true;
 
 			}
 
@@ -981,7 +981,10 @@ THREE.GLTFExporter.prototype = {
 			// occlusionTexture
 			if ( material.aoMap ) {
 
-				var occlusionMapDef = { index: processTexture( material.aoMap ) };
+				var occlusionMapDef = {
+					index: processTexture( material.aoMap ),
+					texCoord: 1
+				};
 
 				if ( material.aoMapIntensity !== 1.0 ) {
 
@@ -1076,6 +1079,8 @@ THREE.GLTFExporter.prototype = {
 
 				if ( ! geometry.isBufferGeometry ) {
 
+					console.warn( 'GLTFExporter: Exporting THREE.Geometry will increase file size. Use THREE.BufferGeometry instead.' );
+
 					var geometryTemp = new THREE.BufferGeometry();
 					geometryTemp.fromGeometry( geometry );
 					geometry = geometryTemp;
@@ -1227,9 +1232,9 @@ THREE.GLTFExporter.prototype = {
 
 						var baseAttribute = geometry.attributes[ attributeName ];
 
-						if ( cachedData.attributes.has( baseAttribute ) ) {
+						if ( cachedData.attributes.has( attribute ) ) {
 
-							target[ gltfAttributeName ] = cachedData.attributes.get( baseAttribute );
+							target[ gltfAttributeName ] = cachedData.attributes.get( attribute );
 							continue;
 
 						}
@@ -1405,7 +1410,7 @@ THREE.GLTFExporter.prototype = {
 				gltfCamera.perspective = {
 
 					aspectRatio: camera.aspect,
-					yfov: THREE.Math.degToRad( camera.fov ) / camera.aspect,
+					yfov: THREE.Math.degToRad( camera.fov ),
 					zfar: camera.far <= 0 ? 0.001 : camera.far,
 					znear: camera.near < 0 ? 0 : camera.near
 
@@ -1443,12 +1448,15 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
+			clip = THREE.GLTFExporter.Utils.mergeMorphTargetTracks( clip.clone(), root );
+
+			var tracks = clip.tracks;
 			var channels = [];
 			var samplers = [];
 
-			for ( var i = 0; i < clip.tracks.length; ++ i ) {
+			for ( var i = 0; i < tracks.length; ++ i ) {
 
-				var track = clip.tracks[ i ];
+				var track = tracks[ i ];
 				var trackBinding = THREE.PropertyBinding.parseTrackName( track.name );
 				var trackNode = THREE.PropertyBinding.findNode( root, trackBinding.nodeName );
 				var trackProperty = PATH_PROPERTIES[ trackBinding.propertyName ];
@@ -1479,16 +1487,6 @@ THREE.GLTFExporter.prototype = {
 
 				if ( trackProperty === PATH_PROPERTIES.morphTargetInfluences ) {
 
-					if ( trackNode.morphTargetInfluences.length !== 1 &&
-						trackBinding.propertyIndex !== undefined ) {
-
-						console.warn( 'THREE.GLTFExporter: Skipping animation track "%s". ' +
-							'Morph target keyframe tracks must target all available morph targets ' +
-							'for the given mesh.', track.name );
-						continue;
-
-					}
-
 					outputItemSize /= trackNode.morphTargetInfluences.length;
 
 				}
@@ -1591,6 +1589,59 @@ THREE.GLTFExporter.prototype = {
 
 		}
 
+		function processLight( light ) {
+
+			var lightDef = {};
+
+			if ( light.name ) lightDef.name = light.name;
+
+			lightDef.color = light.color.toArray();
+
+			lightDef.intensity = light.intensity;
+
+			if ( light.isDirectionalLight ) {
+
+				lightDef.type = 'directional';
+
+			} else if ( light.isPointLight ) {
+
+				lightDef.type = 'point';
+				if ( light.distance > 0 ) lightDef.range = light.distance;
+
+			} else if ( light.isSpotLight ) {
+
+				lightDef.type = 'spot';
+				if ( light.distance > 0 ) lightDef.range = light.distance;
+				lightDef.spot = {};
+				lightDef.spot.innerConeAngle = ( light.penumbra - 1.0 ) * light.angle * - 1.0;
+				lightDef.spot.outerConeAngle = light.angle;
+
+			}
+
+			if ( light.decay !== undefined && light.decay !== 2 ) {
+
+				console.warn( 'THREE.GLTFExporter: Light decay may be lost. glTF is physically-based, '
+					+ 'and expects light.decay=2.' );
+
+			}
+
+			if ( light.target
+					&& ( light.target.parent !== light
+					 || light.target.position.x !== 0
+					 || light.target.position.y !== 0
+					 || light.target.position.z !== - 1 ) ) {
+
+				console.warn( 'THREE.GLTFExporter: Light direction may be lost. For best results, '
+					+ 'make light.target a child of the light with position 0,0,-1.' );
+
+			}
+
+			var lights = outputJSON.extensions[ 'KHR_lights_punctual' ].lights;
+			lights.push( lightDef );
+			return lights.length - 1;
+
+		}
+
 		/**
 		 * Process Object3D node
 		 * @param  {THREE.Object3D} node Object3D to processNode
@@ -1598,13 +1649,6 @@ THREE.GLTFExporter.prototype = {
 		 */
 		function processNode( object ) {
 
-			if ( object.isLight ) {
-
-				console.warn( 'GLTFExporter: Unsupported node type:', object.constructor.name );
-				return null;
-
-			}
-
 			if ( ! outputJSON.nodes ) {
 
 				outputJSON.nodes = [];
@@ -1675,6 +1719,24 @@ THREE.GLTFExporter.prototype = {
 
 				gltfNode.camera = processCamera( object );
 
+			} else if ( object.isDirectionalLight || object.isPointLight || object.isSpotLight ) {
+
+				if ( ! extensionsUsed[ 'KHR_lights_punctual' ] ) {
+
+					outputJSON.extensions = outputJSON.extensions || {};
+					outputJSON.extensions[ 'KHR_lights_punctual' ] = { lights: [] };
+					extensionsUsed[ 'KHR_lights_punctual' ] = true;
+
+				}
+
+				gltfNode.extensions = gltfNode.extensions || {};
+				gltfNode.extensions[ 'KHR_lights_punctual' ] = { light: processLight( object ) };
+
+			} else if ( object.isLight ) {
+
+				console.warn( 'THREE.GLTFExporter: Only directional, point, and spot lights are supported.' );
+				return null;
+
 			}
 
 			if ( object.isSkinnedMesh ) {
@@ -1942,3 +2004,196 @@ THREE.GLTFExporter.prototype = {
 	}
 
 };
+
+THREE.GLTFExporter.Utils = {
+
+	insertKeyframe: function ( track, time ) {
+
+		var tolerance = 0.001; // 1ms
+		var valueSize = track.getValueSize();
+
+		var times = new track.TimeBufferType( track.times.length + 1 );
+		var values = new track.ValueBufferType( track.values.length + valueSize );
+		var interpolant = track.createInterpolant( new track.ValueBufferType( valueSize ) );
+
+		var index;
+
+		if ( track.times.length === 0 ) {
+
+			times[ 0 ] = time;
+
+			for ( var i = 0; i < valueSize; i ++ ) {
+
+				values[ i ] = 0;
+
+			}
+
+			index = 0;
+
+		} else if ( time < track.times[ 0 ] ) {
+
+			if ( Math.abs( track.times[ 0 ] - time ) < tolerance ) return 0;
+
+			times[ 0 ] = time;
+			times.set( track.times, 1 );
+
+			values.set( interpolant.evaluate( time ), 0 );
+			values.set( track.values, valueSize );
+
+			index = 0;
+
+		} else if ( time > track.times[ track.times.length - 1 ] ) {
+
+			if ( Math.abs( track.times[ track.times.length - 1 ] - time ) < tolerance ) {
+
+				return track.times.length - 1;
+
+			}
+
+			times[ times.length - 1 ] = time;
+			times.set( track.times, 0 );
+
+			values.set( track.values, 0 );
+			values.set( interpolant.evaluate( time ), track.values.length );
+
+			index = times.length - 1;
+
+		} else {
+
+			for ( var i = 0; i < track.times.length; i ++ ) {
+
+				if ( Math.abs( track.times[ i ] - time ) < tolerance ) return i;
+
+				if ( track.times[ i ] < time && track.times[ i + 1 ] > time ) {
+
+					times.set( track.times.slice( 0, i + 1 ), 0 );
+					times[ i + 1 ] = time;
+					times.set( track.times.slice( i + 1 ), i + 2 );
+
+					values.set( track.values.slice( 0, ( i + 1 ) * valueSize ), 0 );
+					values.set( interpolant.evaluate( time ), ( i + 1 ) * valueSize );
+					values.set( track.values.slice( ( i + 1 ) * valueSize ), ( i + 2 ) * valueSize );
+
+					index = i + 1;
+
+					break;
+
+				}
+
+			}
+
+		}
+
+		track.times = times;
+		track.values = values;
+
+		return index;
+
+	},
+
+	mergeMorphTargetTracks: function ( clip, root ) {
+
+		var tracks = [];
+		var mergedTracks = {};
+		var sourceTracks = clip.tracks;
+
+		for ( var i = 0; i < sourceTracks.length; ++ i ) {
+
+			var sourceTrack = sourceTracks[ i ];
+			var sourceTrackBinding = THREE.PropertyBinding.parseTrackName( sourceTrack.name );
+			var sourceTrackNode = THREE.PropertyBinding.findNode( root, sourceTrackBinding.nodeName );
+
+			if ( sourceTrackBinding.propertyName !== 'morphTargetInfluences' || sourceTrackBinding.propertyIndex === undefined ) {
+
+				// Tracks that don't affect morph targets, or that affect all morph targets together, can be left as-is.
+				tracks.push( sourceTrack );
+				continue;
+
+			}
+
+			if ( sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodDiscrete
+				&& sourceTrack.createInterpolant !== sourceTrack.InterpolantFactoryMethodLinear ) {
+
+				if ( sourceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
+
+					// This should never happen, because glTF morph target animations
+					// affect all targets already.
+					throw new Error( 'THREE.GLTFExporter: Cannot merge tracks with glTF CUBICSPLINE interpolation.' );
+
+				}
+
+				console.warn( 'THREE.GLTFExporter: Morph target interpolation mode not yet supported. Using LINEAR instead.' );
+
+				sourceTrack = sourceTrack.clone();
+				sourceTrack.setInterpolation( InterpolateLinear );
+
+			}
+
+			var targetCount = sourceTrackNode.morphTargetInfluences.length;
+			var targetIndex = sourceTrackNode.morphTargetDictionary[ sourceTrackBinding.propertyIndex ];
+
+			if ( targetIndex === undefined ) {
+
+				throw new Error( 'THREE.GLTFExporter: Morph target name not found: ' + sourceTrackBinding.propertyIndex );
+
+			}
+
+			var mergedTrack;
+
+			// If this is the first time we've seen this object, create a new
+			// track to store merged keyframe data for each morph target.
+			if ( mergedTracks[ sourceTrackNode.uuid ] === undefined ) {
+
+				mergedTrack = sourceTrack.clone();
+
+				var values = new mergedTrack.ValueBufferType( targetCount * mergedTrack.times.length );
+
+				for ( var j = 0; j < mergedTrack.times.length; j ++ ) {
+
+					values[ j * targetCount + targetIndex ] = mergedTrack.values[ j ];
+
+				}
+
+				mergedTrack.name = '.morphTargetInfluences';
+				mergedTrack.values = values;
+
+				mergedTracks[ sourceTrackNode.uuid ] = mergedTrack;
+				tracks.push( mergedTrack );
+
+				continue;
+
+			}
+
+			var mergedKeyframeIndex = 0;
+			var sourceKeyframeIndex = 0;
+			var sourceInterpolant = sourceTrack.createInterpolant( new sourceTrack.ValueBufferType( 1 ) );
+
+			mergedTrack = mergedTracks[ sourceTrackNode.uuid ];
+
+			// For every existing keyframe of the merged track, write a (possibly
+			// interpolated) value from the source track.
+			for ( var j = 0; j < mergedTrack.times.length; j ++ ) {
+
+				mergedTrack.values[ j * targetCount + targetIndex ] = sourceInterpolant.evaluate( mergedTrack.times[ j ] );
+
+			}
+
+			// For every existing keyframe of the source track, write a (possibly
+			// new) keyframe to the merged track. Values from the previous loop may
+			// be written again, but keyframes are de-duplicated.
+			for ( var j = 0; j < sourceTrack.times.length; j ++ ) {
+
+				var keyframeIndex = this.insertKeyframe( mergedTrack, sourceTrack.times[ j ] );
+				mergedTrack.values[ keyframeIndex * targetCount + targetIndex ] = sourceTrack.values[ j ];
+
+			}
+
+		}
+
+		clip.tracks = tracks;
+
+		return clip;
+
+	}
+
+};

+ 7 - 3
examples/js/loaders/AssimpJSONLoader.js

@@ -169,12 +169,13 @@ THREE.AssimpJSONLoader.prototype = {
 
 						// prop.semantic gives the type of the texture
 						// 1: diffuse
-						// 2: specular mao
+						// 2: specular map
+						// 4: emissive map
 						// 5: height map (bumps)
 						// 6: normal map
-						// more values (i.e. emissive, environment) are known by assimp and may be relevant
+						// more values (i.e. environment, etc) are known by assimp and may be relevant
 
-						if ( semantic === 1 || semantic === 2 || semantic === 5 || semantic === 6 ) {
+						if ( semantic === 1 || semantic === 2 || semantic === 4 || semantic === 5 || semantic === 6 ) {
 
 							var keyname;
 
@@ -186,6 +187,9 @@ THREE.AssimpJSONLoader.prototype = {
 								case 2:
 									keyname = 'specularMap';
 									break;
+								case 4:
+									keyname = 'emissiveMap';
+									break;
 								case 5:
 									keyname = 'bumpMap';
 									break;

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

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

+ 14 - 4
examples/js/loaders/EquirectangularToCubeGenerator.js

@@ -11,6 +11,8 @@ THREE.CubemapGenerator = function ( renderer ) {
 
 THREE.CubemapGenerator.prototype.fromEquirectangular = function ( texture, options ) {
 
+	options = options || {};
+
 	var scene = new THREE.Scene();
 
 	var shader = {
@@ -92,9 +94,9 @@ THREE.CubemapGenerator.prototype.fromEquirectangular = function ( texture, optio
 		type: texture.type,
 		format: texture.format,
 		encoding: texture.encoding,
-		generateMipmaps: ( options.generateMipmaps !== undefined ) ?  options.generateMipmaps : texture.generateMipmaps,
-		minFilter: ( options.minFilter !== undefined ) ?  options.minFilter : texture.minFilter,
-		magFilter: ( options.magFilter !== undefined ) ?  options.magFilter : texture.magFilter
+		generateMipmaps: ( options.generateMipmaps !== undefined ) ? options.generateMipmaps : texture.generateMipmaps,
+		minFilter: ( options.minFilter !== undefined ) ? options.minFilter : texture.minFilter,
+		magFilter: ( options.magFilter !== undefined ) ? options.magFilter : texture.magFilter
 	};
 
 	var camera = new THREE.CubeCamera( 1, 10, resolution, params );
@@ -120,6 +122,8 @@ THREE.EquirectangularToCubeGenerator = ( function () {
 
 	var EquirectangularToCubeGenerator = function ( sourceTexture, options ) {
 
+		options = options || {};
+
 		this.sourceTexture = sourceTexture;
 		this.resolution = options.resolution || 512;
 
@@ -152,6 +156,8 @@ THREE.EquirectangularToCubeGenerator = ( function () {
 
 		update: function ( renderer ) {
 
+			var currentRenderTarget = renderer.getRenderTarget();
+
 			boxMesh.material.uniforms.equirectangularMap.value = this.sourceTexture;
 
 			for ( var i = 0; i < 6; i ++ ) {
@@ -164,10 +170,14 @@ THREE.EquirectangularToCubeGenerator = ( function () {
 				camera.up.set( v.u[ 0 ], v.u[ 1 ], v.u[ 2 ] );
 				camera.lookAt( v.t[ 0 ], v.t[ 1 ], v.t[ 2 ] );
 
-				renderer.render( scene, camera, this.renderTarget, true );
+				renderer.setRenderTarget( this.renderTarget );
+				renderer.clear();
+				renderer.render( scene, camera );
 
 			}
 
+			renderer.setRenderTarget( currentRenderTarget );
+
 			return this.renderTarget.texture;
 
 		},

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

@@ -44,6 +44,7 @@ THREE.FBXLoader = ( function () {
 			var path = ( self.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : self.path;
 
 			var loader = new THREE.FileLoader( this.manager );
+			loader.setPath( self.path );
 			loader.setResponseType( 'arraybuffer' );
 
 			loader.load( url, function ( buffer ) {

+ 26 - 13
examples/js/loaders/GLTFLoader.js

@@ -338,7 +338,7 @@ THREE.GLTFLoader = ( function () {
 
 			case 'directional':
 				lightNode = new THREE.DirectionalLight( color );
-				lightNode.target.position.set( 0, 0, -1 );
+				lightNode.target.position.set( 0, 0, - 1 );
 				lightNode.add( lightNode.target );
 				break;
 
@@ -356,7 +356,7 @@ THREE.GLTFLoader = ( function () {
 				lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
 				lightNode.angle = lightDef.spot.outerConeAngle;
 				lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
-				lightNode.target.position.set( 0, 0, -1 );
+				lightNode.target.position.set( 0, 0, - 1 );
 				lightNode.add( lightNode.target );
 				break;
 
@@ -365,6 +365,10 @@ THREE.GLTFLoader = ( function () {
 
 		}
 
+		// Some lights (e.g. spot) default to a position other than the origin. Reset the position
+		// here, because node-level parsing will only override position if explicitly specified.
+		lightNode.position.set( 0, 0, 0 );
+
 		lightNode.decay = 2;
 
 		if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
@@ -964,6 +968,7 @@ THREE.GLTFLoader = ( function () {
 					uniforms.refractionRatio.value = material.refractionRatio;
 
 					uniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;
+
 				}
 
 				uniforms.specular.value.copy( material.specular );
@@ -1197,6 +1202,7 @@ THREE.GLTFLoader = ( function () {
 	var ATTRIBUTES = {
 		POSITION: 'position',
 		NORMAL: 'normal',
+		TANGENT: 'tangent',
 		TEXCOORD_0: 'uv',
 		TEXCOORD_1: 'uv2',
 		COLOR_0: 'color',
@@ -1848,7 +1854,7 @@ THREE.GLTFLoader = ( function () {
 
 				case 'light':
 					dependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
-					break
+					break;
 
 				default:
 					throw new Error( 'Unknown type: ' + type );
@@ -2227,6 +2233,18 @@ THREE.GLTFLoader = ( function () {
 
 		return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
 
+			switch ( mapName ) {
+
+				case 'aoMap':
+				case 'emissiveMap':
+				case 'metalnessMap':
+				case 'normalMap':
+				case 'roughnessMap':
+					texture.format = THREE.RGBFormat;
+					break;
+
+			}
+
 			if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
 
 				var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;
@@ -2392,14 +2410,6 @@ THREE.GLTFLoader = ( function () {
 
 			if ( materialDef.name !== undefined ) material.name = materialDef.name;
 
-			// Normal map textures use OpenGL conventions:
-			// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
-			if ( material.normalScale ) {
-
-				material.normalScale.y = - material.normalScale.y;
-
-			}
-
 			// baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
 			if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
 			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
@@ -2757,6 +2767,7 @@ THREE.GLTFLoader = ( function () {
 
 					var materials = isMultiMaterial ? mesh.material : [ mesh.material ];
 
+					var useVertexTangents = geometry.attributes.tangent !== undefined;
 					var useVertexColors = geometry.attributes.color !== undefined;
 					var useFlatShading = geometry.attributes.normal === undefined;
 					var useSkinning = mesh.isSkinnedMesh === true;
@@ -2809,12 +2820,13 @@ THREE.GLTFLoader = ( function () {
 						}
 
 						// Clone the material if it will be modified
-						if ( useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
+						if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {
 
 							var cacheKey = 'ClonedMaterial:' + material.uuid + ':';
 
 							if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
 							if ( useSkinning ) cacheKey += 'skinning:';
+							if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
 							if ( useVertexColors ) cacheKey += 'vertex-colors:';
 							if ( useFlatShading ) cacheKey += 'flat-shading:';
 							if ( useMorphTargets ) cacheKey += 'morph-targets:';
@@ -2829,6 +2841,7 @@ THREE.GLTFLoader = ( function () {
 									: material.clone();
 
 								if ( useSkinning ) cachedMaterial.skinning = true;
+								if ( useVertexTangents ) cachedMaterial.vertexTangents = true;
 								if ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;
 								if ( useFlatShading ) cachedMaterial.flatShading = true;
 								if ( useMorphTargets ) cachedMaterial.morphTargets = true;
@@ -3129,7 +3142,7 @@ THREE.GLTFLoader = ( function () {
 
 		var nodeDef = json.nodes[ nodeIndex ];
 
-		return ( function() {
+		return ( function () {
 
 			// .isBone isn't in glTF spec. See .markDefs
 			if ( nodeDef.isBone === true ) {

+ 57 - 67
examples/js/loaders/LDrawLoader.js

@@ -66,13 +66,13 @@ THREE.LDrawLoader = ( function () {
 
 		},
 
-		getRemainingString: function() {
+		getRemainingString: function () {
 
 			return this.line.substring( this.currentCharIndex, this.lineLength );
 
 		},
 
-		isAtTheEnd: function() {
+		isAtTheEnd: function () {
 
 			return this.currentCharIndex >= this.lineLength;
 
@@ -86,21 +86,27 @@ THREE.LDrawLoader = ( function () {
 
 		getLineNumberString: function () {
 
-			return this.lineNumber >= 0? " at line " + this.lineNumber: "";
+			return this.lineNumber >= 0 ? " at line " + this.lineNumber : "";
 
 		}
 
 
 	};
 
-	function sortByMaterial ( a, b ) {
+	function sortByMaterial( a, b ) {
 
 		if ( a.colourCode === b.colourCode ) {
+
 			return 0;
+
 		}
+
 		if ( a.colourCode < b.colourCode ) {
-			return -1;
+
+			return - 1;
+
 		}
+
 		return 1;
 
 	}
@@ -149,14 +155,14 @@ THREE.LDrawLoader = ( function () {
 				index0 = iElem * elementSize;
 				numGroupVerts = elementSize;
 
-			}
-			else {
+			} else {
 
 				numGroupVerts += elementSize;
 
 			}
 
 		}
+
 		if ( numGroupVerts > 0 ) {
 
 			bufferGeometry.addGroup( index0, Infinity, materials.length - 1 );
@@ -166,12 +172,12 @@ THREE.LDrawLoader = ( function () {
 		bufferGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
 
 		var object3d = null;
+
 		if ( elementSize === 2 ) {
 
 			object3d = new THREE.LineSegments( bufferGeometry, materials );
 
-		}
-		else if ( elementSize === 3 ) {
+		} else if ( elementSize === 3 ) {
 
 			bufferGeometry.computeVertexNormals();
 
@@ -259,7 +265,7 @@ THREE.LDrawLoader = ( function () {
 
 			var fileLoader = new THREE.FileLoader( this.manager );
 			fileLoader.setPath( this.path );
-			fileLoader.load( url, function( text ) {
+			fileLoader.load( url, function ( text ) {
 
 				processObject( text, onLoad );
 
@@ -308,10 +314,10 @@ THREE.LDrawLoader = ( function () {
 							finalizeObject();
 
 						}
+
 					}
 
-				}
-				else {
+				} else {
 
 					// No subobjects, finish object
 					finalizeObject();
@@ -349,7 +355,7 @@ THREE.LDrawLoader = ( function () {
 
 				}
 
-				function loadSubobject ( subobject, sync ) {
+				function loadSubobject( subobject, sync ) {
 
 					parseScope.mainColourCode = subobject.material.userData.code;
 					parseScope.mainEdgeColourCode = subobject.material.userData.edgeMaterial.userData.code;
@@ -416,8 +422,7 @@ THREE.LDrawLoader = ( function () {
 								// Try absolute path
 								newLocationState = LDrawLoader.FILE_LOCATION_NOT_FOUND;
 
-							}
-							else {
+							} else {
 
 								// Next attempt is lower case
 								subobject.fileName = subobject.fileName.toLowerCase();
@@ -442,8 +447,7 @@ THREE.LDrawLoader = ( function () {
 								scope.removeScopeLevel();
 								onProcessed( objGroup );
 
-							}
-							else {
+							} else {
 
 								// Load next subobject
 								loadSubobject( parseScope.subobjects[ parseScope.subobjectIndex ] );
@@ -485,8 +489,7 @@ THREE.LDrawLoader = ( function () {
 
 						loadSubobject( parseScope.subobjects[ parseScope.subobjectIndex ] );
 
-					}
-					else {
+					} else {
 
 						finalizeObject();
 
@@ -494,7 +497,7 @@ THREE.LDrawLoader = ( function () {
 
 				}
 
-				function addSubobject ( subobject, subobjectGroup ) {
+				function addSubobject( subobject, subobjectGroup ) {
 
 					if ( scope.separateObjects ) {
 
@@ -546,7 +549,7 @@ THREE.LDrawLoader = ( function () {
 
 		},
 
-		setFileMap: function( fileMap ) {
+		setFileMap: function ( fileMap ) {
 
 			this.fileMap = fileMap;
 
@@ -601,7 +604,7 @@ THREE.LDrawLoader = ( function () {
 
 		},
 
-		removeScopeLevel: function() {
+		removeScopeLevel: function () {
 
 			this.parseScopesStack.pop();
 
@@ -641,7 +644,7 @@ THREE.LDrawLoader = ( function () {
 
 			}
 
-			for ( var i = this.parseScopesStack.length - 1; i >= 0; i-- ) {
+			for ( var i = this.parseScopesStack.length - 1; i >= 0; i -- ) {
 
 				var material = this.parseScopesStack[ i ].lib[ colourCode ];
 
@@ -736,9 +739,10 @@ THREE.LDrawLoader = ( function () {
 
 							colour = '#' + colour.substring( 2 );
 
-						}
-						else if ( ! colour.startsWith( '#' ) ) {
+						} else if ( ! colour.startsWith( '#' ) ) {
+
 							throw 'LDrawLoader: Invalid colour while parsing material' + lineParser.getLineNumberString() + ".";
+
 						}
 						break;
 
@@ -749,8 +753,7 @@ THREE.LDrawLoader = ( function () {
 
 							edgeColour = '#' + edgeColour.substring( 2 );
 
-						}
-						else if ( ! edgeColour.startsWith( '#' ) ) {
+						} else if ( ! edgeColour.startsWith( '#' ) ) {
 
 							// Try to see if edge colour is a colour code
 							edgeMaterial = this.getMaterial( edgeColour );
@@ -849,13 +852,13 @@ THREE.LDrawLoader = ( function () {
 						// Default plastic material with shiny specular
 						hsl.l = Math.min( 1, hsl.l + ( 1 - hsl.l ) * 0.12 );
 
-					}
-					else {
+					} else {
 
 						// Try to imitate pearlescency by setting the specular to the complementary of the color, and low shininess
 						hsl.h = ( hsl.h + 0.5 ) % 1;
 						hsl.l = Math.min( 1, hsl.l + ( 1 - hsl.l ) * 0.7 );
 						shininess = 10;
+
 					}
 
 					specular.setHSL( hsl.h, hsl.s, hsl.l );
@@ -891,6 +894,7 @@ THREE.LDrawLoader = ( function () {
 				default:
 					// Should not happen
 					break;
+
 			}
 
 			// BFC (Back Face Culling) LDraw language meta extension is not implemented, so set all materials double-sided:
@@ -902,15 +906,19 @@ THREE.LDrawLoader = ( function () {
 			material.userData.canHaveEnvMap = canHaveEnvMap;
 
 			if ( luminance !== 0 ) {
+
 				material.emissive.set( material.color ).multiplyScalar( luminance );
+
 			}
 
 			if ( ! edgeMaterial ) {
+
 				// This is the material used for edges
 				edgeMaterial = new THREE.LineBasicMaterial( { color: edgeColour } );
 				edgeMaterial.userData.code = code;
 				edgeMaterial.name = name + " - Edge";
 				edgeMaterial.userData.canHaveEnvMap = false;
+
 			}
 
 			material.userData.code = code;
@@ -948,8 +956,7 @@ THREE.LDrawLoader = ( function () {
 				triangles = [];
 				lineSegments = [];
 
-			}
-			else {
+			} else {
 
 				if ( this.currentGroupObject === null ) {
 
@@ -1014,7 +1021,7 @@ THREE.LDrawLoader = ( function () {
 
 			}
 
-			function parseVector ( lp ) {
+			function parseVector( lp ) {
 
 				var v = new THREE.Vector3( parseFloat( lp.getToken() ), parseFloat( lp.getToken() ), parseFloat( lp.getToken() ) );
 
@@ -1028,24 +1035,10 @@ THREE.LDrawLoader = ( function () {
 
 			}
 
-			function findSubobject( fileName ) {
-
-				for ( var i = 0, n = subobjects.length; i < n; i ++ ) {
-
-					if ( subobjects[ i ].fileName === fileName ) {
-						return subobjects[ i ];
-					}
-
-					return null;
-
-				}
-
-			}
-
 			// Parse all line commands
 			for ( lineIndex = 0; lineIndex < numLines; lineIndex ++ ) {
 
-				line = lines[ lineIndex ];
+				var line = lines[ lineIndex ];
 
 				if ( line.length === 0 ) continue;
 
@@ -1060,8 +1053,7 @@ THREE.LDrawLoader = ( function () {
 						currentEmbeddedFileName = line.substring( 7 );
 						currentEmbeddedText = '';
 
-					}
-					else {
+					} else {
 
 						currentEmbeddedText += line + '\n';
 
@@ -1076,8 +1068,10 @@ THREE.LDrawLoader = ( function () {
 				lp.seekNonSpace();
 
 				if ( lp.isAtTheEnd() ) {
+
 					// Empty line
 					continue;
+
 				}
 
 				// Parse the line type
@@ -1102,10 +1096,9 @@ THREE.LDrawLoader = ( function () {
 
 										this.addMaterial( material );
 
-									}
-									else {
+									}	else {
 
-										console.warn( 'LDrawLoader: Error parsing material' + lineParser.getLineNumberString() );
+										console.warn( 'LDrawLoader: Error parsing material' + lp.getLineNumberString() );
 
 									}
 									break;
@@ -1117,22 +1110,22 @@ THREE.LDrawLoader = ( function () {
 
 								case '!KEYWORDS':
 
-										var newKeywords = lp.getRemainingString().split( ',' );
-										if ( newKeywords.length > 0 ) {
+									var newKeywords = lp.getRemainingString().split( ',' );
+									if ( newKeywords.length > 0 ) {
 
-											if ( ! keywords ) {
+										if ( ! keywords ) {
 
-												keywords = [];
+											keywords = [];
 
-											}
+										}
 
-											newKeywords.forEach( function( keyword ) {
+										newKeywords.forEach( function ( keyword ) {
 
-												keywords.push( keyword.trim() );
+											keywords.push( keyword.trim() );
 
-											} );
+										} );
 
-										}
+									}
 									break;
 
 								case 'FILE':
@@ -1190,16 +1183,14 @@ THREE.LDrawLoader = ( function () {
 							// Found the subobject path in the preloaded file path map
 							fileName = scope.fileMap[ fileName ];
 
-						}
-						else {
+						}	else {
 
 							// Standardized subfolders
 							if ( fileName.startsWith( 's/' ) ) {
 
 								fileName = 'parts/' + fileName;
 
-							}
-							else if ( fileName.startsWith( '48/' ) ) {
+							} else if ( fileName.startsWith( '48/' ) ) {
 
 								fileName = 'p/' + fileName;
 
@@ -1316,8 +1307,7 @@ THREE.LDrawLoader = ( function () {
 
 				}
 
-			}
-			else {
+			} else {
 
 				groupObject = this.currentGroupObject;
 

+ 19 - 4
examples/js/loaders/SVGLoader.js

@@ -162,6 +162,7 @@ THREE.SVGLoader.prototype = {
 							} else {
 								path.lineTo( point.x, point.y );
 							}
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -172,6 +173,7 @@ THREE.SVGLoader.prototype = {
 							control.x = point.x;
 							control.y = point.y;
 							path.lineTo( point.x, point.y );
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -182,6 +184,7 @@ THREE.SVGLoader.prototype = {
 							control.x = point.x;
 							control.y = point.y;
 							path.lineTo( point.x, point.y );
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -193,6 +196,7 @@ THREE.SVGLoader.prototype = {
 							control.x = point.x;
 							control.y = point.y;
 							path.lineTo( point.x, point.y );
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -211,6 +215,7 @@ THREE.SVGLoader.prototype = {
 							control.y = numbers[ j + 3 ];
 							point.x = numbers[ j + 4 ];
 							point.y = numbers[ j + 5 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -229,6 +234,7 @@ THREE.SVGLoader.prototype = {
 							control.y = numbers[ j + 1 ];
 							point.x = numbers[ j + 2 ];
 							point.y = numbers[ j + 3 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -245,6 +251,7 @@ THREE.SVGLoader.prototype = {
 							control.y = numbers[ j + 1 ];
 							point.x = numbers[ j + 2 ];
 							point.y = numbers[ j + 3 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -263,6 +270,7 @@ THREE.SVGLoader.prototype = {
 							control.y = ry;
 							point.x = numbers[ j + 0 ];
 							point.y = numbers[ j + 1 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -277,6 +285,7 @@ THREE.SVGLoader.prototype = {
 							parseArcCommand(
 								path, numbers[ j ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ], numbers[ j + 4 ], start, point
 							);
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -294,6 +303,7 @@ THREE.SVGLoader.prototype = {
 							} else {
 								path.lineTo( point.x, point.y );
 							}
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -304,6 +314,7 @@ THREE.SVGLoader.prototype = {
 							control.x = point.x;
 							control.y = point.y;
 							path.lineTo( point.x, point.y );
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -314,6 +325,7 @@ THREE.SVGLoader.prototype = {
 							control.x = point.x;
 							control.y = point.y;
 							path.lineTo( point.x, point.y );
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -325,6 +337,7 @@ THREE.SVGLoader.prototype = {
 							control.x = point.x;
 							control.y = point.y;
 							path.lineTo( point.x, point.y );
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -343,6 +356,7 @@ THREE.SVGLoader.prototype = {
 							control.y = point.y + numbers[ j + 3 ];
 							point.x += numbers[ j + 4 ];
 							point.y += numbers[ j + 5 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -361,6 +375,7 @@ THREE.SVGLoader.prototype = {
 							control.y = point.y + numbers[ j + 1 ];
 							point.x += numbers[ j + 2 ];
 							point.y += numbers[ j + 3 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -377,6 +392,7 @@ THREE.SVGLoader.prototype = {
 							control.y = point.y + numbers[ j + 1 ];
 							point.x += numbers[ j + 2 ];
 							point.y += numbers[ j + 3 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -395,6 +411,7 @@ THREE.SVGLoader.prototype = {
 							control.y = ry;
 							point.x = point.x + numbers[ j + 0 ];
 							point.y = point.y + numbers[ j + 1 ];
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -409,6 +426,7 @@ THREE.SVGLoader.prototype = {
 							parseArcCommand(
 								path, numbers[ j ], numbers[ j + 1 ], numbers[ j + 2 ], numbers[ j + 3 ], numbers[ j + 4 ], start, point
 							);
+							if ( j === 0 && doSetFirstPoint === true ) firstPoint.copy( point );
 						}
 						break;
 
@@ -432,10 +450,7 @@ THREE.SVGLoader.prototype = {
 
 				// console.log( type, parseFloats( data ), parseFloats( data ).length  )
 
-				if ( doSetFirstPoint === true ) {
-					firstPoint.copy( point );
-					doSetFirstPoint = false;
-				}
+				doSetFirstPoint = false;
 
 			}
 

+ 23 - 19
examples/js/loaders/deprecated/LegacyGLTFLoader.js

@@ -491,8 +491,8 @@ THREE.LegacyGLTFLoader = ( function () {
 	};
 
 	var WEBGL_SIDES = {
-		1028: THREE.BackSide,  // Culling front
-		1029: THREE.FrontSide  // Culling back
+		1028: THREE.BackSide, // Culling front
+		1029: THREE.FrontSide // Culling back
 		//1032: THREE.NoSide   // Culling front and back, what to do?
 	};
 
@@ -566,8 +566,10 @@ THREE.LegacyGLTFLoader = ( function () {
 
 	function _each( object, callback, thisObj ) {
 
-		if ( !object ) {
+		if ( ! object ) {
+
 			return Promise.resolve();
+
 		}
 
 		var results;
@@ -589,11 +591,11 @@ THREE.LegacyGLTFLoader = ( function () {
 
 					if ( value instanceof Promise ) {
 
-						value.then( function( key, value ) {
+						value.then( function ( key, value ) {
 
 							results[ key ] = value;
 
-						}.bind( this, idx ));
+						}.bind( this, idx ) );
 
 					} else {
 
@@ -621,11 +623,11 @@ THREE.LegacyGLTFLoader = ( function () {
 
 						if ( value instanceof Promise ) {
 
-							value.then( function( key, value ) {
+							value.then( function ( key, value ) {
 
 								results[ key ] = value;
 
-							}.bind( this, key ));
+							}.bind( this, key ) );
 
 						} else {
 
@@ -641,11 +643,11 @@ THREE.LegacyGLTFLoader = ( function () {
 
 		}
 
-		return Promise.all( fns ).then( function() {
+		return Promise.all( fns ).then( function () {
 
 			return results;
 
-		});
+		} );
 
 	}
 
@@ -1210,7 +1212,7 @@ THREE.LegacyGLTFLoader = ( function () {
 
 					}
 
-					keys.forEach( function( v ) {
+					keys.forEach( function ( v ) {
 
 						if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ];
 
@@ -1515,7 +1517,7 @@ THREE.LegacyGLTFLoader = ( function () {
 
 					materialParams.color = new THREE.Color().fromArray( materialValues.diffuse );
 
-				} else if ( typeof( materialValues.diffuse ) === 'string' ) {
+				} else if ( typeof ( materialValues.diffuse ) === 'string' ) {
 
 					materialParams.map = dependencies.textures[ materialValues.diffuse ];
 
@@ -1523,13 +1525,13 @@ THREE.LegacyGLTFLoader = ( function () {
 
 				delete materialParams.diffuse;
 
-				if ( typeof( materialValues.reflective ) === 'string' ) {
+				if ( typeof ( materialValues.reflective ) === 'string' ) {
 
 					materialParams.envMap = dependencies.textures[ materialValues.reflective ];
 
 				}
 
-				if ( typeof( materialValues.bump ) === 'string' ) {
+				if ( typeof ( materialValues.bump ) === 'string' ) {
 
 					materialParams.bumpMap = dependencies.textures[ materialValues.bump ];
 
@@ -1547,7 +1549,7 @@ THREE.LegacyGLTFLoader = ( function () {
 
 					}
 
-				} else if ( typeof( materialValues.emission ) === 'string' ) {
+				} else if ( typeof ( materialValues.emission ) === 'string' ) {
 
 					if ( materialType === THREE.MeshBasicMaterial ) {
 
@@ -1565,7 +1567,7 @@ THREE.LegacyGLTFLoader = ( function () {
 
 					materialParams.specular = new THREE.Color().fromArray( materialValues.specular );
 
-				} else if ( typeof( materialValues.specular ) === 'string' ) {
+				} else if ( typeof ( materialValues.specular ) === 'string' ) {
 
 					materialParams.specularMap = dependencies.textures[ materialValues.specular ];
 
@@ -1670,9 +1672,9 @@ THREE.LegacyGLTFLoader = ( function () {
 
 									var parameters = json.techniques[ material.technique ].parameters || {};
 
-									for( var attributeName in parameters ) {
+									for ( var attributeName in parameters ) {
 
-										if ( parameters [ attributeName ][ 'semantic' ] === attributeId ) {
+										if ( parameters[ attributeName ][ 'semantic' ] === attributeId ) {
 
 											geometry.addAttribute( attributeName, bufferAttribute );
 
@@ -2217,8 +2219,10 @@ THREE.LegacyGLTFLoader = ( function () {
 					if ( child.material && child.material.isRawShaderMaterial ) {
 
 						child.gltfShader = new GLTFShader( child, dependencies.nodes );
-						child.onBeforeRender = function(renderer, scene, camera){
-							this.gltfShader.update(scene, camera);
+						child.onBeforeRender = function ( renderer, scene, camera ) {
+
+							this.gltfShader.update( scene, camera );
+
 						};
 
 					}

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

@@ -20,6 +20,7 @@ export { NodeBuilder } from './core/NodeBuilder.js';
 
 // inputs
 
+export { BoolNode } from './inputs/BoolNode.js';
 export { IntNode } from './inputs/IntNode.js';
 export { FloatNode } from './inputs/FloatNode.js';
 export { Vector2Node } from './inputs/Vector2Node.js';

+ 2 - 0
examples/js/nodes/THREE.Nodes.js

@@ -20,6 +20,7 @@ import {
 
 	// inputs
 
+	BoolNode,
 	IntNode,
 	FloatNode,
 	Vector2Node,
@@ -132,6 +133,7 @@ THREE.NodeBuilder = NodeBuilder;
 
 // inputs
 
+THREE.BoolNode = BoolNode;
 THREE.IntNode = IntNode;
 THREE.FloatNode = FloatNode;
 THREE.Vector2Node = Vector2Node;

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

@@ -101,7 +101,7 @@ CameraNode.prototype.getType = function ( builder ) {
 
 };
 
-CameraNode.prototype.isUnique = function ( builder ) {
+CameraNode.prototype.getUnique = function ( builder ) {
 
 	switch ( this.scope ) {
 
@@ -116,7 +116,7 @@ CameraNode.prototype.isUnique = function ( builder ) {
 
 };
 
-CameraNode.prototype.isShared = function ( builder ) {
+CameraNode.prototype.getShared = function ( builder ) {
 
 	switch ( this.scope ) {
 

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

@@ -21,7 +21,7 @@ NormalNode.prototype = Object.create( TempNode.prototype );
 NormalNode.prototype.constructor = NormalNode;
 NormalNode.prototype.nodeType = "Normal";
 
-NormalNode.prototype.isShared = function ( builder ) {
+NormalNode.prototype.getShared = function ( builder ) {
 
 	switch ( this.scope ) {
 

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

@@ -36,7 +36,7 @@ PositionNode.prototype.getType = function ( ) {
 
 };
 
-PositionNode.prototype.isShared = function ( builder ) {
+PositionNode.prototype.getShared = function ( builder ) {
 
 	switch ( this.scope ) {
 

+ 1 - 1
examples/js/nodes/core/FunctionNode.js

@@ -25,7 +25,7 @@ FunctionNode.prototype.nodeType = "Function";
 
 FunctionNode.prototype.useKeywords = true;
 
-FunctionNode.prototype.isShared = function ( builder, output ) {
+FunctionNode.prototype.getShared = function ( builder, output ) {
 
 	return ! this.isMethod;
 

+ 12 - 4
examples/js/nodes/core/InputNode.js

@@ -18,7 +18,15 @@ function InputNode( type, params ) {
 InputNode.prototype = Object.create( TempNode.prototype );
 InputNode.prototype.constructor = InputNode;
 
-InputNode.prototype.isReadonly = function ( builder ) {
+InputNode.prototype.setReadonly = function ( value ) {
+
+	this.readonly = value;
+
+	return this;
+
+};
+
+InputNode.prototype.getReadonly = function ( builder ) {
 
 	return this.readonly;
 
@@ -48,7 +56,7 @@ InputNode.prototype.generate = function ( builder, output, uuid, type, ns, needs
 	type = type || this.getType( builder );
 
 	var data = builder.getNodeData( uuid ),
-		readonly = this.isReadonly( builder ) && this.generateReadonly !== undefined;
+		readonly = this.getReadonly( builder ) && this.generateReadonly !== undefined;
 
 	if ( readonly ) {
 
@@ -60,7 +68,7 @@ InputNode.prototype.generate = function ( builder, output, uuid, type, ns, needs
 
 			if ( ! data.vertex ) {
 
-				data.vertex = builder.createVertexUniform( type, this, ns, needsUpdate );
+				data.vertex = builder.createVertexUniform( type, this, ns, needsUpdate, this.getLabel() );
 
 			}
 
@@ -70,7 +78,7 @@ InputNode.prototype.generate = function ( builder, output, uuid, type, ns, needs
 
 			if ( ! data.fragment ) {
 
-				data.fragment = builder.createFragmentUniform( type, this, ns, needsUpdate );
+				data.fragment = builder.createFragmentUniform( type, this, ns, needsUpdate, this.getLabel() );
 
 			}
 

+ 28 - 18
examples/js/nodes/core/NodeBuilder.js

@@ -22,7 +22,8 @@ var elements = NodeUtils.elements,
 		vec3: 'v3',
 		vec4: 'v4',
 		mat4: 'v4',
-		int: 'i'
+		int: 'i',
+		bool: 'b'
 	},
 	convertTypeToFormat = {
 		t: 'sampler2D',
@@ -442,9 +443,7 @@ NodeBuilder.prototype = {
 
 	},
 
-	getVar: function ( uuid, type, ns, shader ) {
-
-		shader = shader || 'varying';
+	getVar: function ( uuid, type, ns, shader = 'varying', prefix = 'V', label = '' ) {
 
 		var vars = this.getVars( shader ),
 			data = vars[ uuid ];
@@ -452,7 +451,7 @@ NodeBuilder.prototype = {
 		if ( ! data ) {
 
 			var index = vars.length,
-				name = ns ? ns : 'nVv' + index;
+				name = ns ? ns : 'node' + prefix + index + ( label ? '_' + label : '' );
 
 			data = { name: name, type: type };
 
@@ -465,9 +464,9 @@ NodeBuilder.prototype = {
 
 	},
 
-	getTempVar: function ( uuid, type, ns ) {
+	getTempVar: function ( uuid, type, ns, label ) {
 
-		return this.getVar( uuid, type, ns, this.shader );
+		return this.getVar( uuid, type, ns, this.shader, 'T', label );
 
 	},
 
@@ -550,14 +549,14 @@ NodeBuilder.prototype = {
 
 	},
 
-	createUniform: function ( shader, type, node, ns, needsUpdate ) {
+	createUniform: function ( shader, type, node, ns, needsUpdate, label ) {
 
 		var uniforms = this.inputs.uniforms,
 			index = uniforms.list.length;
 
 		var uniform = new NodeUniform( {
 			type: type,
-			name: ns ? ns : 'nVu' + index,
+			name: ns ? ns : 'nodeU' + index + ( label ? '_' + label : '' ),
 			node: node,
 			needsUpdate: needsUpdate
 		} );
@@ -573,15 +572,15 @@ NodeBuilder.prototype = {
 
 	},
 
-	createVertexUniform: function ( type, node, ns, needsUpdate ) {
+	createVertexUniform: function ( type, node, ns, needsUpdate, label ) {
 
-		return this.createUniform( 'vertex', type, node, ns, needsUpdate );
+		return this.createUniform( 'vertex', type, node, ns, needsUpdate, label );
 
 	},
 
-	createFragmentUniform: function ( type, node, ns, needsUpdate ) {
+	createFragmentUniform: function ( type, node, ns, needsUpdate, label ) {
 
-		return this.createUniform( 'fragment', type, node, ns, needsUpdate );
+		return this.createUniform( 'fragment', type, node, ns, needsUpdate, label );
 
 	},
 
@@ -821,28 +820,39 @@ NodeBuilder.prototype = {
 			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 <- i' :
+			case 'f <- b' :	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 <- i' :
+			case 'v2 <- b' : 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 <- i' :
+			case 'v3 <- b' : 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 <- i' :
+			case 'v4 <- b' : return 'vec4( float( ' + code + ' ) )';
 
-			case 'i <- f' : return 'int( ' + code + ' )';
+			case 'i <- f' :
+			case 'i <- b' : 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 'b <- f' : return '( ' + code + ' != 0.0 )';
+			case 'b <- v2' : return '( ' + code + ' != vec2( 0.0 ) )';
+			case 'b <- v3' : return '( ' + code + ' != vec3( 0.0 ) )';
+			case 'b <- v4' : return '( ' + code + ' != vec4( 0.0 ) )';
+			case 'b <- i' : return '( ' + code + ' != 0 )';
+
 		}
 
 		return code;

+ 23 - 9
examples/js/nodes/core/TempNode.js

@@ -23,9 +23,9 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 
 	output = output || this.getType( builder );
 
-	if ( this.isShared( builder, output ) ) {
+	if ( this.getShared( builder, output ) ) {
 
-		var isUnique = this.isUnique( builder, output );
+		var isUnique = this.getUnique( builder, output );
 
 		if ( isUnique && this.constructor.uuid === undefined ) {
 
@@ -40,7 +40,7 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 
 		if ( builder.parsing ) {
 
-			if ( ( data.deps || 0 ) > 0 ) {
+			if ( ( data.deps || 0 ) > 0 || this.getLabel() ) {
 
 				this.appendDepsNode( builder, data, output );
 
@@ -56,7 +56,7 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 
 			return data.name;
 
-		} else if ( ! this.isShared( builder, type ) || ( ! builder.optimize || data.deps == 1 ) ) {
+		} else if ( ! this.getLabel() && ( ! this.getShared( builder, type ) || ( ! builder.optimize || data.deps === 1 ) ) ) {
 
 			return Node.prototype.build.call( this, builder, output, uuid );
 
@@ -88,23 +88,37 @@ TempNode.prototype.build = function ( builder, output, uuid, ns ) {
 
 };
 
-TempNode.prototype.isShared = function ( builder, output ) {
+TempNode.prototype.getShared = function ( builder, output ) {
 
 	return output !== 'sampler2D' && output !== 'samplerCube' && this.shared;
 
 };
 
-TempNode.prototype.isUnique = function ( builder, output ) {
+TempNode.prototype.getUnique = function ( builder, output ) {
 
 	return this.unique;
 
 };
 
+TempNode.prototype.setLabel = function ( name ) {
+
+	this.label = name;
+
+	return this;
+
+};
+
+TempNode.prototype.getLabel = function ( builder ) {
+
+	return this.label;
+
+};
+
 TempNode.prototype.getUuid = function ( unique ) {
 
 	var uuid = unique || unique == undefined ? this.constructor.uuid || this.uuid : this.uuid;
 
-	if ( typeof this.scope == "string" ) uuid = this.scope + '-' + uuid;
+	if ( typeof this.scope === "string" ) uuid = this.scope + '-' + uuid;
 
 	return uuid;
 
@@ -122,11 +136,11 @@ TempNode.prototype.getTemp = function ( builder, uuid ) {
 
 TempNode.prototype.generate = function ( builder, output, uuid, type, ns ) {
 
-	if ( ! this.isShared( builder, output ) ) console.error( "THREE.TempNode is not shared!" );
+	if ( ! this.getShared( builder, output ) ) console.error( "THREE.TempNode is not shared!" );
 
 	uuid = uuid || this.uuid;
 
-	return builder.getTempVar( uuid, type || this.getType( builder ), ns ).name;
+	return builder.getTempVar( uuid, type || this.getType( builder ), ns, this.getLabel() ).name;
 
 };
 

+ 51 - 0
examples/js/nodes/inputs/BoolNode.js

@@ -0,0 +1,51 @@
+/**
+ * @author sunag / http://www.sunag.com.br/
+ */
+
+import { InputNode } from '../core/InputNode.js';
+
+function BoolNode( value ) {
+
+	InputNode.call( this, 'b' );
+
+	this.value = Boolean( value );
+
+}
+
+BoolNode.prototype = Object.create( InputNode.prototype );
+BoolNode.prototype.constructor = BoolNode;
+BoolNode.prototype.nodeType = "Bool";
+
+BoolNode.prototype.generateReadonly = function ( builder, output, uuid, type, ns, needsUpdate ) {
+
+	return builder.format( this.value, type, output );
+
+};
+
+BoolNode.prototype.copy = function ( source ) {
+
+	InputNode.prototype.copy.call( this, source );
+
+	this.value = source.value;
+
+};
+
+BoolNode.prototype.toJSON = function ( meta ) {
+
+	var data = this.getJSONNode( meta );
+
+	if ( ! data ) {
+
+		data = this.createJSONNode( meta );
+
+		data.value = this.value;
+
+		if ( this.readonly === true ) data.readonly = true;
+
+	}
+
+	return data;
+
+};
+
+export { BoolNode };

+ 6 - 2
examples/js/nodes/inputs/RTTNode.js

@@ -72,7 +72,9 @@ RTTNode.prototype.updateFramesaveTo = function ( frame ) {
 
 	this.saveToCurrent = this.saveTo;
 
-	frame.renderer.render( this.saveToScene, this.camera, this.saveTo.renderTarget, this.saveTo.clear );
+	frame.renderer.setRenderTarget( this.saveTo.renderTarget );
+	if ( this.saveTo.clear ) frame.renderer.clear();
+	frame.renderer.render( this.saveToScene, this.camera );
 
 };
 
@@ -96,7 +98,9 @@ RTTNode.prototype.updateFrame = function ( frame ) {
 
 			}
 
-			frame.renderer.render( this.scene, this.camera, this.renderTarget, this.clear );
+			frame.renderer.setRenderTarget( this.renderTarget );
+			if ( this.clear ) frame.renderer.clear();
+			frame.renderer.render( this.scene, this.camera );
 
 		}
 

+ 1 - 1
examples/js/nodes/inputs/ScreenNode.js

@@ -15,7 +15,7 @@ ScreenNode.prototype = Object.create( TextureNode.prototype );
 ScreenNode.prototype.constructor = ScreenNode;
 ScreenNode.prototype.nodeType = "Screen";
 
-ScreenNode.prototype.isUnique = function () {
+ScreenNode.prototype.getUnique = function () {
 
 	return true;
 

+ 1 - 0
examples/js/nodes/materials/PhongNodeMaterial.js

@@ -32,6 +32,7 @@ NodeUtils.addShortcuts( PhongNodeMaterial.prototype, 'fragment', [
 	'ao',
 	'environment',
 	'environmentAlpha',
+	'mask',
 	'position'
 ] );
 

+ 1 - 0
examples/js/nodes/materials/SpriteNodeMaterial.js

@@ -22,6 +22,7 @@ SpriteNodeMaterial.prototype.constructor = SpriteNodeMaterial;
 NodeUtils.addShortcuts( SpriteNodeMaterial.prototype, 'fragment', [
 	'color',
 	'alpha',
+	'mask',
 	'position',
 	'spherical'
 ] );

+ 1 - 0
examples/js/nodes/materials/StandardNodeMaterial.js

@@ -34,6 +34,7 @@ NodeUtils.addShortcuts( StandardNodeMaterial.prototype, 'fragment', [
 	'shadow',
 	'ao',
 	'environment',
+	'mask',
 	'position'
 ] );
 

+ 21 - 2
examples/js/nodes/materials/nodes/PhongNode.js

@@ -103,6 +103,8 @@ PhongNode.prototype.build = function ( builder ) {
 
 		// parse all nodes to reuse generate codes
 
+		if ( this.mask ) this.mask.parse( builder );
+
 		this.color.parse( builder, { slot: 'color' } );
 		this.specular.parse( builder );
 		this.shininess.parse( builder );
@@ -123,6 +125,8 @@ PhongNode.prototype.build = function ( builder ) {
 
 		// build code
 
+		var mask = this.mask ? this.mask.buildCode( builder, 'b' ) : undefined;
+
 		var color = this.color.buildCode( builder, 'c', { slot: 'color' } );
 		var specular = this.specular.buildCode( builder, 'c' );
 		var shininess = this.shininess.buildCode( builder, 'f' );
@@ -157,8 +161,19 @@ PhongNode.prototype.build = function ( builder ) {
 			"#include <normal_fragment_begin>",
 
 			// prevent undeclared material
-			"	BlinnPhongMaterial material;",
+			"	BlinnPhongMaterial material;"
+		];
+
+		if ( mask ) {
+
+			output.push(
+				mask.code,
+				'if ( ! ' + mask.result + ' ) discard;'
+			);
 
+		}
+
+		output.push(
 			color.code,
 			"	vec3 diffuseColor = " + color.result + ";",
 			"	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
@@ -172,7 +187,7 @@ PhongNode.prototype.build = function ( builder ) {
 			"	float shininess = max( 0.0001, " + shininess.result + " );",
 
 			"	float specularStrength = 1.0;" // Ignored in MaterialNode ( replace to specular )
-		];
+		);
 
 		if ( alpha ) {
 
@@ -335,6 +350,8 @@ PhongNode.prototype.copy = function ( source ) {
 	this.specular = source.specular;
 	this.shininess = source.shininess;
 
+	if ( source.mask ) this.mask = source.mask;
+
 	if ( source.alpha ) this.alpha = source.alpha;
 
 	if ( source.normal ) this.normal = source.normal;
@@ -370,6 +387,8 @@ PhongNode.prototype.toJSON = function ( meta ) {
 		data.specular = this.specular.toJSON( meta ).uuid;
 		data.shininess = this.shininess.toJSON( meta ).uuid;
 
+		if ( this.mask ) data.mask = this.mask.toJSON( meta ).uuid;
+
 		if ( this.alpha ) data.alpha = this.alpha.toJSON( meta ).uuid;
 
 		if ( this.normal ) data.normal = this.normal.toJSON( meta ).uuid;

+ 23 - 6
examples/js/nodes/materials/nodes/SpriteNode.js

@@ -123,18 +123,31 @@ SpriteNode.prototype.build = function ( builder ) {
 
 		// parse all nodes to reuse generate codes
 
+		if ( this.mask ) this.mask.parse( builder );
+
 		if ( this.alpha ) this.alpha.parse( builder );
 
 		this.color.parse( builder, { slot: 'color' } );
 
 		// build code
 
-		var alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined,
-			color = this.color.buildCode( builder, 'c', { slot: 'color' } );
+		var mask = this.mask ? this.mask.buildCode( builder, 'b' ) : undefined,
+			alpha = this.alpha ? this.alpha.buildCode( builder, 'f' ) : undefined,
+			color = this.color.buildCode( builder, 'c', { slot: 'color' } ),
+			output = [];
+
+		if ( mask ) {
+
+			output.push(
+				mask.code,
+				'if ( ! ' + mask.result + ' ) discard;'
+			);
+
+		}
 
 		if ( alpha ) {
 
-			output = [
+			output.push(
 				alpha.code,
 				'#ifdef ALPHATEST',
 
@@ -143,14 +156,14 @@ SpriteNode.prototype.build = function ( builder ) {
 				'#endif',
 				color.code,
 				"gl_FragColor = vec4( " + color.result + ", " + alpha.result + " );"
-			];
+			);
 
 		} else {
 
-			output = [
+			output.push(
 				color.code,
 				"gl_FragColor = vec4( " + color.result + ", 1.0 );"
-			];
+			);
 
 		}
 
@@ -180,6 +193,8 @@ SpriteNode.prototype.copy = function ( source ) {
 
 	if ( source.spherical !== undefined ) this.spherical = source.spherical;
 
+	if ( source.mask ) this.mask = source.mask;
+
 	if ( source.alpha ) this.alpha = source.alpha;
 
 };
@@ -202,6 +217,8 @@ SpriteNode.prototype.toJSON = function ( meta ) {
 
 		if ( this.spherical === false ) data.spherical = false;
 
+		if ( this.mask ) data.mask = this.mask.toJSON( meta ).uuid;
+
 		if ( this.alpha ) data.alpha = this.alpha.toJSON( meta ).uuid;
 
 	}

+ 22 - 3
examples/js/nodes/materials/nodes/StandardNode.js

@@ -117,6 +117,8 @@ StandardNode.prototype.build = function ( builder ) {
 
 		// parse all nodes to reuse generate codes
 
+		if ( this.mask ) this.mask.parse( builder );
+
 		this.color.parse( builder, { slot: 'color', context: contextGammaOnly } );
 		this.roughness.parse( builder );
 		this.metalness.parse( builder );
@@ -141,6 +143,8 @@ StandardNode.prototype.build = function ( builder ) {
 
 		// build code
 
+		var mask = this.mask ? this.mask.buildCode( builder, 'b' ) : undefined;
+
 		var color = this.color.buildCode( builder, 'c', { slot: 'color', context: contextGammaOnly } );
 		var roughness = this.roughness.buildCode( builder, 'f' );
 		var metalness = this.metalness.buildCode( builder, 'f' );
@@ -194,8 +198,19 @@ StandardNode.prototype.build = function ( builder ) {
 
 			// add before: prevent undeclared material
 			"	PhysicalMaterial material;",
-			"	material.diffuseColor = vec3( 1.0 );",
+			"	material.diffuseColor = vec3( 1.0 );"
+		];
+
+		if ( mask ) {
+
+			output.push(
+				mask.code,
+				'if ( ! ' + mask.result + ' ) discard;'
+			);
 
+		}
+
+		output.push(
 			color.code,
 			"	vec3 diffuseColor = " + color.result + ";",
 			"	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );",
@@ -207,7 +222,7 @@ StandardNode.prototype.build = function ( builder ) {
 
 			metalness.code,
 			"	float metalnessFactor = " + metalness.result + ";"
-		];
+		);
 
 		if ( alpha ) {
 
@@ -215,7 +230,7 @@ StandardNode.prototype.build = function ( builder ) {
 				alpha.code,
 				'#ifdef ALPHATEST',
 
-				'if ( ' + alpha.result + ' <= ALPHATEST ) discard;',
+				'	if ( ' + alpha.result + ' <= ALPHATEST ) discard;',
 
 				'#endif'
 			);
@@ -403,6 +418,8 @@ StandardNode.prototype.copy = function ( source ) {
 	this.roughness = source.roughness;
 	this.metalness = source.metalness;
 
+	if ( source.mask ) this.mask = source.mask;
+
 	if ( source.alpha ) this.alpha = source.alpha;
 
 	if ( source.normal ) this.normal = source.normal;
@@ -442,6 +459,8 @@ StandardNode.prototype.toJSON = function ( meta ) {
 		data.roughness = this.roughness.toJSON( meta ).uuid;
 		data.metalness = this.metalness.toJSON( meta ).uuid;
 
+		if ( this.mask ) data.mask = this.mask.toJSON( meta ).uuid;
+
 		if ( this.alpha ) data.alpha = this.alpha.toJSON( meta ).uuid;
 
 		if ( this.normal ) data.normal = this.normal.toJSON( meta ).uuid;

+ 35 - 16
examples/js/nodes/math/CondNode.js

@@ -4,18 +4,18 @@
 
 import { TempNode } from '../core/TempNode.js';
 
-function CondNode( a, b, ifNode, elseNode, op ) {
+function CondNode( a, b, op, ifNode, elseNode ) {
 
 	TempNode.call( this );
 
 	this.a = a;
 	this.b = b;
 
+	this.op = op;
+	
 	this.ifNode = ifNode;
 	this.elseNode = elseNode;
 
-	this.op = op;
-
 }
 
 CondNode.EQUAL = '==';
@@ -31,13 +31,22 @@ CondNode.prototype.nodeType = "Cond";
 
 CondNode.prototype.getType = function ( builder ) {
 
-	if ( builder.getTypeLength( this.elseNode.getType( builder ) ) > builder.getTypeLength( this.ifNode.getType( builder ) ) ) {
+	if (this.ifNode) {
+		
+		var ifType = this.ifNode.getType( builder );
+		var elseType = this.elseNode.getType( builder );
+		
+		if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) {
 
-		return this.elseNode.getType( builder );
+			return elseType;
 
-	}
+		}
 
-	return this.ifNode.getType( builder );
+		return ifType;
+		
+	}
+	
+	return 'b';
 
 };
 
@@ -59,10 +68,20 @@ CondNode.prototype.generate = function ( builder, output ) {
 		condType = this.getCondType( builder ),
 		a = this.a.build( builder, condType ),
 		b = this.b.build( builder, condType ),
-		ifNode = this.ifNode.build( builder, type ),
-		elseNode = this.elseNode.build( builder, type );
-
-	var code = '( ' + [ a, this.op, b, '?', ifNode, ':', elseNode ].join( ' ' ) + ' )';
+		code;
+		
+	if (this.ifNode) {
+		
+		var ifCode = this.ifNode.build( builder, type ),
+			elseCode = this.elseNode.build( builder, type );
+		
+		code = '( ' + [ a, this.op, b, '?', ifCode, ':', elseCode ].join( ' ' ) + ' )';
+		
+	} else {
+
+		code = '( ' + a + ' ' + this.op + ' ' +  b  + ' )';
+		
+	}
 
 	return builder.format( code, this.getType( builder ), output );
 
@@ -75,11 +94,11 @@ CondNode.prototype.copy = function ( source ) {
 	this.a = source.a;
 	this.b = source.b;
 
+	this.op = source.op;
+
 	this.ifNode = source.ifNode;
 	this.elseNode = source.elseNode;
 
-	this.op = source.op;
-
 };
 
 CondNode.prototype.toJSON = function ( meta ) {
@@ -93,11 +112,11 @@ CondNode.prototype.toJSON = function ( meta ) {
 		data.a = this.a.toJSON( meta ).uuid;
 		data.b = this.b.toJSON( meta ).uuid;
 
-		data.ifNode = this.ifNode.toJSON( meta ).uuid;
-		data.elseNode = this.elseNode.toJSON( meta ).uuid;
-
 		data.op = this.op;
 
+		if ( data.ifNode ) data.ifNode = this.ifNode.toJSON( meta ).uuid;
+		if ( data.elseNode ) data.elseNode = this.elseNode.toJSON( meta ).uuid;
+
 	}
 
 	return data;

+ 4 - 2
examples/js/nodes/postprocessing/NodePostProcessing.js

@@ -16,7 +16,7 @@ function NodePostProcessing( renderer, renderTarget ) {
 			stencilBuffer: false
 		};
 
-		var size = renderer.getDrawingBufferSize();
+		var size = renderer.getDrawingBufferSize( new THREE.Vector2() );
 		renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );
 
 	}
@@ -64,10 +64,12 @@ NodePostProcessing.prototype = {
 		frame.setRenderer( this.renderer )
 			.setRenderTexture( this.renderTarget.texture );
 
-		this.renderer.render( scene, camera, this.renderTarget );
+		this.renderer.setRenderTarget( this.renderTarget );
+		this.renderer.render( scene, camera );
 
 		frame.updateNode( this.material );
 
+		this.renderer.setRenderTarget( null );
 		this.renderer.render( this.scene, this.camera );
 
 	},

+ 2 - 2
examples/js/nodes/utils/ColorSpaceNode.js

@@ -131,7 +131,7 @@ ColorSpaceNode.Nodes = ( function () {
 	var LinearToLogLuv = new FunctionNode( [
 		"vec4 LinearToLogLuv( in vec4 value ) {",
 
-		"	vec3 Xp_Y_XYZp = value.rgb * cLogLuvM;",
+		"	vec3 Xp_Y_XYZp = cLogLuvM * value.rgb;",
 		"	Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));",
 		"	vec4 vResult;",
 		"	vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;",
@@ -155,7 +155,7 @@ ColorSpaceNode.Nodes = ( function () {
 		"	Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);",
 		"	Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;",
 		"	Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;",
-		"	vec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;",
+		"	vec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;",
 		"	return vec4( max(vRGB, 0.0), 1.0 );",
 
 		"}"

+ 3 - 3
examples/js/nodes/utils/TimerNode.js

@@ -12,7 +12,7 @@ function TimerNode( scale, scope, timeScale ) {
 	this.scale = scale !== undefined ? scale : 1;
 	this.scope = scope || TimerNode.GLOBAL;
 
-	this.timeScale = timeScale !== undefined ? timeScale : this.scale !== 1;
+	this.timeScale = timeScale !== undefined ? timeScale : scale !== undefined;
 
 }
 
@@ -24,7 +24,7 @@ TimerNode.prototype = Object.create( FloatNode.prototype );
 TimerNode.prototype.constructor = TimerNode;
 TimerNode.prototype.nodeType = "Timer";
 
-TimerNode.prototype.isReadonly = function () {
+TimerNode.prototype.getReadonly = function () {
 
 	// never use TimerNode as readonly but aways as "uniform"
 
@@ -32,7 +32,7 @@ TimerNode.prototype.isReadonly = function () {
 
 };
 
-TimerNode.prototype.isUnique = function () {
+TimerNode.prototype.getUnique = function () {
 
 	// share TimerNode "uniform" input if is used on more time with others TimerNode
 

+ 1 - 1
examples/js/nodes/utils/VelocityNode.js

@@ -21,7 +21,7 @@ VelocityNode.prototype = Object.create( Vector3Node.prototype );
 VelocityNode.prototype.constructor = VelocityNode;
 VelocityNode.prototype.nodeType = "Velocity";
 
-VelocityNode.prototype.isReadonly = function ( builder ) {
+VelocityNode.prototype.getReadonly = function ( builder ) {
 
 	return false;
 

+ 12 - 6
examples/js/objects/Fire.js

@@ -342,7 +342,8 @@ THREE.Fire = function ( geometry, options ) {
 
 		this.sourceMaterial.uniforms[ "densityMap" ].value = this.field0.texture;
 
-		renderer.render( this.fieldScene, this.orthoCamera, this.field1 );
+		renderer.setRenderTarget( this.field1 );
+		renderer.render( this.fieldScene, this.orthoCamera );
 
 		this.sourceMesh.visible = false;
 
@@ -356,7 +357,8 @@ THREE.Fire = function ( geometry, options ) {
 
 		this.diffuseMaterial.uniforms[ "densityMap" ].value = this.field0.texture;
 
-		renderer.render( this.fieldScene, this.orthoCamera, this.field1 );
+		renderer.setRenderTarget( this.field1 );
+		renderer.render( this.fieldScene, this.orthoCamera );
 
 		this.diffuseMesh.visible = false;
 
@@ -370,7 +372,8 @@ THREE.Fire = function ( geometry, options ) {
 
 		this.driftMaterial.uniforms[ "densityMap" ].value = this.field0.texture;
 
-		renderer.render( this.fieldScene, this.orthoCamera, this.field1 );
+		renderer.setRenderTarget( this.field1 );
+		renderer.render( this.fieldScene, this.orthoCamera );
 
 		this.driftMesh.visible = false;
 
@@ -386,7 +389,8 @@ THREE.Fire = function ( geometry, options ) {
 
 		this.projMaterial1.uniforms[ "densityMap" ].value = this.field0.texture;
 
-		renderer.render( this.fieldScene, this.orthoCamera, this.fieldProj );
+		renderer.setRenderTarget( this.fieldProj );
+		renderer.render( this.fieldScene, this.orthoCamera );
 
 		this.projMesh1.visible = false;
 
@@ -398,7 +402,8 @@ THREE.Fire = function ( geometry, options ) {
 
 		for ( var i = 0; i < 20; i ++ ) {
 
-			renderer.render( this.fieldScene, this.orthoCamera, this.field1 );
+			renderer.setRenderTarget( this.field1 );
+			renderer.render( this.fieldScene, this.orthoCamera );
 
 			var temp = this.field1;
 			this.field1 = this.fieldProj;
@@ -417,7 +422,8 @@ THREE.Fire = function ( geometry, options ) {
 
 		this.projMesh3.visible = true;
 
-		renderer.render( this.fieldScene, this.orthoCamera, this.field1 );
+		renderer.setRenderTarget( this.field1 );
+		renderer.render( this.fieldScene, this.orthoCamera );
 
 		this.projMesh3.visible = false;
 

+ 1 - 1
examples/js/objects/Lensflare.js

@@ -162,7 +162,7 @@ THREE.Lensflare = function () {
 
 	this.onBeforeRender = function ( renderer, scene, camera ) {
 
-		viewport.copy( renderer.getCurrentViewport() );
+		renderer.getCurrentViewport( viewport );
 
 		var invAspect = viewport.w / viewport.z;
 		var halfViewportWidth = viewport.z / 2.0;

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

@@ -33,6 +33,7 @@ THREE.Reflector = function ( geometry, options ) {
 	var view = new THREE.Vector3();
 	var target = new THREE.Vector3();
 	var q = new THREE.Vector4();
+	var size = new THREE.Vector2();
 
 	var textureMatrix = new THREE.Matrix4();
 	var virtualCamera = new THREE.PerspectiveCamera();
@@ -160,7 +161,9 @@ THREE.Reflector = function ( geometry, options ) {
 		renderer.vr.enabled = false; // Avoid camera modification and recursion
 		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
-		renderer.render( scene, virtualCamera, renderTarget, true );
+		renderer.setRenderTarget( renderTarget );
+		renderer.clear();
+		renderer.render( scene, virtualCamera );
 
 		renderer.vr.enabled = currentVrEnabled;
 		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
@@ -173,7 +176,7 @@ THREE.Reflector = function ( geometry, options ) {
 
 		if ( bounds !== undefined ) {
 
-			var size = renderer.getSize();
+			renderer.getSize( size );
 			var pixelRatio = renderer.getPixelRatio();
 
 			viewport.x = bounds.x * size.width * pixelRatio;

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

@@ -187,6 +187,7 @@ THREE.Refractor = function ( geometry, options ) {
 	var render = ( function () {
 
 		var viewport = new THREE.Vector4();
+		var size = new THREE.Vector2();
 
 		return function render( renderer, scene, camera ) {
 
@@ -199,7 +200,9 @@ THREE.Refractor = function ( geometry, options ) {
 			renderer.vr.enabled = false; // avoid camera modification
 			renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
 
-			renderer.render( scene, virtualCamera, renderTarget, true );
+			renderer.setRenderTarget( renderTarget );
+			renderer.clear();
+			renderer.render( scene, virtualCamera );
 
 			renderer.vr.enabled = currentVrEnabled;
 			renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
@@ -211,7 +214,7 @@ THREE.Refractor = function ( geometry, options ) {
 
 			if ( bounds !== undefined ) {
 
-				var size = renderer.getSize();
+				renderer.getSize( size );
 				var pixelRatio = renderer.getPixelRatio();
 
 				viewport.x = bounds.x * size.width * pixelRatio;

+ 3 - 1
examples/js/objects/Water.js

@@ -291,7 +291,9 @@ THREE.Water = function ( geometry, options ) {
 		renderer.vr.enabled = false; // Avoid camera modification and recursion
 		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
-		renderer.render( scene, mirrorCamera, renderTarget, true );
+		renderer.setRenderTarget( renderTarget );
+		renderer.clear();
+		renderer.render( scene, mirrorCamera );
 
 		scope.visible = true;
 

+ 2 - 1
examples/js/pmrem/PMREMCubeUVPacker.js

@@ -137,7 +137,8 @@ THREE.PMREMCubeUVPacker = ( function () {
 			renderer.gammaOutput = false;
 			renderer.toneMapping = THREE.LinearToneMapping;
 			renderer.toneMappingExposure = 1.0;
-			renderer.render( scene, camera, this.CubeUVRenderTarget, false );
+			renderer.setRenderTarget( this.CubeUVRenderTarget );
+			renderer.render( scene, camera );
 
 			renderer.setRenderTarget( currentRenderTarget );
 			renderer.toneMapping = toneMapping;

+ 3 - 1
examples/js/pmrem/PMREMGenerator.js

@@ -137,7 +137,9 @@ THREE.PMREMGenerator = ( function () {
 
 			renderTarget.activeCubeFace = faceIndex;
 			shader.uniforms[ 'faceIndex' ].value = faceIndex;
-			renderer.render( scene, camera, renderTarget, true );
+			renderer.setRenderTarget( renderTarget );
+			renderer.clear();
+			renderer.render( scene, camera );
 
 		},
 

+ 14 - 6
examples/js/postprocessing/AdaptiveToneMappingPass.js

@@ -130,7 +130,7 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 
 	constructor: THREE.AdaptiveToneMappingPass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		if ( this.needsInit ) {
 
@@ -148,20 +148,23 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 			//Render the luminance of the current scene into a render target with mipmapping enabled
 			this.quad.material = this.materialLuminance;
 			this.materialLuminance.uniforms.tDiffuse.value = readBuffer.texture;
-			renderer.render( this.scene, this.camera, this.currentLuminanceRT );
+			renderer.setRenderTarget( this.currentLuminanceRT );
+			renderer.render( this.scene, this.camera );
 
 			//Use the new luminance values, the previous luminance and the frame delta to
 			//adapt the luminance over time.
 			this.quad.material = this.materialAdaptiveLum;
-			this.materialAdaptiveLum.uniforms.delta.value = delta;
+			this.materialAdaptiveLum.uniforms.delta.value = deltaTime;
 			this.materialAdaptiveLum.uniforms.lastLum.value = this.previousLuminanceRT.texture;
 			this.materialAdaptiveLum.uniforms.currentLum.value = this.currentLuminanceRT.texture;
-			renderer.render( this.scene, this.camera, this.luminanceRT );
+			renderer.setRenderTarget( this.luminanceRT );
+			renderer.render( this.scene, this.camera );
 
 			//Copy the new adapted luminance value so that it can be used by the next frame.
 			this.quad.material = this.materialCopy;
 			this.copyUniforms.tDiffuse.value = this.luminanceRT.texture;
-			renderer.render( this.scene, this.camera, this.previousLuminanceRT );
+			renderer.setRenderTarget( this.previousLuminanceRT );
+			renderer.render( this.scene, this.camera );
 
 		}
 
@@ -170,11 +173,16 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 
 		if ( this.renderToScreen ) {
 
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene, this.camera );
 
 		} else {
 
-			renderer.render( this.scene, this.camera, writeBuffer, this.clear );
+			renderer.setRenderTarget( writeBuffer );
+
+			if ( this.clear ) renderer.clear();
+
+			renderer.render( this.scene, this.camera );
 
 		}
 

+ 16 - 8
examples/js/postprocessing/AfterimagePass.js

@@ -70,17 +70,25 @@ THREE.AfterimagePass.prototype = Object.assign( Object.create( THREE.Pass.protot
 
 		this.quadComp.material = this.shaderMaterial;
 
-		renderer.render( this.sceneComp, this.camera, this.textureComp );
-		renderer.render( this.scene, this.camera, this.textureOld );
-		
+		renderer.setRenderTarget( this.textureComp );
+		renderer.render( this.sceneComp, this.camera );
+
+		renderer.setRenderTarget( this.textureOld );
+		renderer.render( this.scene, this.camera );
+
 		if ( this.renderToScreen ) {
-			
+
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene, this.camera );
-			
+
 		} else {
-			
-			renderer.render( this.scene, this.camera, writeBuffer, this.clear );
-			
+
+			renderer.setRenderTarget( writeBuffer );
+
+			if ( this.clear ) renderer.clear();
+
+			renderer.render( this.scene, this.camera );
+
 		}
 
 	}

+ 10 - 4
examples/js/postprocessing/BloomPass.js

@@ -80,7 +80,7 @@ THREE.BloomPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 	constructor: THREE.BloomPass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
 
@@ -91,7 +91,9 @@ THREE.BloomPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 		this.convolutionUniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurX;
 
-		renderer.render( this.scene, this.camera, this.renderTargetX, true );
+		renderer.setRenderTarget( this.renderTargetX );
+		renderer.clear();
+		renderer.render( this.scene, this.camera );
 
 
 		// Render quad with blured scene into texture (convolution pass 2)
@@ -99,7 +101,9 @@ THREE.BloomPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 		this.convolutionUniforms[ "tDiffuse" ].value = this.renderTargetX.texture;
 		this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurY;
 
-		renderer.render( this.scene, this.camera, this.renderTargetY, true );
+		renderer.setRenderTarget( this.renderTargetY );
+		renderer.clear();
+		renderer.render( this.scene, this.camera );
 
 		// Render original scene with superimposed blur to texture
 
@@ -109,7 +113,9 @@ THREE.BloomPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 		if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST );
 
-		renderer.render( this.scene, this.camera, readBuffer, this.clear );
+		renderer.setRenderTarget( readBuffer );
+		if ( this.clear ) renderer.clear();
+		renderer.render( this.scene, this.camera );
 
 	}
 

+ 9 - 4
examples/js/postprocessing/BokehPass.js

@@ -82,7 +82,7 @@ THREE.BokehPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 	constructor: THREE.BokehPass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		this.quad2.material = this.materialBokeh;
 
@@ -97,7 +97,9 @@ THREE.BokehPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 		renderer.setClearColor( 0xffffff );
 		renderer.setClearAlpha( 1.0 );
-		renderer.render( this.scene, this.camera, this.renderTargetDepth, true );
+		renderer.setRenderTarget( this.renderTargetDepth );
+		renderer.clear();
+		renderer.render( this.scene, this.camera );
 
 		// Render bokeh composite
 
@@ -107,11 +109,14 @@ THREE.BokehPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 
 		if ( this.renderToScreen ) {
 
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene2, this.camera2 );
 
 		} else {
 
-			renderer.render( this.scene2, this.camera2, writeBuffer, this.clear );
+			renderer.setRenderTarget( writeBuffer );
+			renderer.clear();
+			renderer.render( this.scene2, this.camera2 );
 
 		}
 
@@ -119,7 +124,7 @@ THREE.BokehPass.prototype = Object.assign( Object.create( THREE.Pass.prototype )
 		renderer.setClearColor( this.oldClearColor );
 		renderer.setClearAlpha( this.oldClearAlpha );
 		renderer.autoClear = this.oldAutoClear;
-	
+
 	}
 
 } );

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

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

+ 4 - 2
examples/js/postprocessing/CubeTexturePass.js

@@ -36,7 +36,7 @@ THREE.CubeTexturePass.prototype = Object.assign( Object.create( THREE.Pass.proto
 
 	constructor: THREE.CubeTexturePass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		var oldAutoClear = renderer.autoClear;
 		renderer.autoClear = false;
@@ -48,7 +48,9 @@ THREE.CubeTexturePass.prototype = Object.assign( Object.create( THREE.Pass.proto
 		this.cubeMesh.material.uniforms[ "opacity" ].value = this.opacity;
 		this.cubeMesh.material.transparent = ( this.opacity < 1.0 );
 
-		renderer.render( this.cubeScene, this.cubeCamera, this.renderToScreen ? null : readBuffer, this.clear );
+		renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );
+		if ( this.clear ) renderer.clear();
+		renderer.render( this.cubeScene, this.cubeCamera );
 
 		renderer.autoClear = oldAutoClear;
 

+ 5 - 2
examples/js/postprocessing/DotScreenPass.js

@@ -38,7 +38,7 @@ THREE.DotScreenPass.prototype = Object.assign( Object.create( THREE.Pass.prototy
 
 	constructor: THREE.DotScreenPass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ "tSize" ].value.set( readBuffer.width, readBuffer.height );
@@ -47,11 +47,14 @@ THREE.DotScreenPass.prototype = Object.assign( Object.create( THREE.Pass.prototy
 
 		if ( this.renderToScreen ) {
 
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene, this.camera );
 
 		} else {
 
-			renderer.render( this.scene, this.camera, writeBuffer, this.clear );
+			renderer.setRenderTarget( writeBuffer );
+			if ( this.clear ) renderer.clear();
+			renderer.render( this.scene, this.camera );
 
 		}
 

+ 23 - 7
examples/js/postprocessing/EffectComposer.js

@@ -15,7 +15,7 @@ THREE.EffectComposer = function ( renderer, renderTarget ) {
 			stencilBuffer: false
 		};
 
-		var size = renderer.getDrawingBufferSize();
+		var size = renderer.getDrawingBufferSize( new THREE.Vector2() );
 		renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );
 		renderTarget.texture.name = 'EffectComposer.rt1';
 
@@ -46,6 +46,8 @@ THREE.EffectComposer = function ( renderer, renderTarget ) {
 
 	this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
 
+	this._previousFrameTime = Date.now();
+
 };
 
 Object.assign( THREE.EffectComposer.prototype, {
@@ -62,7 +64,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 		this.passes.push( pass );
 
-		var size = this.renderer.getDrawingBufferSize();
+		var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() );
 		pass.setSize( size.width, size.height );
 
 	},
@@ -73,7 +75,19 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 	},
 
-	render: function ( delta ) {
+	render: function ( deltaTime ) {
+
+		// deltaTime value is in seconds
+
+		if ( deltaTime === undefined ) {
+
+			deltaTime = ( Date.now() - this._previousFrameTime ) * 0.001;
+
+		}
+
+		this._previousFrameTime = Date.now();
+
+		var currentRenderTarget = this.renderer.getRenderTarget();
 
 		var maskActive = false;
 
@@ -85,7 +99,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 			if ( pass.enabled === false ) continue;
 
-			pass.render( this.renderer, this.writeBuffer, this.readBuffer, delta, maskActive );
+			pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );
 
 			if ( pass.needsSwap ) {
 
@@ -95,7 +109,7 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 					context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );
 
-					this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, delta );
+					this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );
 
 					context.stencilFunc( context.EQUAL, 1, 0xffffffff );
 
@@ -121,13 +135,15 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 		}
 
+		this.renderer.setRenderTarget( currentRenderTarget );
+
 	},
 
 	reset: function ( renderTarget ) {
 
 		if ( renderTarget === undefined ) {
 
-			var size = this.renderer.getDrawingBufferSize();
+			var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() );
 
 			renderTarget = this.renderTarget1.clone();
 			renderTarget.setSize( size.width, size.height );
@@ -180,7 +196,7 @@ Object.assign( THREE.Pass.prototype, {
 
 	setSize: function ( width, height ) {},
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );
 

+ 6 - 3
examples/js/postprocessing/FilmPass.js

@@ -39,20 +39,23 @@ THREE.FilmPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ),
 
 	constructor: THREE.FilmPass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
-		this.uniforms[ "time" ].value += delta;
+		this.uniforms[ "time" ].value += deltaTime;
 
 		this.quad.material = this.material;
 
 		if ( this.renderToScreen ) {
 
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene, this.camera );
 
 		} else {
 
-			renderer.render( this.scene, this.camera, writeBuffer, this.clear );
+			renderer.setRenderTarget( writeBuffer );
+			if ( this.clear ) renderer.clear();
+			renderer.render( this.scene, this.camera );
 
 		}
 

+ 5 - 2
examples/js/postprocessing/GlitchPass.js

@@ -40,7 +40,7 @@ THREE.GlitchPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 	constructor: THREE.GlitchPass,
 
-	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+	render: function ( renderer, writeBuffer, readBuffer, deltaTime, maskActive ) {
 
 		this.uniforms[ "tDiffuse" ].value = readBuffer.texture;
 		this.uniforms[ 'seed' ].value = Math.random();//default seeding
@@ -77,11 +77,14 @@ THREE.GlitchPass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 
 		if ( this.renderToScreen ) {
 
+			renderer.setRenderTarget( null );
 			renderer.render( this.scene, this.camera );
 
 		} else {
 
-			renderer.render( this.scene, this.camera, writeBuffer, this.clear );
+			renderer.setRenderTarget( writeBuffer );
+			if ( this.clear ) renderer.clear();
+			renderer.render( this.scene, this.camera );
 
 		}
 

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