Browse Source

Merge branch 'dev' into refactor_flexible_skinning

Conflicts:
	src/objects/Skeleton.js
	src/renderers/shaders/ShaderChunk.js
Ian Kerr 11 years ago
parent
commit
8437bfb9c6
100 changed files with 3687 additions and 2892 deletions
  1. 1 1
      bower.json
  2. 268 97
      build/three.js
  3. 189 172
      build/three.min.js
  4. 7 1
      docs/api/core/Object3D.html
  5. 1 1
      docs/api/extras/GeometryUtils.html
  6. 40 12
      docs/api/extras/geometries/ExtrudeGeometry.html
  7. 0 6
      docs/api/extras/geometries/ShapeGeometry.html
  8. 8 6
      docs/api/extras/helpers/BoundingBoxHelper.html
  9. 2 2
      docs/api/extras/renderers/plugins/ShadowMapPlugin.html
  10. 5 0
      docs/api/materials/MeshBasicMaterial.html
  11. 4 0
      docs/api/materials/MeshLambertMaterial.html
  12. 4 0
      docs/api/materials/MeshPhongMaterial.html
  13. 3 5
      editor/js/Menubar.Edit.js
  14. 1 2
      editor/js/Sidebar.Geometry.BoxGeometry.js
  15. 1 3
      editor/js/Sidebar.Geometry.CircleGeometry.js
  16. 1 2
      editor/js/Sidebar.Geometry.CylinderGeometry.js
  17. 1 2
      editor/js/Sidebar.Geometry.IcosahedronGeometry.js
  18. 2 3
      editor/js/Sidebar.Geometry.PlaneGeometry.js
  19. 1 2
      editor/js/Sidebar.Geometry.SphereGeometry.js
  20. 1 2
      editor/js/Sidebar.Geometry.TorusGeometry.js
  21. 1 2
      editor/js/Sidebar.Geometry.TorusKnotGeometry.js
  22. 0 1
      editor/js/Sidebar.Geometry.js
  23. 35 13
      editor/js/Sidebar.Material.js
  24. 144 0
      examples/canvas_effects_stereo.html
  25. 1 1
      examples/canvas_geometry_hierarchy.html
  26. 4 2
      examples/canvas_geometry_nurbs.html
  27. 5 12
      examples/css3d_sprites.html
  28. 4 1
      examples/index.html
  29. 2 2
      examples/js/UCSCharacter.js
  30. 34 48
      examples/js/controls/DeviceOrientationControls.js
  31. 73 0
      examples/js/controls/VRControls.js
  32. 22 15
      examples/js/effects/StereoEffect.js
  33. 216 0
      examples/js/effects/VREffect.js
  34. 1 1
      examples/js/libs/dat.gui.min.js
  35. 32 0
      examples/js/libs/pnltri.min.js
  36. 18 67
      examples/js/loaders/ColladaLoader.js
  37. 4 2
      examples/js/loaders/OBJLoader.js
  38. 0 2
      examples/js/loaders/OBJMTLLoader.js
  39. 114 0
      examples/js/postprocessing/GlitchPass.js
  40. 36 12
      examples/js/renderers/CSS3DRenderer.js
  41. 4 2
      examples/js/renderers/SVGRenderer.js
  42. 103 0
      examples/js/shaders/DigitalGlitch.js
  43. 47 0
      examples/js/shaders/TechnicolorShader.js
  44. 1 1
      examples/webgl_buffergeometry_lines.html
  45. 1 1
      examples/webgl_buffergeometry_lines_indexed.html
  46. 1 1
      examples/webgl_buffergeometry_particles.html
  47. 0 2
      examples/webgl_camera.html
  48. 6 26
      examples/webgl_effects_stereo.html
  49. 215 0
      examples/webgl_effects_vr.html
  50. 1 2
      examples/webgl_geometry_extrude_splines.html
  51. 667 0
      examples/webgl_geometry_text2.html
  52. 4 4
      examples/webgl_interactive_raycasting_pointcloud.html
  53. 3 2
      examples/webgl_loader_collada_keyframe.html
  54. 0 2
      examples/webgl_loader_scene.html
  55. 0 4
      examples/webgl_materials_cubemap_dynamic.html
  56. 220 0
      examples/webgl_objects_update.html
  57. 1 1
      examples/webgl_particles_billboards_colors.html
  58. 142 0
      examples/webgl_postprocessing_glitch.html
  59. 0 5
      examples/webgl_shading_physical.html
  60. 0 6
      examples/webgl_terrain_dynamic.html
  61. 10 15
      src/core/Geometry.js
  62. 39 1
      src/core/Object3D.js
  63. 58 73
      src/core/Projector.js
  64. 9 1
      src/extras/FontUtils.js
  65. 0 7
      src/extras/geometries/ExtrudeGeometry.js
  66. 0 4
      src/extras/geometries/ShapeGeometry.js
  67. 2 0
      src/extras/geometries/TubeGeometry.js
  68. 1 1
      src/extras/helpers/SkeletonHelper.js
  69. 55 51
      src/extras/helpers/WireframeHelper.js
  70. 56 51
      src/extras/renderers/plugins/DepthPassPlugin.js
  71. 18 11
      src/extras/renderers/plugins/LensFlarePlugin.js
  72. 61 56
      src/extras/renderers/plugins/ShadowMapPlugin.js
  73. 34 21
      src/extras/renderers/plugins/SpritePlugin.js
  74. 6 0
      src/loaders/Loader.js
  75. 6 0
      src/materials/MeshBasicMaterial.js
  76. 6 0
      src/materials/MeshLambertMaterial.js
  77. 6 0
      src/materials/MeshPhongMaterial.js
  78. 8 1
      src/materials/PointCloudMaterial.js
  79. 7 7
      src/materials/ShaderMaterial.js
  80. 2 0
      src/renderers/CanvasRenderer.js
  81. 310 294
      src/renderers/WebGLRenderer.js
  82. 1 1739
      src/renderers/shaders/ShaderChunk.js
  83. 5 0
      src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl
  84. 5 0
      src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl
  85. 5 0
      src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl
  86. 40 0
      src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl
  87. 5 0
      src/renderers/shaders/ShaderChunk/color_fragment.glsl
  88. 5 0
      src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl
  89. 5 0
      src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl
  90. 13 0
      src/renderers/shaders/ShaderChunk/color_vertex.glsl
  91. 21 0
      src/renderers/shaders/ShaderChunk/default_vertex.glsl
  92. 27 0
      src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl
  93. 61 0
      src/renderers/shaders/ShaderChunk/envmap_fragment.glsl
  94. 19 0
      src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl
  95. 8 0
      src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl
  96. 18 0
      src/renderers/shaders/ShaderChunk/envmap_vertex.glsl
  97. 27 0
      src/renderers/shaders/ShaderChunk/fog_fragment.glsl
  98. 15 0
      src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl
  99. 5 0
      src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
  100. 6 0
      src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl

+ 1 - 1
bower.json

@@ -3,7 +3,7 @@
 	"version": "0.0.67",
 	"homepage": "http://threejs.org/",
 	"description": "JavaScript 3D library",
-	"main": "build/three.js",
+	"main": "build/three.min.js",
 	"keywords": [
 		"three",
 		"threejs",

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


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


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

@@ -25,7 +25,13 @@
 
 		<h3>.[page:Integer id]</h3>
 		<div>
-		Unique number of this object instance.
+		Identifier of this object instance.
+		</div>
+		
+		<h3>.[page:String uuid]</h3>
+		<div>
+		[link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID] of this object instance. 
+		This gets automatically assigned, so this shouldn't be edited.
 		</div>
 
 		<h3>.[page:String name]</h3>

+ 1 - 1
docs/api/extras/GeometryUtils.html

@@ -16,7 +16,7 @@
 
 		<h3> .merge( [page:Geometry geometry1] , [page:Geometry geometry2], [page:Integer materialIndexOffset] )</h3>
 		<div>
-		geometry1 — Parent geomentry element <br />
+		geometry1 — Parent geometry element <br />
 		geometry2 — Geometry that need to be added in parent <br />
 		materialIndexOffset — Offset applied to the materialIndex of all the new faces in the merged geometry. Default : 0 <br />
 		</div>

+ 40 - 12
docs/api/extras/geometries/ExtrudeGeometry.html

@@ -17,7 +17,7 @@
 		<h2>Constructor</h2>
 
 
-		<h3>[name]([page:todo shapes], [page:Object options])</h3>
+		<h3>[name]([page:Array shapes], [page:Object options])</h3>
 		<div>
 		shapes — Shape or an array of shapes. <br />
 		options — Object that can contain the following parameters.
@@ -39,7 +39,7 @@
 
 		</div>
 		<div>
-		todo
+		This object extrudes an 2D shape to an 3D geometry.
 		</div>
 
 
@@ -48,19 +48,47 @@
 
 		<h2>Methods</h2>
 
-		<h3>.addShapeList ([page:todo shapes], [page:Object options])</h3>
+		<h3>.addShapeList ([page:Array shapes], [page:Object options])</h3>
 		<div>
-			shapes — todo <br />
-			options — todo
-		</div>
-		<div>todo</div>
+			shapes — An Array of shapes to add. <br />
+			options — Object that can contain the following parameters.
+	<ul>
+<li>curveSegments —  int. number of points on the curves</li>
+<li>steps —  int. number of points used for subdividing segements of extrude spline</li>
+<li>amount —  int. Depth to extrude the shape</li>
+<li>bevelEnabled —  bool. turn on bevel</li>
+<li>bevelThickness —  float. how deep into the original shape bevel goes</li>
+<li>bevelSize —  float. how far from shape outline is bevel</li>
+<li>bevelSegments —  int. number of bevel layers</li>
+<li>extrudePath —  THREE.CurvePath. 3d spline path to extrude shape along. (creates Frames if (frames aren't defined)</li>
+<li>frames —  THREE.TubeGeometry.FrenetFrames.  containing arrays of tangents, normals, binormals</li>
+<li>material —  int. material index for front and back faces</li>
+<li>extrudeMaterial —  int. material index for extrusion and beveled faces</li>
+<li>uvGenerator —  Object. object that provides UV generator functions</li>
+	</ul>
+	</div>
+		<div>Adds the shapes to the list to extrude.</div>
 
-		<h3>.addShape ([page:todo shape], [page:Object options])</h3>
+		<h3>.addShape ([page:Shape shape], [page:Object options])</h3>
 		<div>
-			shape — todo <br />
-			options — todo
-		</div>
-		<div>todo</div>
+			shape — A shape to add. <br />
+			options — Object that can contain the following parameters.
+	<ul>
+<li>curveSegments —  int. number of points on the curves</li>
+<li>steps —  int. number of points used for subdividing segements of extrude spline</li>
+<li>amount —  int. Depth to extrude the shape</li>
+<li>bevelEnabled —  bool. turn on bevel</li>
+<li>bevelThickness —  float. how deep into the original shape bevel goes</li>
+<li>bevelSize —  float. how far from shape outline is bevel</li>
+<li>bevelSegments —  int. number of bevel layers</li>
+<li>extrudePath —  THREE.CurvePath. 3d spline path to extrude shape along. (creates Frames if (frames aren't defined)</li>
+<li>frames —  THREE.TubeGeometry.FrenetFrames.  containing arrays of tangents, normals, binormals</li>
+<li>material —  int. material index for front and back faces</li>
+<li>extrudeMaterial —  int. material index for extrusion and beveled faces</li>
+<li>uvGenerator —  Object. object that provides UV generator functions</li>
+	</ul>
+	</div>
+		<div>Add the shape to the list to extrude.</div>
 
 
 		<h2>Source</h2>

+ 0 - 6
docs/api/extras/geometries/ShapeGeometry.html

@@ -52,12 +52,6 @@
 		<h2>Properties</h2>
 
 
-
-		<h3>.[page:Object shapebb]</h3>
-		<div>
-		todo
-		</div> 
-
 		<h2>Methods</h2>
 
 

+ 8 - 6
docs/api/extras/helpers/BoundingBoxHelper.html

@@ -16,13 +16,15 @@
 
 		<h2>Example</h2>
 
-		<code>var dir = new THREE.Vector3( 1, 0, 0 );
-		var origin = new THREE.Vector3( 0, 0, 0 );
-		var length = 1;
-		var hex = 0xffff00;
+		<code>var hex  = 0xff0000;
 
-		var arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex );
-		scene.add( arrowHelper );
+		var sphereMaterial = new THREE.MeshLambertMaterial( {color: 0x00ff00} );
+		var sphere = new THREE.Mesh( new THREE.SphereGeometry( 30, 12, 12), sphereMaterial );
+		scene.add( sphere );
+
+		var bbox = new THREE.BoundingBoxHelper( sphere, hex );
+		bbox.update();
+		scene.add( bbox );
 		</code>
 
 

+ 2 - 2
docs/api/extras/renderers/plugins/ShadowMapPlugin.html

@@ -27,7 +27,7 @@
 
 
 
-		<h3>.init([page:WebglRenderer renderer])</h3>
+		<h3>.init([page:WebGLRenderer renderer])</h3>
 		<div>
 		renderer -- The WebglRenderer that uses the plugin.
 		</div>
@@ -41,7 +41,7 @@
 		camera -- The camera to render.
 		</div>
 		<div>
-		Updates the textures nessecary for the shadowmaps. This gets called by updateShadowMap in [page:WebglRenderer].
+		Updates the textures nessecary for the shadowmaps. This gets called by updateShadowMap in [page:WebGLRenderer].
 		</div>
 
 		<h3>.render([page:Scene scene], [page:Camera camera])</h3>

+ 5 - 0
docs/api/materials/MeshBasicMaterial.html

@@ -32,6 +32,7 @@
 		fog — Define whether the material color is affected by global fog settings. Default is true.<br />
 		lightMap — Set light map. Default is null.<br />
 		specularMap — Set specular map. Default is null.<br />
+		alphaMap — Set alpha map. Default is null.<br />
 		envMap — Set env map. Default is null.<br />
 		skinning — Define whether the material uses skinning. Default is false.<br />
 		morphTargets — Define whether the material uses morphTargets. Default is false.
@@ -74,6 +75,10 @@
 		<h3>.[page:Texture specularMap]</h3>
 		<div>Set specular map. Default is null.</div>
 
+		<h3>.[page:Texture alphaMap]</h3>
+		<div>The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). Default is null.</div>
+		<div>Only the color of the texture is used, ignoring the alpha channel if one exists. For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the green channel when sampling this texture due to the extra bit of precision provided for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and luminance/alpha textures will also still work as expected.</div>
+
 		<h3>.[page:TextureCube envMap]</h3>
 		<div>Set env map. Default is null.</div>
 

+ 4 - 0
docs/api/materials/MeshLambertMaterial.html

@@ -81,6 +81,10 @@
 		<h3>.[page:Texture specularMap]</h3>
 		<div>Since this material does not have a specular component, the specular value affects only how much of the environment map affects the surface. Default is null.</div>
 
+		<h3>.[page:Texture alphaMap]</h3>
+		<div>The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). Default is null.</div>
+		<div>Only the color of the texture is used, ignoring the alpha channel if one exists. For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the green channel when sampling this texture due to the extra bit of precision provided for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and luminance/alpha textures will also still work as expected.</div>
+
 		<h3>.[page:TextureCube envMap]</h3>
 		<div>Set env map. Default is null.</div>
 

+ 4 - 0
docs/api/materials/MeshPhongMaterial.html

@@ -91,6 +91,10 @@
 		<h3>.[page:Texture specularMap]</h3>
 		<div>The specular map value affects both how much the specular surface highlight contributes and how much of the environment map affects the surface. Default is null.</div>
 
+		<h3>.[page:Texture alphaMap]</h3>
+		<div>The alpha map is a grayscale texture that controls the opacity across the surface (black: fully transparent; white: fully opaque). Default is null.</div>
+		<div>Only the color of the texture is used, ignoring the alpha channel if one exists. For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the green channel when sampling this texture due to the extra bit of precision provided for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and luminance/alpha textures will also still work as expected.</div>
+
 		<h3>.[page:TextureCube envMap]</h3>
 		<div>Set env map. Default is null.</div>
 

+ 3 - 5
editor/js/Menubar.Edit.js

@@ -47,8 +47,6 @@ Menubar.Edit = function ( editor ) {
 
 			if ( confirm( 'Convert ' + object.name + ' to BufferGeometry?' ) === false ) return;
 
-			delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 			object.geometry = new THREE.BufferGeometry().fromGeometry( object.geometry );
 
 			editor.signals.objectChanged.dispatch( object );
@@ -65,17 +63,17 @@ Menubar.Edit = function ( editor ) {
 
 		if ( confirm( 'Flatten ' + object.name + '?' ) === false ) return;
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		var geometry = object.geometry.clone();
 		geometry.applyMatrix( object.matrix );
 
+
 		object.geometry = geometry;
 
 		object.position.set( 0, 0, 0 );
 		object.rotation.set( 0, 0, 0 );
 		object.scale.set( 1, 1, 1 );
-
+		
+		object.geometry.buffersNeedUpdate = true;
 		editor.signals.objectChanged.dispatch( object );
 
 	}

+ 1 - 2
editor/js/Sidebar.Geometry.BoxGeometry.js

@@ -68,8 +68,6 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.BoxGeometry(
@@ -81,6 +79,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 			depthSegments.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 1 - 3
editor/js/Sidebar.Geometry.CircleGeometry.js

@@ -28,15 +28,13 @@ Sidebar.Geometry.CircleGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.CircleGeometry(
 			radius.getValue(),
 			segments.getValue()
 		);
-
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 1 - 2
editor/js/Sidebar.Geometry.CylinderGeometry.js

@@ -68,8 +68,6 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.CylinderGeometry(
@@ -81,6 +79,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 			openEnded.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 1 - 2
editor/js/Sidebar.Geometry.IcosahedronGeometry.js

@@ -29,8 +29,6 @@ Sidebar.Geometry.IcosahedronGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.IcosahedronGeometry(
@@ -38,6 +36,7 @@ Sidebar.Geometry.IcosahedronGeometry = function ( signals, object ) {
 			detail.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 2 - 3
editor/js/Sidebar.Geometry.PlaneGeometry.js

@@ -48,9 +48,7 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 	//
 
 	function update() {
-
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
+		
 		object.geometry.dispose();
 
 		object.geometry = new THREE.PlaneGeometry(
@@ -60,6 +58,7 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 			heightSegments.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 1 - 2
editor/js/Sidebar.Geometry.SphereGeometry.js

@@ -79,8 +79,6 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.SphereGeometry(
@@ -93,6 +91,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 			thetaLength.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 1 - 2
editor/js/Sidebar.Geometry.TorusGeometry.js

@@ -59,8 +59,6 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.TorusGeometry(
@@ -71,6 +69,7 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 			arc.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 1 - 2
editor/js/Sidebar.Geometry.TorusKnotGeometry.js

@@ -79,8 +79,6 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 
 	function update() {
 
-		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
-
 		object.geometry.dispose();
 
 		object.geometry = new THREE.TorusKnotGeometry(
@@ -93,6 +91,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 			heightScale.getValue()
 		);
 
+		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
 		signals.objectChanged.dispatch( object );

+ 0 - 1
editor/js/Sidebar.Geometry.js

@@ -91,7 +91,6 @@ Sidebar.Geometry = function ( editor ) {
 
 			updateFields( geometry );
 
-			//
 
 			if ( parameters !== undefined ) {
 

+ 35 - 13
editor/js/Sidebar.Material.js

@@ -71,6 +71,7 @@ Sidebar.Material = function ( editor ) {
 		'MeshLambertMaterial': 'MeshLambertMaterial',
 		'MeshNormalMaterial': 'MeshNormalMaterial',
 		'MeshPhongMaterial': 'MeshPhongMaterial',
+		'ShaderMaterial': 'ShaderMaterial',
 		'SpriteMaterial': 'SpriteMaterial'
 
 	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
@@ -130,6 +131,26 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialShininessRow );
 
+	// vertex shader
+
+	var materialVertexShaderRow = new UI.Panel();
+	var materialVertexShader = new UI.TextArea().setWidth( '150px' ).setHeight( '40px' ).onChange( update );
+
+	materialVertexShaderRow.add( new UI.Text( 'Vertex Shader' ).setWidth( '90px' ) );
+	materialVertexShaderRow.add( materialVertexShader );
+
+	container.add( materialVertexShaderRow );
+
+	// fragment shader
+
+	var materialFragmentShaderRow = new UI.Panel();
+	var materialFragmentShader = new UI.TextArea().setWidth( '150px' ).setHeight( '40px' ).onChange( update );
+
+	materialFragmentShaderRow.add( new UI.Text( 'Fragment Shader' ).setWidth( '90px' ) );
+	materialFragmentShaderRow.add( materialFragmentShader );
+
+	container.add( materialFragmentShaderRow );
+
 	// vertex colors
 
 	var materialVertexColorsRow = new UI.Panel();
@@ -146,7 +167,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialVertexColorsRow );
 
-
 	// skinning
 
 	var materialSkinningRow = new UI.Panel();
@@ -157,7 +177,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialSkinningRow );
 
-
 	// map
 
 	var materialMapRow = new UI.Panel();
@@ -170,7 +189,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialMapRow );
 
-
 	// light map
 
 	var materialLightMapRow = new UI.Panel();
@@ -183,7 +201,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialLightMapRow );
 
-
 	// bump map
 
 	var materialBumpMapRow = new UI.Panel();
@@ -198,7 +215,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialBumpMapRow );
 
-
 	// normal map
 
 	var materialNormalMapRow = new UI.Panel();
@@ -211,7 +227,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialNormalMapRow );
 
-
 	// specular map
 
 	var materialSpecularMapRow = new UI.Panel();
@@ -224,7 +239,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialSpecularMapRow );
 
-
 	// env map
 
 	var materialEnvMapRow = new UI.Panel();
@@ -239,7 +253,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialEnvMapRow );
 
-
 	// blending
 
 	var materialBlendingRow = new UI.Panel();
@@ -259,7 +272,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialBlendingRow );
 
-
 	// side
 
 	var materialSideRow = new UI.Panel();
@@ -276,7 +288,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialSideRow );
 
-
 	// opacity
 
 	var materialOpacityRow = new UI.Panel();
@@ -287,7 +298,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialOpacityRow );
 
-
 	// transparent
 
 	var materialTransparentRow = new UI.Panel();
@@ -298,7 +308,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialTransparentRow );
 
-
 	// wireframe
 
 	var materialWireframeRow = new UI.Panel();
@@ -311,7 +320,6 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialWireframeRow );
 
-
 	//
 
 	function update() {
@@ -574,6 +582,8 @@ Sidebar.Material = function ( editor ) {
 			'emissive': materialEmissiveRow,
 			'specular': materialSpecularRow,
 			'shininess': materialShininessRow,
+			'vertexShader': materialVertexShaderRow,
+			'fragmentShader': materialFragmentShaderRow,
 			'vertexColors': materialVertexColorsRow,
 			'skinning': materialSkinningRow,
 			'map': materialMapRow,
@@ -653,6 +663,18 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.vertexShader !== undefined ) {
+
+				materialVertexShader.setValue( material.vertexShader );
+
+			}
+
+			if ( material.fragmentShader !== undefined ) {
+
+				materialFragmentShader.setValue( material.fragmentShader );
+
+			}
+
 			if ( material.vertexColors !== undefined ) {
 
 				materialVertexColors.setValue( material.vertexColors );

+ 144 - 0
examples/canvas_effects_stereo.html

@@ -0,0 +1,144 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js canvas - effects - stereo</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				background:#fff;
+				padding:0;
+				margin:0;
+				font-weight: bold;
+				overflow:hidden;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/effects/StereoEffect.js"></script>
+
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			var container, stats;
+
+			var camera, scene, renderer;
+
+			var geometry, group;
+
+			var effect;
+
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.z = 500;
+
+				scene = new THREE.Scene();
+
+				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } );
+
+				group = new THREE.Object3D();
+
+				for ( var i = 0; i < 200; i ++ ) {
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.position.x = Math.random() * 2000 - 1000;
+					mesh.position.y = Math.random() * 2000 - 1000;
+					mesh.position.z = Math.random() * 2000 - 1000;
+					mesh.rotation.x = Math.random() * 2 * Math.PI;
+					mesh.rotation.y = Math.random() * 2 * Math.PI;
+					mesh.matrixAutoUpdate = false;
+					mesh.updateMatrix();
+					group.add( mesh );
+
+				}
+
+				scene.add( group );
+
+				renderer = new THREE.CanvasRenderer();
+				renderer.setClearColor( 0xffffff );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				effect = new THREE.StereoEffect( renderer );
+				effect.setSize( window.innerWidth, window.innerHeight );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				stats.domElement.style.zIndex = 100;
+				container.appendChild( stats.domElement );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				effect.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function onDocumentMouseMove(event) {
+
+				mouseX = ( event.clientX - windowHalfX ) * 10;
+				mouseY = ( event.clientY - windowHalfY ) * 10;
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				camera.position.x += ( mouseX - camera.position.x ) * .05;
+				camera.position.y += ( - mouseY - camera.position.y ) * .05;
+				camera.lookAt( scene.position );
+
+				var currentSeconds = Date.now();
+				group.rotation.x = Math.sin( currentSeconds * 0.0007 ) * 0.5;
+				group.rotation.y = Math.sin( currentSeconds * 0.0003 ) * 0.5;
+				group.rotation.z = Math.sin( currentSeconds * 0.0002 ) * 0.5;
+
+				effect.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 1 - 1
examples/canvas_geometry_hierarchy.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js canvas - geometry hierarchy 2</title>
+		<title>three.js canvas - geometry - hierarchy</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>

+ 4 - 2
examples/canvas_geometry_nurbs.html

@@ -108,7 +108,6 @@
 
 				var nurbsLine = new THREE.Line( nurbsGeometry, nurbsMaterial );
 				nurbsLine.position.set( 0, -100, 0 );
-				group.add( nurbsLine );
 
 				var nurbsControlPointsGeometry = new THREE.Geometry();
 				nurbsControlPointsGeometry.vertices = nurbsCurve.controlPoints;
@@ -116,7 +115,10 @@
 
 				var nurbsControlPointsLine = new THREE.Line( nurbsControlPointsGeometry, nurbsControlPointsMaterial );
 				nurbsControlPointsLine.position.copy( nurbsLine.position );
-				group.add( nurbsControlPointsLine );
+
+				group.add( nurbsLine, nurbsControlPointsLine );
+				// this also works:
+				// group.add( nurbsLine ).add( nurbsControlPointsLine );
 
 				//
 

+ 5 - 12
examples/css3d_sprites.html

@@ -63,19 +63,12 @@
 
 				scene = new THREE.Scene();
 
-				var sprite = document.createElement( 'img' );
-				sprite.addEventListener( 'load', function ( event ) {
+				var image = document.createElement( 'img' );
+				image.addEventListener( 'load', function ( event ) {
 
-					for ( var i = 0, j = 0; i < particlesTotal; i ++, j += 3 ) {
+					for ( var i = 0; i < particlesTotal; i ++ ) {
 
-						var canvas = document.createElement( 'canvas' );
-						canvas.width = sprite.width;
-						canvas.height = sprite.height;
-
-						var context = canvas.getContext( '2d' );
-						context.drawImage( sprite, 0, 0 );
-
-						var object = new THREE.CSS3DSprite( canvas );
+						var object = new THREE.CSS3DSprite( image.cloneNode() );
 						object.position.x = Math.random() * 4000 - 2000,
 						object.position.y = Math.random() * 4000 - 2000,
 						object.position.z = Math.random() * 4000 - 2000
@@ -88,7 +81,7 @@
 					transition();
 
 				}, false );
-				sprite.src = 'textures/sprite.png';
+				image.src = 'textures/sprite.png';
 
 				// Plane
 

+ 4 - 1
examples/index.html

@@ -121,9 +121,10 @@
 				"webgl_custom_attributes_particles2",
 				"webgl_custom_attributes_particles3",
 				"webgl_effects_anaglyph",
-				"webgl_effects_crosseyed",
 				"webgl_effects_oculusrift",
 				"webgl_effects_parallaxbarrier",
+				"webgl_effects_stereo",
+				"webgl_effects_vr",
 				"webgl_geometries",
 				"webgl_geometries2",
 				"webgl_geometry_colors",
@@ -250,6 +251,7 @@
 				"webgl_postprocessing_dof2",
 				"webgl_postprocessing_godrays",
 				"webgl_postprocessing_crossfade",
+				"webgl_postprocessing_glitch",
 				"webgl_rtt",
 				"webgl_sandbox",
 				"webgl_shader",
@@ -304,6 +306,7 @@
 				"canvas_ascii_effect",
 				"canvas_camera_orthographic",
 				"canvas_camera_orthographic2",
+				"canvas_effects_stereo",
 				"canvas_geometry_birds",
 				"canvas_geometry_cube",
 				"canvas_geometry_earth",

+ 2 - 2
examples/js/UCSCharacter.js

@@ -41,7 +41,7 @@ THREE.UCSCharacter = function() {
 			geometry.computeBoundingBox();
 			geometry.computeVertexNormals();
 
-			THREE.AnimationHandler.add( geometry.animation );
+			//THREE.AnimationHandler.add( geometry.animation );
 
 			mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshFaceMaterial() );
 			scope.root.add( mesh );
@@ -53,7 +53,7 @@ THREE.UCSCharacter = function() {
 			mesh.castShadow = true;
 			mesh.receiveShadow = true;
 
-			animation = new THREE.Animation( mesh, geometry.animation.name );
+			animation = new THREE.Animation( mesh, geometry.animation );
 			animation.play();
 			
 			scope.setSkin(0);

+ 34 - 48
examples/js/controls/DeviceOrientationControls.js

@@ -7,6 +7,8 @@
 
 THREE.DeviceOrientationControls = function ( object ) {
 
+	var scope = this;
+
 	this.object = object;
 
 	this.object.rotation.reorder( "YXZ" );
@@ -17,91 +19,75 @@ THREE.DeviceOrientationControls = function ( object ) {
 
 	this.screenOrientation = 0;
 
-	this.onDeviceOrientationChangeEvent = function( rawEvtData ) {
+	var onDeviceOrientationChangeEvent = function ( event ) {
 
-		this.deviceOrientation = rawEvtData;
+		scope.deviceOrientation = event;
 
 	};
 
-	this.onScreenOrientationChangeEvent = function() {
+	var onScreenOrientationChangeEvent = function () {
 
-		this.screenOrientation = window.orientation || 0;
+		scope.screenOrientation = window.orientation || 0;
 
 	};
 
-	this.update = function() {
+	// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
 
-		var alpha, beta, gamma;
+	var setObjectQuaternion = function () {
 
-		return function () {
+		var zee = new THREE.Vector3( 0, 0, 1 );
 
-			if ( this.freeze ) return;
+		var euler = new THREE.Euler();
 
-			alpha  = this.deviceOrientation.gamma ? THREE.Math.degToRad( this.deviceOrientation.alpha ) : 0; // Z
-			beta   = this.deviceOrientation.beta  ? THREE.Math.degToRad( this.deviceOrientation.beta  ) : 0; // X'
-			gamma  = this.deviceOrientation.gamma ? THREE.Math.degToRad( this.deviceOrientation.gamma ) : 0; // Y''
-			orient = this.screenOrientation       ? THREE.Math.degToRad( this.screenOrientation       ) : 0; // O
+		var q0 = new THREE.Quaternion();
 
-			setObjectQuaternion( this.object.quaternion, alpha, beta, gamma, orient );
+		var q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis
 
-		}
+		return function ( quaternion, alpha, beta, gamma, orient ) {
 
-	}();
+			euler.set( beta, alpha, - gamma, 'YXZ' );                       // 'ZXY' for the device, but 'YXZ' for us
 
-	function bind( scope, fn ) {
+			quaternion.setFromEuler( euler );                               // orient the device
 
-		return function () {
+			quaternion.multiply( q1 );                                      // camera looks out the back of the device, not the top
 
-			fn.apply( scope, arguments );
+			quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) );    // adjust for screen orientation
 
-		};
+		}
 
-	};
+	}();
 
 	this.connect = function() {
 
-		this.onScreenOrientationChangeEvent(); // run once on load
+		onScreenOrientationChangeEvent(); // run once on load
 
-		window.addEventListener( 'orientationchange', bind( this, this.onScreenOrientationChangeEvent ), false );
-		window.addEventListener( 'deviceorientation', bind( this, this.onDeviceOrientationChangeEvent ), false );
+		window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
+		window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
 
-		this.freeze = false;
+		scope.freeze = false;
 
 	};
 
 	this.disconnect = function() {
 
-		this.freeze = true;
+		scope.freeze = true;
 
-		window.removeEventListener( 'orientationchange', bind( this, this.onScreenOrientationChangeEvent ), false );
-		window.removeEventListener( 'deviceorientation', bind( this, this.onDeviceOrientationChangeEvent ), false );
+		window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
+		window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
 
 	};
 
-	// The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''
+	this.update = function () {
 
-	setObjectQuaternion = function () {
+		if ( scope.freeze ) return;
 
-		var zee = new THREE.Vector3( 0, 0, 1 );
+		var alpha  = scope.deviceOrientation.gamma ? THREE.Math.degToRad( scope.deviceOrientation.alpha ) : 0; // Z
+		var beta   = scope.deviceOrientation.beta  ? THREE.Math.degToRad( scope.deviceOrientation.beta  ) : 0; // X'
+		var gamma  = scope.deviceOrientation.gamma ? THREE.Math.degToRad( scope.deviceOrientation.gamma ) : 0; // Y''
+		var orient = scope.screenOrientation       ? THREE.Math.degToRad( scope.screenOrientation       ) : 0; // O
 
-		var euler = new THREE.Euler();
+		setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient );
 
-		var q0 = new THREE.Quaternion();
-
-		var q1 = new THREE.Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis
-
-		return function ( quaternion, alpha, beta, gamma, orient ) {
-
-			euler.set( beta, alpha, - gamma, 'YXZ' );                       // 'ZXY' for the device, but 'YXZ' for us
-
-			quaternion.setFromEuler( euler );                               // orient the device
-
-			quaternion.multiply( q1 );                                      // camera looks out the back of the device, not the top
-
-			quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) );    // adjust for screen orientation
-
-		}
-
-	}();
+	};
 
 };

+ 73 - 0
examples/js/controls/VRControls.js

@@ -0,0 +1,73 @@
+/**
+ * @author dmarcos / https://github.com/dmarcos
+ */
+
+THREE.VRControls = function ( camera, done ) {
+
+	this._camera = camera;
+
+	this._init = function () {
+		var self = this;
+		if ( !navigator.mozGetVRDevices ) {
+			if ( done ) {
+				done("Your browser is not VR Ready");
+			}
+			return;
+		}
+		navigator.mozGetVRDevices( gotVRDevices );
+		function gotVRDevices( devices ) {
+			var vrInput;
+			var error;
+			for ( var i = 0; i < devices.length; ++i ) {
+				if ( devices[i] instanceof PositionSensorVRDevice ) {
+					vrInput = devices[i]
+					self._vrInput = vrInput;
+					break; // We keep the first we encounter
+				}
+			}
+			if ( done ) {
+				if ( !vrInput ) {
+				 error = 'HMD not available';
+				}
+				done( error );
+			}
+		}
+	};
+
+	this._init();
+
+	this.update = function() {
+		var camera = this._camera;
+		var quat;
+		var vrState = this.getVRState();
+		if ( !vrState ) {
+			return;
+		}
+		// Applies head rotation from sensors data.
+		if ( camera ) {
+			camera.quaternion.fromArray( vrState.hmd.rotation );
+		}
+	};
+
+	this.getVRState = function() {
+		var vrInput = this._vrInput;
+		var orientation;
+		var vrState;
+		if ( !vrInput ) {
+			return null;
+		}
+		orientation	= vrInput.getState().orientation;
+		vrState = {
+			hmd : {
+				rotation : [
+					orientation.x,
+					orientation.y,
+					orientation.z,
+					orientation.w
+				]
+			}
+		};
+		return vrState;
+	};
+
+};

+ 22 - 15
examples/js/effects/CrosseyedEffect.js → examples/js/effects/StereoEffect.js

@@ -1,22 +1,25 @@
 /**
  * @author alteredq / http://alteredqualia.com/
+ * @authod mrdoob / http://mrdoob.com/
+ * @authod arodic / http://aleksandarrodic.com/
  */
 
-THREE.CrosseyedEffect = function ( renderer ) {
+THREE.StereoEffect = function ( renderer ) {
 
 	// API
 
-	this.separation = 10;
+	this.separation = 3;
 
 	// internals
 
 	var _width, _height;
 
-	var _cameraL = new THREE.PerspectiveCamera();
-	_cameraL.target = new THREE.Vector3();
+	var _position = new THREE.Vector3();
+	var _quaternion = new THREE.Quaternion();
+	var _scale = new THREE.Vector3();
 
+	var _cameraL = new THREE.PerspectiveCamera();
 	var _cameraR = new THREE.PerspectiveCamera();
-	_cameraR.target = new THREE.Vector3();
 
 	// initialization
 
@@ -33,6 +36,12 @@ THREE.CrosseyedEffect = function ( renderer ) {
 
 	this.render = function ( scene, camera ) {
 
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+	
+		camera.matrixWorld.decompose( _position, _quaternion, _scale );
+
 		// left
 
 		_cameraL.fov = camera.fov;
@@ -41,32 +50,30 @@ THREE.CrosseyedEffect = function ( renderer ) {
 		_cameraL.far = camera.far;
 		_cameraL.updateProjectionMatrix();
 
-		_cameraL.position.copy( camera.position );
-		_cameraL.target.copy( camera.target );
-		_cameraL.translateX( this.separation );
-		_cameraL.lookAt( _cameraL.target );
+		_cameraL.position.copy( _position );
+		_cameraL.quaternion.copy( _quaternion );
+		_cameraL.translateX( - this.separation );
 
 		// right
 
 		_cameraR.near = camera.near;
 		_cameraR.far = camera.far;
-
 		_cameraR.projectionMatrix = _cameraL.projectionMatrix;
 
-		_cameraR.position.copy( camera.position );
-		_cameraR.target.copy( camera.target );
-		_cameraR.translateX( - this.separation );
-		_cameraR.lookAt( _cameraR.target );
+		_cameraR.position.copy( _position );
+		_cameraR.quaternion.copy( _quaternion );
+		_cameraR.translateX( this.separation );
 
 		//
 
+		renderer.setViewport( 0, 0, _width * 2, _height );
 		renderer.clear();
 
 		renderer.setViewport( 0, 0, _width, _height );
 		renderer.render( scene, _cameraL );
 
 		renderer.setViewport( _width, 0, _width, _height );
-		renderer.render( scene, _cameraR, false );
+		renderer.render( scene, _cameraR );
 
 	};
 

+ 216 - 0
examples/js/effects/VREffect.js

@@ -0,0 +1,216 @@
+/**
+ * @author dmarcos / https://github.com/dmarcos
+ *
+ * It handles stereo rendering
+ * If mozGetVRDevices API is not available it gracefuly falls back to a
+ * regular renderer
+ *
+ * The HMD supported is the Oculus DK1 and The Web API doesn't currently allow
+ * to query for the display resolution. The dimensions of the screen are temporarly
+ * hardcoded (1280 x 800).
+ *
+ * For VR mode to work it has to be used with the Oculus enabled builds of Firefox:
+ *
+ * OSX: http://people.mozilla.com/~vladimir/vr/firefox-33.0a1.en-US.mac.dmg
+ * WIN: http://people.mozilla.com/~vladimir/vr/firefox-33.0a1.en-US.win64-x86_64.zip
+ *
+ */
+THREE.VREffect = function ( renderer, done ) {
+
+	this._renderer = renderer;
+
+	this._init = function() {
+		var self = this;
+		if ( !navigator.mozGetVRDevices ) {
+			if ( done ) {
+				done("Your browser is not VR Ready");
+			}
+			return;
+		}
+		navigator.mozGetVRDevices( gotVRDevices );
+		function gotVRDevices( devices ) {
+			var vrHMD;
+			var error;
+			for ( var i = 0; i < devices.length; ++i ) {
+				if ( devices[i] instanceof HMDVRDevice ) {
+					vrHMD = devices[i];
+					self._vrHMD = vrHMD;
+					self.leftEyeTranslation = vrHMD.getEyeTranslation( "left" );
+					self.rightEyeTranslation = vrHMD.getEyeTranslation( "right" );
+					self.leftEyeFOV = vrHMD.getRecommendedEyeFieldOfView( "left" );
+					self.rightEyeFOV = vrHMD.getRecommendedEyeFieldOfView( "right" );
+					break; // We keep the first we encounter
+				}
+			}
+			if ( done ) {
+				if ( !vrHMD ) {
+				 error = 'HMD not available';
+				}
+				done( error );
+			}
+		}
+	};
+
+	this._init();
+
+	this.render = function ( scene, camera ) {
+		var renderer = this._renderer;
+		var vrHMD = this._vrHMD;
+		renderer.enableScissorTest( false );
+		// VR render mode if HMD is available
+		if ( vrHMD ) {
+			this.renderStereo.apply( this, arguments );
+			return;
+		}
+		// Regular render mode if not HMD
+		renderer.render.apply( this._renderer , arguments );
+	};
+
+	this.renderStereo = function( scene, camera, renderTarget, forceClear ) {
+		var cameraLeft;
+		var cameraRight;
+		var leftEyeTranslation = this.leftEyeTranslation;
+		var rightEyeTranslation = this.rightEyeTranslation;
+		var renderer = this._renderer;
+		var rendererWidth = renderer.domElement.width / renderer.devicePixelRatio;
+		var rendererHeight = renderer.domElement.height / renderer.devicePixelRatio;
+		var eyeDivisionLine = rendererWidth / 2;
+		renderer.enableScissorTest( true );
+		renderer.clear();
+
+		// Grab camera matrix from user.
+		// This is interpreted as the head base.
+		if ( camera.matrixAutoUpdate ) {
+			camera.updateMatrix();
+		}
+		var eyeWorldMatrix = camera.matrixWorld.clone();
+
+		cameraLeft = camera.clone();
+		cameraRight = camera.clone();
+		cameraLeft.projectionMatrix = this.FovToProjection( this.leftEyeFOV );
+		cameraRight.projectionMatrix = this.FovToProjection( this.rightEyeFOV );
+		cameraLeft.position.add(new THREE.Vector3(
+			leftEyeTranslation.x, leftEyeTranslation.y, leftEyeTranslation.z) );
+		cameraRight.position.add(new THREE.Vector3(
+			rightEyeTranslation.x, rightEyeTranslation.y, rightEyeTranslation.z) );
+
+		// render left eye
+		renderer.setViewport( 0, 0, eyeDivisionLine, rendererHeight );
+		renderer.setScissor( 0, 0, eyeDivisionLine, rendererHeight );
+		renderer.render( scene, cameraLeft );
+
+		// render right eye
+		renderer.setViewport( eyeDivisionLine, 0, eyeDivisionLine, rendererHeight );
+		renderer.setScissor( eyeDivisionLine, 0, eyeDivisionLine, rendererHeight );
+		renderer.render( scene, cameraRight );
+
+	};
+
+	this.setFullScreen = function( enable ) {
+		var renderer = this._renderer;
+		var vrHMD = this._vrHMD;
+		var canvasOriginalSize = this._canvasOriginalSize;
+		if (!vrHMD) {
+			return;
+		}
+		// If state doesn't change we do nothing
+		if ( enable === this._fullScreen ) {
+			return;
+		}
+		this._fullScreen = !!enable;
+
+		// VR Mode disabled
+		if ( !enable ) {
+			// Restores canvas original size
+			renderer.setSize( canvasOriginalSize.width, canvasOriginalSize.height );
+			return;
+		}
+		// VR Mode enabled
+		this._canvasOriginalSize = {
+			width: renderer.domElement.width,
+			height: renderer.domElement.height
+		};
+		fullScreen = true;
+		// Hardcoded Rift display size
+		renderer.setSize( 1280, 800 );
+		vrHMD.xxxToggleElementVR( renderer.domElement );
+		this.startFullscreen( vrHMD );
+	};
+
+	this.startFullscreen = function( vrHMD ) {
+		var self = this;
+		var renderer = this._renderer;
+		document.addEventListener( "mozfullscreenchange", function() {
+			if ( !document.mozFullScreenElement ) {
+				self.setFullScreen( false );
+			}
+		},false );
+		renderer.domElement.mozRequestFullScreen( { vrDisplay: vrHMD } );
+	};
+
+	this.FovToNDCScaleOffset = function( fov ) {
+		var pxscale = 2.0 / (fov.leftTan + fov.rightTan);
+		var pxoffset = (fov.leftTan - fov.rightTan) * pxscale * 0.5;
+		var pyscale = 2.0 / (fov.upTan + fov.downTan);
+		var pyoffset = (fov.upTan - fov.downTan) * pyscale * 0.5;
+		return { scale: [pxscale, pyscale], offset: [pxoffset, pyoffset] };
+	};
+
+	this.FovPortToProjection = function( fov, rightHanded /* = true */, zNear /* = 0.01 */, zFar /* = 10000.0 */ )
+	{
+		rightHanded = rightHanded === undefined ? true : rightHanded;
+		zNear = zNear === undefined ? 0.01 : zNear;
+		zFar = zFar === undefined ? 10000.0 : zFar;
+
+		var handednessScale = rightHanded ? -1.0 : 1.0;
+
+		// start with an identity matrix
+		var mobj = new THREE.Matrix4();
+		var m = mobj.elements;
+
+		// and with scale/offset info for normalized device coords
+		var scaleAndOffset = this.FovToNDCScaleOffset(fov);
+
+		// X result, map clip edges to [-w,+w]
+		m[0*4+0] = scaleAndOffset.scale[0];
+		m[0*4+1] = 0.0;
+		m[0*4+2] = scaleAndOffset.offset[0] * handednessScale;
+		m[0*4+3] = 0.0;
+
+		// Y result, map clip edges to [-w,+w]
+		// Y offset is negated because this proj matrix transforms from world coords with Y=up,
+		// but the NDC scaling has Y=down (thanks D3D?)
+		m[1*4+0] = 0.0;
+		m[1*4+1] = scaleAndOffset.scale[1];
+		m[1*4+2] = -scaleAndOffset.offset[1] * handednessScale;
+		m[1*4+3] = 0.0;
+
+		// Z result (up to the app)
+		m[2*4+0] = 0.0;
+		m[2*4+1] = 0.0;
+		m[2*4+2] = zFar / (zNear - zFar) * -handednessScale;
+		m[2*4+3] = (zFar * zNear) / (zNear - zFar);
+
+		// W result (= Z in)
+		m[3*4+0] = 0.0;
+		m[3*4+1] = 0.0;
+		m[3*4+2] = handednessScale;
+		m[3*4+3] = 0.0;
+
+		mobj.transpose();
+
+		return mobj;
+	};
+
+	this.FovToProjection = function( fov, rightHanded /* = true */, zNear /* = 0.01 */, zFar /* = 10000.0 */ )
+	{
+		var fovPort = {
+			upTan: Math.tan(fov.upDegrees * Math.PI / 180.0),
+			downTan: Math.tan(fov.downDegrees * Math.PI / 180.0),
+			leftTan: Math.tan(fov.leftDegrees * Math.PI / 180.0),
+			rightTan: Math.tan(fov.rightDegrees * Math.PI / 180.0)
+		};
+		return this.FovPortToProjection(fovPort, rightHanded, zNear, zFar);
+	};
+
+};

+ 1 - 1
examples/js/libs/dat.gui.min.js

@@ -87,7 +87,7 @@ b,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="RGB")ret
 "HEX")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space==="HSV")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw"Corrupted color state";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw"Failed to interpret color arguments";this.__state.a=this.__state.a||
 1};j.COMPONENTS="r,g,b,h,s,v,hex,a".split(",");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,"r",2);f(j.prototype,"g",1);f(j.prototype,"b",0);b(j.prototype,"h");b(j.prototype,"s");b(j.prototype,"v");Object.defineProperty(j.prototype,"a",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,"hex",{get:function(){if(!this.__state.space!=="HEX")this.__state.hex=
 a.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space="HEX";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0};
-a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255<<e)}}}(),dat.color.toString,dat.utils.common),dat.color.interpret,dat.utils.common),dat.utils.requestAnimationFrame=function(){return window.webkitRequestAnimationFrame||
+a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255<<e)}}}(),dat.color.toString,dat.utils.common),dat.color.interpret,dat.utils.common),dat.utils.requestAnimationFrame=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||
 window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(e,1E3/60)}}(),dat.dom.CenteredDiv=function(e,a){var c=function(){this.backgroundElement=document.createElement("div");a.extend(this.backgroundElement.style,{backgroundColor:"rgba(0,0,0,0.8)",top:0,left:0,display:"none",zIndex:"1000",opacity:0,WebkitTransition:"opacity 0.2s linear"});e.makeFullscreen(this.backgroundElement);this.backgroundElement.style.position="fixed";this.domElement=
 document.createElement("div");a.extend(this.domElement.style,{position:"fixed",display:"none",zIndex:"1001",opacity:0,WebkitTransition:"-webkit-transform 0.2s ease-out, opacity 0.2s linear"});document.body.appendChild(this.backgroundElement);document.body.appendChild(this.domElement);var c=this;e.bind(this.backgroundElement,"click",function(){c.hide()})};c.prototype.show=function(){var c=this;this.backgroundElement.style.display="block";this.domElement.style.display="block";this.domElement.style.opacity=
 0;this.domElement.style.webkitTransform="scale(1.1)";this.layout();a.defer(function(){c.backgroundElement.style.opacity=1;c.domElement.style.opacity=1;c.domElement.style.webkitTransform="scale(1)"})};c.prototype.hide=function(){var a=this,c=function(){a.domElement.style.display="none";a.backgroundElement.style.display="none";e.unbind(a.domElement,"webkitTransitionEnd",c);e.unbind(a.domElement,"transitionend",c);e.unbind(a.domElement,"oTransitionEnd",c)};e.bind(this.domElement,"webkitTransitionEnd",

+ 32 - 0
examples/js/libs/pnltri.min.js

@@ -0,0 +1,32 @@
+// pnltri.js / raw.github.com/jahting/pnltri.js/master/LICENSE
+'use strict';var PNLTRI={REVISION:"1.0"};PNLTRI.Math={log2:function(a){return Math.log(a)/Math.LN2},random:Math.random,array_shuffle:function(a){for(var c=a.length-1;0<c;c--){var b=Math.floor(PNLTRI.Math.random()*(c+1)),d=a[c];a[c]=a[b];a[b]=d}return a},ptsCrossProd:function(a,c,b){return(c.x-a.x)*(b.y-a.y)-(c.y-a.y)*(b.x-a.x)}};PNLTRI.Math.EPSILON_P=Math.pow(2,-43);PNLTRI.Math.EPSILON_N=-PNLTRI.Math.EPSILON_P;PNLTRI.PolygonData=function(a){this.vertices=[];this.segments=[];this.idNextPolyChain=0;this.monoSubPolyChains=[];this.triangles=[];if(a)for(var c=0,b=a.length;c<b;c++)this.addPolygonChain(a[c])};
+PNLTRI.PolygonData.prototype={constructor:PNLTRI.PolygonData,getSegments:function(){return this.segments},getFirstSegment:function(){return this.segments[0]},getMonoSubPolys:function(){return this.monoSubPolyChains},getTriangles:function(){return this.triangles.concat()},nbPolyChains:function(){return this.idNextPolyChain},compare_pts_yx:function(a,c){var b=a.y-c.y;if(b>PNLTRI.Math.EPSILON_P)return 1;if(b<PNLTRI.Math.EPSILON_N)return-1;b=a.x-c.x;return b>PNLTRI.Math.EPSILON_P?1:b<PNLTRI.Math.EPSILON_N?
+-1:0},isClockWise:function(a){var c=a,b=0;do b+=(c.vFrom.x-c.vTo.x)*(c.vFrom.y+c.vTo.y),c=c.snext;while(c!=a);return 0>b},appendVertexEntry:function(a){a=a?a:{x:null,y:null,outSegs:[]};a.id=this.vertices.length;this.vertices.push(a);return a},createSegmentEntry:function(a,c){return{chainId:this.idNextPolyChain,vFrom:a,vTo:c,upward:1==this.compare_pts_yx(c,a),sprev:null,snext:null}},appendSegmentEntry:function(a){this.segments.push(a);0==this.monoSubPolyChains.length&&(this.monoSubPolyChains=[this.segments[0]]);
+return a},addVertexChain:function(a){function c(a,b){return Math.abs(a.x-b.x)<PNLTRI.Math.EPSILON_P&&Math.abs(a.y-b.y)<PNLTRI.Math.EPSILON_P}for(var b=[],d,e,g,h=0;h<a.length;h++)d=this.appendVertexEntry({x:a[h].x,y:a[h].y}),e=!0,g=b.length-1,0<=g&&c(d,b[g])&&(e=!1),e&&b.push(d);1<b.length&&c(b[b.length-1],b[0])&&b.pop();return b},addPolygonChain:function(a){a=this.addVertexChain(a);if(3>a.length)return console.log("Polygon has < 3 vertices!",a),0;for(var c=this.segments.length,b,d,e,g=0;g<a.length-
+1;g++)b=this.createSegmentEntry(a[g],a[g+1]),e?(b.sprev=e,e.snext=b):d=b,e=b,this.appendSegmentEntry(b);b=this.createSegmentEntry(a[a.length-1],a[0]);b.sprev=e;e.snext=b;this.appendSegmentEntry(b);d.sprev=b;b.snext=d;this.idNextPolyChain++;return this.segments.length-c},initMonoChains:function(){for(var a=0;a<this.segments.length;a++)this.segments[a].marked=!1,this.segments[a].mprev=this.segments[a].sprev,this.segments[a].mnext=this.segments[a].snext,this.segments[a].vFrom.outSegs=[{segOut:this.segments[a],
+vertTo:this.segments[a].vTo}]},appendVertexOutsegEntry:function(a,c){var b=c?c:{segOut:null,vertTo:null};a.outSegs.push(b);return b},splitPolygonChain:function(a,c,b){function d(a,b){for(var c,d,f=null,e=4,h=0;h<a.outSegs.length;h++){c=a.outSegs[h];var g=c.vertTo;d=g.x-a.x;var g=g.y-a.y,k=b.x-a.x,t=b.y-a.y,v=(d*k+g*t)/Math.sqrt(d*d+g*g)/Math.sqrt(k*k+t*t);(d=0<=d*t-k*g?1-v:3+v)<e&&(e=d,f=c)}return f}var e=d(c,b),g=d(b,c),e=e.segOut,g=g.segOut,h=1==this.compare_pts_yx(c,b),k=this.appendSegmentEntry({vFrom:c,
+vTo:b,upward:!h,mprev:e.mprev,mnext:g}),h=this.appendSegmentEntry({vFrom:b,vTo:c,upward:h,mprev:g.mprev,mnext:e});e.mprev.mnext=k;g.mprev.mnext=h;e.mprev=h;g.mprev=k;this.appendVertexOutsegEntry(c,{segOut:k,vertTo:b});this.appendVertexOutsegEntry(b,{segOut:h,vertTo:c});this.monoSubPolyChains[a]=g;this.monoSubPolyChains.push(e);return this.monoSubPolyChains.length-1},unique_monotone_chains_max:function(){var a,c,b,d,e,g;for(g=0;g<this.segments.length;g++)this.segments[g].marked=!1;var h=[];for(g=0;g<
+this.monoSubPolyChains.length;g++){a=c=this.monoSubPolyChains[g];d=e=a.vFrom;a.marked=!0;a=a.mnext;for(var k=!1;(b=a.vFrom)!=d;){if(a.marked){k=!0;break}else a.marked=!0;1==this.compare_pts_yx(b,e)&&(e=b,c=a);a=a.mnext}k||h.push(c)}return h},normalize_monotone_chains:function(){this.monoSubPolyChains=this.unique_monotone_chains_max();return this.monoSubPolyChains.length},clearTriangles:function(){this.triangles=[]},addTriangle:function(a,c,b){this.triangles.push([a.id,c.id,b.id])}};PNLTRI.EarClipTriangulator=function(a){this.polyData=a};
+PNLTRI.EarClipTriangulator.prototype={constructor:PNLTRI.EarClipTriangulator,triangulate_polygon_no_holes:function(){var a=this.polyData,c=a.getFirstSegment(),b=c;if(a.isClockWise(c)){do b.mprev=b.snext,b=b.mnext=b.sprev;while(b!=c)}else{do b.mprev=b.sprev,b=b.mnext=b.snext;while(b!=c)}for(c=a=c;a.mnext!=a.mprev;){a:{var b=a.mprev.vFrom.x,d=a.mprev.vFrom.y,e=a.vFrom.x,g=a.vFrom.y,h=a.mnext.vFrom.x,k=a.mnext.vFrom.y,n=h-e,p=k-g,q=b-h,u=d-k,f=e-b,m=g-d;if(PNLTRI.Math.EPSILON_P>f*p-n*m)b=!1;else{for(var l=
+a.mprev.mprev,s=a.mnext;s!=l;){var s=s.mnext,r=s.vFrom.x,t=s.vFrom.y,v=r-b,w=t-d;if(0!=v||0!=w){var x=r-e,y=t-g;if(0!=x||0!=y)if(r-=h,t-=k,(0!=r||0!=t)&&n*y-p*x>=PNLTRI.Math.EPSILON_N&&f*w-m*v>=PNLTRI.Math.EPSILON_N&&q*t-u*r>=PNLTRI.Math.EPSILON_N){b=!1;break a}}}b=!0}}if(b)this.polyData.addTriangle(a.mprev.vFrom,a.vFrom,a.mnext.vFrom),a.mprev.mnext=a.mnext,a.mnext.mprev=a.mprev,c=a=a.mnext;else if(a=a.mnext,a==c)return!1}return!0}};PNLTRI.trapCnt=0;PNLTRI.Trapezoid=function(a,c,b,d){this.trapID=PNLTRI.trapCnt++;this.vHigh=a?a:{x:Number.POSITIVE_INFINITY,y:Number.POSITIVE_INFINITY};this.vLow=c?c:{x:Number.NEGATIVE_INFINITY,y:Number.NEGATIVE_INFINITY};this.lseg=b;this.rseg=d;this.depth=-1;this.monoDiag=null};
+PNLTRI.Trapezoid.prototype={constructor:PNLTRI.Trapezoid,clone:function(){var a=new PNLTRI.Trapezoid(this.vHigh,this.vLow,this.lseg,this.rseg);a.uL=this.uL;a.uR=this.uR;a.dL=this.dL;a.dR=this.dR;a.sink=this.sink;return a},setAbove:function(a,c){this.uL=a;this.uR=c},setBelow:function(a,c){this.dL=a;this.dR=c},splitOffLower:function(a){var c=this.clone();this.vLow=c.vHigh=a;this.setBelow(c,null);c.setAbove(this,null);c.dL&&(c.dL.uL=c);c.dR&&(c.dR.uR=c);return c}};PNLTRI.T_Y=1;PNLTRI.T_X=2;
+PNLTRI.T_SINK=3;PNLTRI.S_LEFT=1;PNLTRI.S_RIGHT=2;PNLTRI.QsNode=function(a){this.nodetype=PNLTRI.T_SINK;this.trap=a;a.sink=this};PNLTRI.QsNode.prototype={constructor:PNLTRI.QsNode};
+PNLTRI.QueryStructure=function(a){PNLTRI.trapCnt=0;var c=new PNLTRI.Trapezoid(null,null,null,null);this.root=new PNLTRI.QsNode(c);this.trapArray=[c];this.segListArray=null;if(a){this.segListArray=a.getSegments();for(c=0;c<this.segListArray.length;c++)this.segListArray[c].rootFrom=this.segListArray[c].rootTo=this.root,this.segListArray[c].is_inserted=!1;this.compare_pts_yx=a.compare_pts_yx}else this.compare_pts_yx=PNLTRI.PolygonData.prototype.compare_pts_yx};
+PNLTRI.QueryStructure.prototype={constructor:PNLTRI.QueryStructure,getRoot:function(){return this.root},getSegListArray:function(){return this.segListArray},cloneTrap:function(a){a=a.clone();this.trapArray.push(a);return a},splitNodeAtPoint:function(a,c,b){var d=a.trap;if(d.vHigh==c||d.vLow==c)return a;var e=d.splitOffLower(c);this.trapArray.push(e);a.nodetype=PNLTRI.T_Y;a.yval=c;a.trap=null;a.right=new PNLTRI.QsNode(d);a.left=new PNLTRI.QsNode(e);return b?d.sink:e.sink},fpEqual:function(a,c){return Math.abs(a-
+c)<PNLTRI.Math.EPSILON_P},is_left_of:function(a,c,b){b=a.vFrom.x-c.x;var d=a.vTo.x-c.x;if(Math.abs(a.vTo.y-c.y)<PNLTRI.Math.EPSILON_P)a=d,c=b;else if(Math.abs(a.vFrom.y-c.y)<PNLTRI.Math.EPSILON_P)a=b,c=d;else return a.upward?PNLTRI.Math.ptsCrossProd(a.vFrom,a.vTo,c):PNLTRI.Math.ptsCrossProd(a.vTo,a.vFrom,c);return Math.abs(a)<PNLTRI.Math.EPSILON_P?Math.abs(c)<PNLTRI.Math.EPSILON_P?0:c:a},ptNode:function(a,c,b){var d,e=!0;switch(b.nodetype){case PNLTRI.T_SINK:return b;case PNLTRI.T_Y:d=a;d==b.yval&&
+(d=c);d=this.compare_pts_yx(d,b.yval);-1==d&&(e=!1);break;case PNLTRI.T_X:if(a==b.seg.vFrom||a==b.seg.vTo){if(this.fpEqual(a.y,c.y)){c.x<a.x&&(e=!1);break}else d=this.is_left_of(b.seg,c,!1),0<d?e=!1:0==d&&(e=a==b.seg.vFrom?!0:!1);break}else d=this.is_left_of(b.seg,a,!0),0<d?e=!1:0==d&&(e=!0);break;default:console.log("ptNode: undef. NodeType: ",b.nodetype)}return e?this.ptNode(a,c,b.right):this.ptNode(a,c,b.left)},add_segment:function(a){function c(){var a=f.uL||f.uR;a.dL&&a.dR?f==a.dR?(m.setAbove(null,
+null),l.setAbove(null,a),a.setBelow(a.dL,l)):(l.setAbove(null,null),m.setAbove(a,null),a.setBelow(m,a.dR)):(m.setAbove(a,null),l.setAbove(null,a),a.setBelow(m,l))}function b(a){f.vLow==u.vLow&&q?f.dL?(m.setBelow(a,null),l.setBelow(null,null),a.setAbove(m,a.uR)):(l.setBelow(null,a),m.setBelow(null,null),a.setAbove(a.uL,l)):(a.uL&&a.uR?a.uL==f?(a.usave=a.uR,a.uside=PNLTRI.S_LEFT,m.setBelow(a,null),l.setBelow(a,null)):(a.usave=a.uL,a.uside=PNLTRI.S_RIGHT,m.setBelow(null,a),l.setBelow(null,a)):f.vLow==
+u.vLow?(m.setBelow(a,null),l.setBelow(null,a)):(m.setBelow(null,a),l.setBelow(a,null)),a.setAbove(m,l))}function d(){var b;f.vLow==u.vLow&&q?(f.dL.setAbove(m,null),f.dR.setAbove(null,l),b=f.dR,m.setBelow(f.dL,null),l.setBelow(null,b),b=null):0<e.is_left_of(a,f.vLow,!0)?(b=f.dR,f.dL.setAbove(m,null),f.dR.setAbove(m,l),m.setBelow(f.dL,f.dR),l.setBelow(null,f.dR)):(b=f.dL,f.dL.setAbove(m,l),f.dR.setAbove(null,l),l.setBelow(f.dL,f.dR),m.setBelow(f.dL,null));return b}var e=this,g,h,k,n,p,q;a.upward?(n=
+a.vFrom,g=a.vTo,p=a.rootFrom,h=a.rootTo,q=a.sprev.is_inserted,k=a.snext.is_inserted):(n=a.vTo,g=a.vFrom,p=a.rootTo,h=a.rootFrom,q=a.snext.is_inserted,k=a.sprev.is_inserted);h=this.ptNode(g,n,h);k||(h=this.splitNodeAtPoint(h,g,!1));k=h.trap;if(k.uL||k.uR){h=this.ptNode(n,g,p);q||(h=this.splitNodeAtPoint(h,n,!0));var u=h.trap,f=k,m,l,s,r;for(g=this.trapArray.length+2;f;){if(0>--g){console.log("ERR add_segment: infinite loop",f,a,this);return}if(!f.dL&&!f.dR){console.log("ERR add_segment: missing successors",
+f,a,this);return}h=f.sink;h.nodetype=PNLTRI.T_X;h.seg=a;h.trap=null;n=p=!0;r&&r.rseg==f.rseg?(p=!1,m=f,l=r,l.vLow=f.vLow,h.right=r.sink,h.left=new PNLTRI.QsNode(m)):s&&s.lseg==f.lseg?(n=!1,l=f,m=s,m.vLow=f.vLow,h.left=s.sink,h.right=new PNLTRI.QsNode(l)):(m=f,l=this.cloneTrap(f),h.right=new PNLTRI.QsNode(l),h.left=new PNLTRI.QsNode(m));f.uL&&f.uR?f.usave?(f.uside==PNLTRI.S_LEFT?(l.setAbove(f.uR,f.usave),l.uL.setBelow(l,null),l.uR.setBelow(null,l)):(m.setAbove(f.usave,f.uL),m.uL.setBelow(m,null),m.uR.setBelow(null,
+m)),m.usave=l.usave=null):f.vHigh==k.vHigh?(l.setAbove(null,f.uR),l.uR.setBelow(null,l),m.setAbove(f.uL,null)):(p&&(l.setAbove(f.uR,null),l.uL.setBelow(l,l.uL.dR)),n&&m.setAbove(null,f.uL)):c();f.dL&&f.dR?n=d():(n=f.dL?f.dL:f.dR,b(n));m.rseg&&(m.rseg.trLeft=l);l.lseg&&(l.lseg.trRight=m);m.rseg=l.lseg=a;a.trLeft=m;a.trRight=l;f.vLow!=u.vLow?(s=m,r=l,f=n):f=null}a.is_inserted=!0}else console.log("ERR add_segment: missing trFirst.uX: ",k)},assignDepths:function(){var a=[this.trapArray[0]],c=[],b,d,e=
+0;do{for(;b=a.pop();)-1==b.depth&&(b.depth=e,b.uL&&a.push(b.uL),b.uR&&a.push(b.uR),b.dL&&a.push(b.dL),b.dR&&a.push(b.dR),(d=b.lseg)&&-1==d.trLeft.depth&&c.push(d.trLeft),(d=b.rseg)&&-1==d.trRight.depth&&c.push(d.trRight));a=c;c=[];e++}while(0<a.length)},reverse_polygon_chain:function(a){var c,b=a;do c=b.snext,b.snext=b.sprev,b.sprev=c,c=b.vTo,b.vTo=b.vFrom,b.vFrom=c,b.upward=!b.upward,b=b.sprev;while(b!=a)},normalize_segment_orientation:function(){for(var a,c=0;c<this.segListArray.length;c++)a=this.segListArray[c],
+a.upward==(0==a.trLeft.depth%2)&&this.reverse_polygon_chain(a)},find_first_inside:function(){for(var a,c=0,b=this.trapArray.length;c<b;c++)if(a=this.trapArray[c],1==a.depth%2&&!a.monoDiag&&(!a.uL&&!a.uR||!a.dL&&!a.dR))return a;return null}};PNLTRI.Trapezoider=function(a){this.polyData=a;this.queryStructure=new PNLTRI.QueryStructure(this.polyData)};
+PNLTRI.Trapezoider.prototype={constructor:PNLTRI.Trapezoider,find_first_inside:function(){return this.queryStructure.find_first_inside()},math_logstar_n:function(a){var c;for(c=0;1<=a;c++)a=PNLTRI.Math.log2(a);return c-1},math_NH:function(a,c){var b,d;b=0;for(d=a;b<c;b++)d=PNLTRI.Math.log2(d);return Math.ceil(1*a/d)},optimise_randomlist:function(a){var c=0,b=this.polyData.nbPolyChains();if(1!=b)for(var d=Array(b),e=a.concat(),g=0;g<e.length;g++){var h=e[g].chainId;d[h]?a[b++]=e[g]:(a[c++]=e[g],d[h]=
+!0)}},find_new_roots:function(a){a.is_inserted||(a.rootFrom=this.queryStructure.ptNode(a.vFrom,a.vTo,a.rootFrom),a.rootTo=this.queryStructure.ptNode(a.vTo,a.vFrom,a.rootTo))},trapezoide_polygon:function(){var a=this.queryStructure,c=a.segListArray.concat();PNLTRI.Math.array_shuffle(c);this.optimise_randomlist(c);var b,d,e=c.length,g=this.math_logstar_n(e);for(d=1;d<=g;d++){for(b=this.math_NH(e,d-1);b<this.math_NH(e,d);b++)a.add_segment(c[b-1]);for(b=0;b<e;b++)this.find_new_roots(c[b])}for(b=this.math_NH(e,
+g);b<=e;b++)a.add_segment(c[b-1]);a.assignDepths();a.normalize_segment_orientation()}};PNLTRI.MonoSplitter=function(a){this.polyData=a;this.startTrap=this.trapezoider=null};
+PNLTRI.MonoSplitter.prototype={constructor:PNLTRI.MonoSplitter,monotonate_trapezoids:function(){this.trapezoider=new PNLTRI.Trapezoider(this.polyData);this.trapezoider.trapezoide_polygon();this.startTrap=this.trapezoider.find_first_inside();this.polyData.initMonoChains();for(var a=0,c=this.startTrap;c;)if(this.polyData.monoSubPolyChains[a]=c.lseg,this.alyTrap(a,c,null,null,null),c=this.trapezoider.find_first_inside())a=this.polyData.monoSubPolyChains.length;return this.polyData.normalize_monotone_chains()},
+doSplit:function(a,c,b,d){return d?this.polyData.splitPolygonChain(a,c,b):this.polyData.splitPolygonChain(a,b,c)},alyTrap:function(a,c,b,d,e){function g(){var a;return(a=h.pop())?(k=a[0],n=a[1],p=a[2],q=a[3],!0):!1}var h=[],k,n,p,q,u;null==b&&(d=!0,c.uL?b=!0:c.dL?b=!1:(d=!1,b=c.uR?!0:!1));for(c&&h.push([c,b,d,a]);g();)if(!k.monoDiag){if(!k.lseg||!k.rseg)return console.log("ERR alyTrap: lseg/rseg missing",k),h;n?p?(a=k.uL,c=k.uR,b=k.dL,d=k.dR):(a=k.uR,c=k.uL,b=k.dR,d=k.dL):p?(a=k.dL,c=k.dR,b=k.uL,
+d=k.uR):(a=k.dR,c=k.dL,b=k.uR,d=k.uL);if(c||d)u=this.doSplit(q,k.vLow,k.vHigh,p);d&&h.push([d,n,!p,u]);c&&h.push([c,!n,!p,u]);b&&h.push([b,n,p,q]);b||d||a&&h.push([a,!n,p,q]);k.monoDiag=!0;if(e)return h}return[]}};PNLTRI.MonoTriangulator=function(a){this.polyData=a};
+PNLTRI.MonoTriangulator.prototype={constructor:PNLTRI.MonoTriangulator,triangulate_all_polygons:function(){var a=this.polyData.getMonoSubPolys();this.polyData.clearTriangles();for(var c=0;c<a.length;c++){var b=a[c],d=b.mprev,e=b.mnext;e.mnext==d?this.polyData.addTriangle(b.vFrom,e.vFrom,d.vFrom):this.triangulate_monotone_polygon(b)}},triangulate_monotone_polygon:function(a){var c=a.mnext;a=a.vFrom;var b=[c.vFrom],d=0,c=c.mnext,e=c.vFrom;if(e!=a){for(;e!=a||1<d;)if(0<d)if(0<PNLTRI.Math.ptsCrossProd(e,
+b[d-1],b[d]))this.polyData.addTriangle(b[d-1],b[d],e),d--;else if(b[++d]=e,e==a)for(console.log("ERR uni-y-monotone: only concave angles left",b);1<d;)d--,this.polyData.addTriangle(b[d-1],b[d],b[d+1]);else c=c.mnext,e=c.vFrom;else b[++d]=e,c=c.mnext,e=c.vFrom;this.polyData.addTriangle(b[d-1],b[d],e)}}};PNLTRI.Triangulator=function(){this.lastPolyData=null};PNLTRI.Triangulator.prototype={constructor:PNLTRI.Triangulator,triangulate_polygon:function(a,c){if(!a||0==a.length)return[];var b=new PNLTRI.PolygonData(a),d;d=c?!1:1==b.nbPolyChains();d&&(d=new PNLTRI.EarClipTriangulator(b),d=d.triangulate_polygon_no_holes());d||((new PNLTRI.MonoSplitter(b)).monotonate_trapezoids(),d=new PNLTRI.MonoTriangulator(b),d.triangulate_all_polygons());this.lastPolyData=b;return b.getTriangles()}};

+ 18 - 67
examples/js/loaders/ColladaLoader.js

@@ -644,9 +644,6 @@ THREE.ColladaLoader = function () {
 
 	function applySkin ( geometry, instanceCtrl, frame ) {
 
-		// TODO: get this from the renderer or options
-		var maxbones = 64;
-
 		var skinController = controllers[ instanceCtrl.url ];
 
 		frame = frame !== undefined ? frame : 40;
@@ -746,12 +743,10 @@ THREE.ColladaLoader = function () {
 
 		console.log( 'ColladaLoader:', animationBounds.ID + ' has ' + sortedbones.length + ' bones.' );
 
-		//if using hardware skinning, move the vertices into the binding pose
-		if(sortedbones.length < maxbones) {
 
-			skinToBindPose(geometry,skeleton,skinController);
 
-		}
+		skinToBindPose(geometry,skeleton,skinController);
+
 
 		for ( frame = 0; frame < animationBounds.frames; frame ++ ) {
 
@@ -763,81 +758,37 @@ THREE.ColladaLoader = function () {
 			setupSkeleton( skeleton, bones, frame );
 			setupSkinningMatrices( bones, skinController.skin );
 
-			//if using hardware skinning, just hook up the animiation data
-			if(sortedbones.length < maxbones) {
-
-				for(var i = 0; i < bones.length; i ++) {
-
-					for(var j = 0; j < animationdata.hierarchy.length; j ++) {
-
-						if(animationdata.hierarchy[j].name == bones[i].sid) {
-
-							var key = {};
-							key.time = (frame/30);
-							key.matrix = bones[i].animatrix;
-
-							if(frame == 0)
-								bones[i].matrix = key.matrix;
-
-							var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
-							key.matrix.decompose(data[0],data[1],data[2]);
-
-							key.pos = [data[0].x,data[0].y,data[0].z];
-
-							key.scl = [data[2].x,data[2].y,data[2].z];
-							key.rot = data[1];
-
-							animationdata.hierarchy[j].keys.push(key);
-
-						}
-
-					}
-
-				}
-
-				geometry.animation = animationdata;
-
-			} else {
-
-				// otherwise, process the animation into morphtargets
-
-				for ( i = 0; i < geometry.vertices.length; i++ ) {
+			for(var i = 0; i < bones.length; i ++) {
 
-					skinned.push( new THREE.Vector3() );
-
-				}
+				for(var j = 0; j < animationdata.hierarchy.length; j ++) {
 
-				for ( i = 0; i < bones.length; i ++ ) {
+					if(animationdata.hierarchy[j].name == bones[i].sid) {
 
-					if ( bones[ i ].type != 'JOINT' ) continue;
+						var key = {};
+						key.time = (frame/30);
+						key.matrix = bones[i].animatrix;
 
-					for ( j = 0; j < bones[ i ].weights.length; j ++ ) {
+						if(frame == 0)
+							bones[i].matrix = key.matrix;
 
-						w = bones[ i ].weights[ j ];
-						vidx = w.index;
-						weight = w.weight;
+						var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
+						key.matrix.decompose(data[0],data[1],data[2]);
 
-						o = geometry.vertices[vidx];
-						s = skinned[vidx];
+						key.pos = [data[0].x,data[0].y,data[0].z];
 
-						v.x = o.x;
-						v.y = o.y;
-						v.z = o.z;
+						key.scl = [data[2].x,data[2].y,data[2].z];
+						key.rot = data[1];
 
-						v.applyMatrix4( bones[i].skinningMatrix );
-
-						s.x += (v.x * weight);
-						s.y += (v.y * weight);
-						s.z += (v.z * weight);
+						animationdata.hierarchy[j].keys.push(key);
 
 					}
 
 				}
 
-				geometry.morphTargets.push( { name: "target_" + frame, vertices: skinned } );
-
 			}
 
+			geometry.animation = animationdata;
+
 		}
 
 	};

+ 4 - 2
examples/js/loaders/OBJLoader.js

@@ -190,7 +190,9 @@ THREE.OBJLoader.prototype = {
 
 		var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/
 
-		//
+		// fixes
+
+		text = text.replace( /\\\r\n/g, '' ); // handles line continuations \
 
 		var lines = text.split( '\n' );
 
@@ -324,4 +326,4 @@ THREE.OBJLoader.prototype = {
 
 	}
 
-};
+};

+ 0 - 2
examples/js/loaders/OBJMTLLoader.js

@@ -94,7 +94,6 @@ THREE.OBJMTLLoader.prototype = {
 
 				geometry = new THREE.Geometry();
 				mesh = new THREE.Mesh( geometry, material );
-				verticesCount = 0;
 
 			}
 
@@ -119,7 +118,6 @@ THREE.OBJMTLLoader.prototype = {
 		var mesh = new THREE.Mesh( geometry, material );
 
 		var vertices = [];
-		var verticesCount = 0;
 		var normals = [];
 		var uvs = [];
 

+ 114 - 0
examples/js/postprocessing/GlitchPass.js

@@ -0,0 +1,114 @@
+/**
+ 
+ */
+
+THREE.GlitchPass = function ( dt_size ) {
+
+	if ( THREE.DigitalGlitch === undefined ) console.error( "THREE.GlitchPass relies on THREE.DigitalGlitch" );
+	
+	var shader = THREE.DigitalGlitch;
+	this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+	if(dt_size==undefined) dt_size=64;
+	
+	
+	this.uniforms[ "tDisp"].value=this.generateHeightmap(dt_size);
+	
+
+	this.material = new THREE.ShaderMaterial({
+		uniforms: this.uniforms,
+		vertexShader: shader.vertexShader,
+		fragmentShader: shader.fragmentShader
+	});
+
+	console.log(this.material);
+	
+	this.enabled = true;
+	this.renderToScreen = false;
+	this.needsSwap = true;
+
+
+	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
+	this.scene  = new THREE.Scene();
+
+	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.scene.add( this.quad );
+	
+	this.goWild=false;
+	this.curF=0;
+	this.generateTrigger();
+	
+};
+
+THREE.GlitchPass.prototype = {
+
+	render: function ( renderer, writeBuffer, readBuffer, delta ) 
+	{
+		this.uniforms[ "tDiffuse" ].value = readBuffer;
+		this.uniforms[ 'seed' ].value=Math.random();//default seeding
+		this.uniforms[ 'byp' ].value=0;
+		
+		if(this.curF % this.randX ==0 || this.goWild==true)
+		{
+			this.uniforms[ 'amount' ].value=Math.random()/30;
+			this.uniforms[ 'angle' ].value=THREE.Math.randFloat(-Math.PI,Math.PI);
+			this.uniforms[ 'seed_x' ].value=THREE.Math.randFloat(-1,1);
+			this.uniforms[ 'seed_y' ].value=THREE.Math.randFloat(-1,1);
+			this.uniforms[ 'distortion_x' ].value=THREE.Math.randFloat(0,1);
+			this.uniforms[ 'distortion_y' ].value=THREE.Math.randFloat(0,1);
+			this.curF=0;
+			this.generateTrigger();
+		}
+		else if(this.curF % this.randX <this.randX/5)
+		{
+			this.uniforms[ 'amount' ].value=Math.random()/90;
+			this.uniforms[ 'angle' ].value=THREE.Math.randFloat(-Math.PI,Math.PI);
+			this.uniforms[ 'distortion_x' ].value=THREE.Math.randFloat(0,1);
+			this.uniforms[ 'distortion_y' ].value=THREE.Math.randFloat(0,1);
+			this.uniforms[ 'seed_x' ].value=THREE.Math.randFloat(-0.3,0.3);
+			this.uniforms[ 'seed_y' ].value=THREE.Math.randFloat(-0.3,0.3);
+		}
+		else if(this.goWild==false)
+		{
+			this.uniforms[ 'byp' ].value=1;
+		}
+		this.curF++;
+		
+		this.quad.material = this.material;
+		if ( this.renderToScreen ) 
+		{
+			renderer.render( this.scene, this.camera );
+		} 
+		else 
+		{
+			renderer.render( this.scene, this.camera, writeBuffer, false );
+		}
+	},
+	generateTrigger:function()
+	{
+		this.randX=THREE.Math.randInt(120,240);
+	},
+	generateHeightmap:function(dt_size)
+	{
+		var data_arr = new Float32Array( dt_size*dt_size * 3 );
+		console.log(dt_size);
+		var length=dt_size*dt_size;
+		
+		for ( var i = 0; i < length; i++) 
+		{
+			var val=THREE.Math.randFloat(0,1);
+			data_arr[ i*3 + 0 ] = val;
+			data_arr[ i*3 + 1 ] = val;
+			data_arr[ i*3 + 2 ] = val;
+		}
+		
+		var texture = new THREE.DataTexture( data_arr, dt_size, dt_size, THREE.RGBFormat, THREE.FloatType );
+		console.log(texture);
+		console.log(dt_size);
+		texture.minFilter = THREE.NearestFilter;
+		texture.magFilter = THREE.NearestFilter;
+		texture.needsUpdate = true;
+		texture.flipY = false;
+		return texture;
+	}
+};

+ 36 - 12
examples/js/renderers/CSS3DRenderer.js

@@ -42,6 +42,11 @@ THREE.CSS3DRenderer = function () {
 	var _widthHalf, _heightHalf;
 
 	var matrix = new THREE.Matrix4();
+	
+	var cache = {
+		camera: { fov: 0, style: '' },
+		objects: {}
+	};
 
 	var domElement = document.createElement( 'div' );
 	domElement.style.overflow = 'hidden';
@@ -167,11 +172,18 @@ THREE.CSS3DRenderer = function () {
 			}
 
 			var element = object.element;
+			var cachedStyle = cache.objects[ object.id ];
+
+			if ( cachedStyle === undefined || cachedStyle !== style ) {
+
+				element.style.WebkitTransform = style;
+				element.style.MozTransform = style;
+				element.style.oTransform = style;
+				element.style.transform = style;
 
-			element.style.WebkitTransform = style;
-			element.style.MozTransform = style;
-			element.style.oTransform = style;
-			element.style.transform = style;
+				cache.objects[ object.id ] = style;
+
+			}
 
 			if ( element.parentNode !== cameraElement ) {
 
@@ -193,10 +205,16 @@ THREE.CSS3DRenderer = function () {
 
 		var fov = 0.5 / Math.tan( THREE.Math.degToRad( camera.fov * 0.5 ) ) * _height;
 
-		domElement.style.WebkitPerspective = fov + "px";
-		domElement.style.MozPerspective = fov + "px";
-		domElement.style.oPerspective = fov + "px";
-		domElement.style.perspective = fov + "px";
+		if ( cache.camera.fov !== fov ) {
+
+			domElement.style.WebkitPerspective = fov + "px";
+			domElement.style.MozPerspective = fov + "px";
+			domElement.style.oPerspective = fov + "px";
+			domElement.style.perspective = fov + "px";
+
+			cache.camera.fov = fov;
+
+		}
 
 		scene.updateMatrixWorld();
 
@@ -207,10 +225,16 @@ THREE.CSS3DRenderer = function () {
 		var style = "translate3d(0,0," + fov + "px)" + getCameraCSSMatrix( camera.matrixWorldInverse ) +
 			" translate3d(" + _widthHalf + "px," + _heightHalf + "px, 0)";
 
-		cameraElement.style.WebkitTransform = style;
-		cameraElement.style.MozTransform = style;
-		cameraElement.style.oTransform = style;
-		cameraElement.style.transform = style;
+		if ( cache.camera.style !== style ) {
+
+			cameraElement.style.WebkitTransform = style;
+			cameraElement.style.MozTransform = style;
+			cameraElement.style.oTransform = style;
+			cameraElement.style.transform = style;
+			
+			cache.camera.style = style;
+
+		}
 
 		renderObject( scene, camera );
 

+ 4 - 2
examples/js/renderers/SVGRenderer.js

@@ -23,6 +23,7 @@ THREE.SVGRenderer = function () {
 	_directionalLights = new THREE.Color(),
 	_pointLights = new THREE.Color(),
 	_clearColor = new THREE.Color(),
+	_clearAlpha = 1,
 
 	_w, // z-buffer to w-buffer
 	_vector3 = new THREE.Vector3(), // Needed for PointLight
@@ -67,7 +68,8 @@ THREE.SVGRenderer = function () {
 
 	this.setClearColor = function ( color, alpha ) {
 
-		_clearColor.set(color);
+		_clearColor.set( color );
+		_clearAlpha = alpha !== undefined ? alpha : 1;
 
 	};
 
@@ -97,7 +99,7 @@ THREE.SVGRenderer = function () {
 
 		}
 		
-		_svg.style.backgroundColor = _clearColor.getStyle();
+		_svg.style.backgroundColor = 'rgba(' + ( ( _clearColor.r * 255 ) | 0 ) + ',' + ( ( _clearColor.g * 255 ) | 0 ) + ',' + ( ( _clearColor.b * 255 ) | 0 ) + ',' + _clearAlpha + ')';
 
 	};
 

+ 103 - 0
examples/js/shaders/DigitalGlitch.js

@@ -0,0 +1,103 @@
+/**
+ * @author felixturner / http://airtight.cc/
+ *
+ * RGB Shift Shader
+ * Shifts red and blue channels from center in opposite directions
+ * Ported from http://kriss.cx/tom/2009/05/rgb-shift/
+ * by Tom Butterworth / http://kriss.cx/tom/
+ *
+ * amount: shift distance (1 is width of input)
+ * angle: shift angle in radians
+ */
+
+THREE.DigitalGlitch = {
+
+	uniforms: {
+
+		"tDiffuse":		{ type: "t", value: null },//diffuse texture
+		"tDisp":		{ type: "t", value: null },//displacement texture for digital glitch squares
+		"byp":			{ type: "i", value: 0 },//apply the glitch ?
+		"amount":		{ type: "f", value: 0.08 },
+		"angle":		{ type: "f", value: 0.02 },
+		"seed":			{ type: "f", value: 0.02 },
+		"seed_x":		{ type: "f", value: 0.02 },//-1,1
+		"seed_y":		{ type: "f", value: 0.02 },//-1,1
+		"distortion_x":	{ type: "f", value: 0.5 },
+		"distortion_y":	{ type: "f", value: 0.6 },
+		"col_s":		{ type: "f", value: 0.05 }
+	},
+
+	vertexShader: [
+
+		"varying vec2 vUv;",
+		"void main() {",
+			"vUv = uv;",
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+		"}"
+	].join("\n"),
+
+	fragmentShader: [
+		"uniform int byp;",//should we apply the glitch ?
+		
+		"uniform sampler2D tDiffuse;",
+		"uniform sampler2D tDisp;",
+		
+		"uniform float amount;",
+		"uniform float angle;",
+		"uniform float seed;",
+		"uniform float seed_x;",
+		"uniform float seed_y;",
+		"uniform float distortion_x;",
+		"uniform float distortion_y;",
+		"uniform float col_s;",
+			
+		"varying vec2 vUv;",
+		
+		
+		"float rand(vec2 co){",
+			"return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);",
+		"}",
+				
+		"void main() {",
+			"if(byp<1) {",
+				"vec2 p = vUv;",
+				"float xs = floor(gl_FragCoord.x / 0.5);",
+				"float ys = floor(gl_FragCoord.y / 0.5);",
+				//based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch
+				"vec4 normal = texture2D (tDisp, p*seed*seed);",
+				"if(p.y<distortion_x+col_s && p.y>distortion_x-col_s*seed) {",
+					"if(seed_x>0.){",
+						"p.y = 1. - (p.y + distortion_y);",
+					"}",
+					"else {",
+						"p.y = distortion_y;",
+					"}",
+				"}",
+				"if(p.x<distortion_y+col_s && p.x>distortion_y-col_s*seed) {",
+					"if(seed_y>0.){",
+						"p.x=distortion_x;",
+					"}",
+					"else {",
+						"p.x = 1. - (p.x + distortion_x);",
+					"}",
+				"}",
+				"p.x+=normal.x*seed_x*(seed/5.);",
+				"p.y+=normal.y*seed_y*(seed/5.);",
+				//base from RGB shift shader
+				"vec2 offset = amount * vec2( cos(angle), sin(angle));",
+				"vec4 cr = texture2D(tDiffuse, p + offset);",
+				"vec4 cga = texture2D(tDiffuse, p);",
+				"vec4 cb = texture2D(tDiffuse, p - offset);",
+				"gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);",
+				//add noise
+				"vec4 snow = 200.*amount*vec4(rand(vec2(xs * seed,ys * seed*50.))*0.2);",
+				"gl_FragColor = gl_FragColor+ snow;",
+			"}",
+			"else {",
+				"gl_FragColor=texture2D (tDiffuse, vUv);",
+			"}",
+		"}"
+
+	].join("\n")
+
+};

+ 47 - 0
examples/js/shaders/TechnicolorShader.js

@@ -0,0 +1,47 @@
+/**
+ * @author flimshaw / http://charliehoey.com
+ *
+ * Technicolor Shader
+ * Simulates the look of the two-strip technicolor process popular in early 20th century films.
+ * More historical info here: http://www.widescreenmuseum.com/oldcolor/technicolor1.htm
+ * Demo here: http://charliehoey.com/technicolor_shader/shader_test.html
+ */
+
+THREE.TechnicolorShader = {
+
+	uniforms: {
+
+		"tDiffuse": { type: "t", value: null },
+
+	},
+
+	vertexShader: [
+
+		"varying vec2 vUv;",
+
+		"void main() {",
+
+			"vUv = uv;",
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+		"}"
+
+	].join("\n"),
+
+	fragmentShader: [
+
+		"uniform sampler2D tDiffuse;",
+		"varying vec2 vUv;",
+
+		"void main() {",
+
+			"vec4 tex = texture2D( tDiffuse, vec2( vUv.x, vUv.y ) );",
+			"vec4 newTex = vec4(tex.r, (tex.g + tex.b) * .5, (tex.g + tex.b) * .5, 1.0);",
+
+			"gl_FragColor = newTex;",
+
+		"}"
+
+	].join("\n")
+
+};

+ 1 - 1
examples/webgl_buffergeometry_lines.html

@@ -67,7 +67,7 @@
 				var segments = 10000;
 
 				var geometry = new THREE.BufferGeometry();
-				var material = new THREE.LineBasicMaterial({ vertexColors: true });
+				var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
 
 				var positions = new Float32Array( segments * 3 );
 				var colors = new Float32Array( segments * 3 );

+ 1 - 1
examples/webgl_buffergeometry_lines_indexed.html

@@ -62,7 +62,7 @@
 				scene = new THREE.Scene();
 
 				var geometry = new THREE.BufferGeometry();
-				var material = new THREE.LineBasicMaterial({ vertexColors: true });
+				var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors });
 
 				var positions = [];
 				var next_positions_index = 0;

+ 1 - 1
examples/webgl_buffergeometry_particles.html

@@ -109,7 +109,7 @@
 
 				//
 
-				var material = new THREE.PointCloudMaterial( { size: 15, vertexColors: true } );
+				var material = new THREE.PointCloudMaterial( { size: 15, vertexColors: THREE.VertexColors } );
 
 				particleSystem = new THREE.PointCloud( geometry, material );
 				scene.add( particleSystem );

+ 0 - 2
examples/webgl_camera.html

@@ -37,8 +37,6 @@
 		</style>
 	</head>
 	<body>
-
-		<div id="container"></div>
 		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - cameras<br/>
 		<b>O</b> orthographic <b>P</b> perspective
 		</div>

+ 6 - 26
examples/webgl_effects_crosseyed.html → examples/webgl_effects_stereo.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgl - effects - crosseyed</title>
+		<title>three.js webgl - effects - stereo</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
@@ -34,13 +34,12 @@
 
 	<body>
 		<div id="info">
-			<a href="http://threejs.org" target="_blank">three.js</a> - effects - crosseyed. skybox by <a href="http://www.zfight.com/" target="_blank">Jochum Skoglund</a>
-			- O, P : change eye separation
+			<a href="http://threejs.org" target="_blank">three.js</a> - effects - stereo. skybox by <a href="http://www.zfight.com/" target="_blank">Jochum Skoglund</a>
 		</div>
 
 		<script src="../build/three.min.js"></script>
 
-		<script src="js/effects/CrosseyedEffect.js"></script>
+		<script src="js/effects/StereoEffect.js"></script>
 
 		<script src="js/Detector.js"></script>
 
@@ -75,8 +74,6 @@
 				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 100000 );
 				camera.position.z = 3200;
 
-				camera.target = new THREE.Vector3( 0, 0, 0 );
-
 				scene = new THREE.Scene();
 
 				var geometry = new THREE.SphereGeometry( 100, 32, 16 );
@@ -127,11 +124,9 @@
 				renderer = new THREE.WebGLRenderer();
 				container.appendChild( renderer.domElement );
 
-				effect = new THREE.CrosseyedEffect( renderer );
+				effect = new THREE.StereoEffect( renderer );
+				effect.separation = 10;
 				effect.setSize( window.innerWidth, window.innerHeight );
-				effect.separation = 90;
-
-				document.addEventListener( 'keydown', onKeyDown, false );
 
 				//
 
@@ -158,22 +153,6 @@
 
 			}
 
-			function onKeyDown ( event ) {
-
-				switch( event.keyCode ) {
-
-					/* O */
-					case 79: effect.separation -= 0.5; break;
-
-					/* P */
-					case 80: effect.separation += 0.5; break;
-
-				}
-
-				console.log( effect.separation );
-
-			};
-
 			//
 
 			function animate() {
@@ -190,6 +169,7 @@
 
 				camera.position.x += ( mouseX - camera.position.x ) * .05;
 				camera.position.y += ( - mouseY - camera.position.y ) * .05;
+				camera.lookAt( scene.position );
 
 				for ( var i = 0, il = spheres.length; i < il; i ++ ) {
 

+ 215 - 0
examples/webgl_effects_vr.html

@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - native vr demo</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #f0f0f0;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			.button {
+				position: fixed;
+				bottom: 20px;
+				right: 20px;
+				padding: 8px;
+				color: #FFF;
+				background-color: #555;
+			}
+
+			.button:hover {
+				cursor: pointer;
+				background-color: rgb(18, 36, 70);
+			}
+
+			.button.error {
+				pointer-events: none;
+				background-color: red;
+			}
+
+		</style>
+	</head>
+	<body>
+		<div class="button">Start VR Mode</div>
+
+		<script src="../build/three.js"></script>
+		<script src="js/effects/VREffect.js"></script>
+		<script src="js/controls/VRControls.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			var container, stats;
+			var camera, scene, projector, raycaster, renderer;
+			var vrEffect;
+			var vrControls;
+
+			var mouse = new THREE.Vector2(), INTERSECTED;
+			var radius = 100, theta = 0;
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				var info = document.createElement( 'div' );
+				info.style.position = 'absolute';
+				info.style.top = '10px';
+				info.style.width = '100%';
+				info.style.textAlign = 'center';
+				info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> webgl - interactive cubes';
+				container.appendChild( info );
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
+
+				scene = new THREE.Scene();
+
+				var light = new THREE.DirectionalLight( 0xffffff, 2 );
+				light.position.set( 1, 1, 1 ).normalize();
+				scene.add( light );
+
+				var light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( -1, -1, -1 ).normalize();
+				scene.add( light );
+
+				var geometry = new THREE.BoxGeometry( 20, 20, 20 );
+
+				for ( var i = 0; i < 2000; i ++ ) {
+
+					var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
+
+					object.position.x = Math.random() * 800 - 400;
+					object.position.y = Math.random() * 800 - 400;
+					object.position.z = Math.random() * 800 - 400;
+
+					object.rotation.x = Math.random() * 2 * Math.PI;
+					object.rotation.y = Math.random() * 2 * Math.PI;
+					object.rotation.z = Math.random() * 2 * Math.PI;
+
+					object.scale.x = Math.random() + 0.5;
+					object.scale.y = Math.random() + 0.5;
+					object.scale.z = Math.random() + 0.5;
+
+					scene.add( object );
+
+				}
+
+				projector = new THREE.Projector();
+				raycaster = new THREE.Raycaster();
+
+				renderer = new THREE.WebGLRenderer();
+				var fullScreenButton = document.querySelector( '.button' );
+				fullScreenButton.onclick = function() {
+					vrEffect.setFullScreen( true );
+				};
+
+				vrEffect = new THREE.VREffect(renderer, VREffectLoaded);
+				vrControls = new THREE.VRControls(camera);
+
+				function VREffectLoaded(error) {
+					if (error) {
+						fullScreenButton.innerHTML = error;
+						fullScreenButton.classList.add('error');
+					}
+				}
+
+				renderer.setClearColor( 0xf0f0f0 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.sortObjects = false;
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				event.preventDefault();
+
+				mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
+				mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				theta += 0.1;
+
+				camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) );
+				camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) );
+				camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) );
+				camera.lookAt( scene.position );
+
+				// find intersections
+
+				var vector = new THREE.Vector3( mouse.x, mouse.y, 1 );
+				projector.unprojectVector( vector, camera );
+
+				raycaster.set( camera.position, vector.sub( camera.position ).normalize() );
+
+				var intersects = raycaster.intersectObjects( scene.children );
+
+				if ( intersects.length > 0 ) {
+
+					if ( INTERSECTED != intersects[ 0 ].object ) {
+
+						if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
+
+						INTERSECTED = intersects[ 0 ].object;
+						INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
+						INTERSECTED.material.emissive.setHex( 0xff0000 );
+
+					}
+
+				} else {
+
+					if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
+
+					INTERSECTED = null;
+
+				}
+
+				vrControls.update();
+				vrEffect.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 2
examples/webgl_geometry_extrude_splines.html

@@ -136,8 +136,7 @@
 
 			tubeMesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [
 				new THREE.MeshLambertMaterial({
-					color: color,
-					transparent: true
+					color: color
 				}),
 				new THREE.MeshBasicMaterial({
 					color: 0x000000,

+ 667 - 0
examples/webgl_geometry_text2.html

@@ -0,0 +1,667 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - geometry - text</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+			}
+			#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
+		</style>
+	</head>
+	<body>
+
+		<div id="info">
+		<a href="http://threejs.org" target="_blank">three.js</a> - procedural 3D text by <a href="http://www.lab4games.net/zz85/blog" target="_blank">zz85</a> &amp; alteredq
+		(fonts from <a href="http://typeface.neocracy.org/">typeface.js</a> and <a href="http://en.wikipedia.org/wiki/Droid_%28font%29">Droid</a>)
+		<br/>built-in shape triangulation has been replaced with <a href="https://github.com/jahting/pnltri.js">PnlTri.js</a> by <a href="https://github.com/jahting" target="_blank">j ahting</a>
+		<br/>type to enter new text, drag to spin the text
+		<br/><span class="button" id="color">change color</span>,
+			<span class="button" id="font">change font</span>,
+			<span class="button" id="weight">change weight</span>,
+			<span class="button" id="bevel">change bevel</span>,
+			<span class="button" id="postprocessing">change postprocessing</span>,
+			<a id="permalink" href="#">permalink</a>
+		</div>
+
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/utils/GeometryUtils.js"></script>
+
+		<script src="js/shaders/ConvolutionShader.js"></script>
+		<script src="js/shaders/CopyShader.js"></script>
+		<script src="js/shaders/FilmShader.js"></script>
+		<script src="js/shaders/FXAAShader.js"></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/BloomPass.js"></script>
+		<script src="js/postprocessing/FilmPass.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<!-- load the font files -->
+
+		<script src="fonts/gentilis_bold.typeface.js"></script>
+		<script src="fonts/gentilis_regular.typeface.js"></script>
+		<script src="fonts/optimer_bold.typeface.js"></script>
+		<script src="fonts/optimer_regular.typeface.js"></script>
+		<script src="fonts/helvetiker_bold.typeface.js"></script>
+		<script src="fonts/helvetiker_regular.typeface.js"></script>
+		<script src="fonts/droid/droid_sans_regular.typeface.js"></script>
+		<script src="fonts/droid/droid_sans_bold.typeface.js"></script>
+		<script src="fonts/droid/droid_serif_regular.typeface.js"></script>
+		<script src="fonts/droid/droid_serif_bold.typeface.js"></script>
+
+		<!-- todo async loader for fonts -->
+
+
+		<!-- replace built-in triangulation with PnlTri.js -->
+		<script src="js/libs/pnltri.min.js"></script>
+		<script>
+			THREE.Shape.Utils.triangulateShape = ( function () {
+				var pnlTriangulator = new PNLTRI.Triangulator();
+				return function ( contour, holes ) {
+					// console.log("new Triangulation: PnlTri.js " + PNLTRI.REVISION );
+					return pnlTriangulator.triangulate_polygon( [ contour ].concat(holes) );
+				};
+			} )();
+		</script>
+		
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats, permalink, hex, color;
+
+			var camera, cameraTarget, scene, renderer;
+
+			var composer;
+			var effectFXAA;
+
+			var group, textMesh1, textMesh2, textGeo, material;
+
+			var firstLetter = true;
+
+			var text = "three.js",
+
+				height = 20,
+				size = 70,
+				hover = 30,
+
+				curveSegments = 4,
+
+				bevelThickness = 2,
+				bevelSize = 1.5,
+				bevelSegments = 3,
+				bevelEnabled = true,
+
+				font = "optimer", // helvetiker, optimer, gentilis, droid sans, droid serif
+				weight = "bold", // normal bold
+				style = "normal"; // normal italic
+
+			var mirror = true;
+
+			var fontMap = {
+
+				"helvetiker": 0,
+				"optimer": 1,
+				"gentilis": 2,
+				"droid sans": 3,
+				"droid serif": 4
+
+			};
+
+			var weightMap = {
+
+				"normal": 0,
+				"bold": 1
+
+			};
+
+			var reverseFontMap = {};
+			var reverseWeightMap = {};
+
+			for ( var i in fontMap ) reverseFontMap[ fontMap[i] ] = i;
+			for ( var i in weightMap ) reverseWeightMap[ weightMap[i] ] = i;
+
+			var targetRotation = 0;
+			var targetRotationOnMouseDown = 0;
+
+			var mouseX = 0;
+			var mouseXOnMouseDown = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			var postprocessing = { enabled : false };
+			var glow = 0.9;
+
+			init();
+			animate();
+
+			function capitalize( txt ) {
+
+				return txt.substring( 0, 1 ).toUpperCase() + txt.substring( 1 );
+
+			}
+
+			function decimalToHex( d ) {
+
+				var hex = Number( d ).toString( 16 );
+				hex = "000000".substr( 0, 6 - hex.length ) + hex;
+				return hex.toUpperCase();
+
+			}
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				permalink = document.getElementById( "permalink" );
+
+				// CAMERA
+
+				camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 1500 );
+				camera.position.set( 0, 400, 700 );
+
+				cameraTarget = new THREE.Vector3( 0, 150, 0 );
+
+				// SCENE
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0x000000, 250, 1400 );
+
+				// LIGHTS
+
+				var dirLight = new THREE.DirectionalLight( 0xffffff, 0.125 );
+				dirLight.position.set( 0, 0, 1 ).normalize();
+				scene.add( dirLight );
+
+				var pointLight = new THREE.PointLight( 0xffffff, 1.5 );
+				pointLight.position.set( 0, 100, 90 );
+				scene.add( pointLight );
+
+				//text = capitalize( font ) + " " + capitalize( weight );
+				//text = "abcdefghijklmnopqrstuvwxyz0123456789";
+				//text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+				// Get text from hash
+
+				var hash = document.location.hash.substr( 1 );
+
+				if ( hash.length !== 0 ) {
+
+					var colorhash  = hash.substring( 0, 6 );
+					var fonthash   = hash.substring( 6, 7 );
+					var weighthash = hash.substring( 7, 8 );
+					var pphash 	   = hash.substring( 8, 9 );
+					var bevelhash  = hash.substring( 9, 10 );
+					var texthash   = hash.substring( 10 );
+
+					hex = colorhash;
+					pointLight.color.setHex( parseInt( colorhash, 16 ) );
+
+					font = reverseFontMap[ parseInt( fonthash ) ];
+					weight = reverseWeightMap[ parseInt( weighthash ) ];
+
+					postprocessing.enabled = parseInt( pphash );
+					bevelEnabled = parseInt( bevelhash );
+
+					text = decodeURI( texthash );
+
+					updatePermalink();
+
+				} else {
+
+					pointLight.color.setHSL( Math.random(), 1, 0.5 );
+					hex = decimalToHex( pointLight.color.getHex() );
+
+				}
+
+				material = new THREE.MeshFaceMaterial( [ 
+					new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } ), // front
+					new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.SmoothShading } ) // side
+				] );
+
+				group = new THREE.Object3D();
+				group.position.y = 100;
+
+				scene.add( group );
+
+				createText();
+
+				var plane = new THREE.Mesh( new THREE.PlaneGeometry( 10000, 10000 ), new THREE.MeshBasicMaterial( { color: 0xffffff, opacity: 0.5, transparent: true } ) );
+				plane.position.y = 100;
+				plane.rotation.x = - Math.PI / 2;
+				scene.add( plane );
+
+				// RENDERER
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				renderer.setClearColor( scene.fog.color, 1 );
+
+				container.appendChild( renderer.domElement );
+
+				// STATS
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				//container.appendChild( stats.domElement );
+
+				// EVENTS
+
+				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+				document.addEventListener( 'keypress', onDocumentKeyPress, false );
+				document.addEventListener( 'keydown', onDocumentKeyDown, false );
+
+				document.getElementById( "color" ).addEventListener( 'click', function() {
+
+					pointLight.color.setHSL( Math.random(), 1, 0.5 );
+					hex = decimalToHex( pointLight.color.getHex() );
+
+					updatePermalink();
+
+				}, false );
+
+				document.getElementById( "font" ).addEventListener( 'click', function() {
+
+					if ( font == "helvetiker" ) {
+
+						font = "optimer";
+
+					} else if ( font == "optimer" ) {
+
+						font = "gentilis";
+
+					} else if ( font == "gentilis" ) {
+
+						font = "droid sans";
+
+					} else if ( font == "droid sans" ) {
+
+						font = "droid serif";
+
+					} else {
+
+						font = "helvetiker";
+
+					}
+
+					refreshText();
+
+				}, false );
+
+				document.getElementById( "weight" ).addEventListener( 'click', function() {
+
+					if ( weight == "bold" ) {
+
+						weight = "normal";
+
+					} else {
+
+						weight = "bold";
+
+					}
+
+					refreshText();
+
+				}, false );
+
+				document.getElementById( "bevel" ).addEventListener( 'click', function() {
+
+					bevelEnabled = !bevelEnabled;
+
+					refreshText();
+
+				}, false );
+
+				document.getElementById( "postprocessing" ).addEventListener( 'click', function() {
+
+					postprocessing.enabled = !postprocessing.enabled;
+					updatePermalink();
+
+				}, false );
+
+
+				// POSTPROCESSING
+
+				renderer.autoClear = false;
+
+				var renderModel = new THREE.RenderPass( scene, camera );
+				var effectBloom = new THREE.BloomPass( 0.25 );
+				var effectFilm = new THREE.FilmPass( 0.5, 0.125, 2048, false );
+
+				effectFXAA = new THREE.ShaderPass( THREE.FXAAShader );
+
+				var width = window.innerWidth || 2;
+				var height = window.innerHeight || 2;
+
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height );
+
+				effectFilm.renderToScreen = true;
+
+				composer = new THREE.EffectComposer( renderer );
+
+				composer.addPass( renderModel );
+				composer.addPass( effectFXAA );
+				composer.addPass( effectBloom );
+				composer.addPass( effectFilm );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				composer.reset();
+
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
+
+			}
+
+			//
+
+			function boolToNum( b ) {
+
+				return b ? 1 : 0;
+
+			}
+
+			function updatePermalink() {
+
+				var link = hex + fontMap[ font ] + weightMap[ weight ] + boolToNum( postprocessing.enabled ) + boolToNum( bevelEnabled ) + "#" + encodeURI( text );
+
+				permalink.href = "#" + link;
+				window.location.hash = link;
+
+			}
+
+			function onDocumentKeyDown( event ) {
+
+				if ( firstLetter ) {
+
+					firstLetter = false;
+					text = "";
+
+				}
+
+				var keyCode = event.keyCode;
+
+				// backspace
+
+				if ( keyCode == 8 ) {
+
+					event.preventDefault();
+
+					text = text.substring( 0, text.length - 1 );
+					refreshText();
+
+					return false;
+
+				}
+
+			}
+
+			function onDocumentKeyPress( event ) {
+
+				var keyCode = event.which;
+
+				// backspace
+
+				if ( keyCode == 8 ) {
+
+					event.preventDefault();
+
+				} else {
+
+					var ch = String.fromCharCode( keyCode );
+					text += ch;
+
+					refreshText();
+
+				}
+
+			}
+
+			function createText() {
+
+				textGeo = new THREE.TextGeometry( text, {
+
+					size: size,
+					height: height,
+					curveSegments: curveSegments,
+
+					font: font,
+					weight: weight,
+					style: style,
+
+					bevelThickness: bevelThickness,
+					bevelSize: bevelSize,
+					bevelEnabled: bevelEnabled,
+
+					material: 0,
+					extrudeMaterial: 1
+
+				});
+
+				textGeo.computeBoundingBox();
+				textGeo.computeVertexNormals();
+
+				// "fix" side normals by removing z-component of normals for side faces
+				// (this doesn't work well for beveled geometry as then we lose nice curvature around z-axis)
+
+				if ( ! bevelEnabled ) {
+
+					var triangleAreaHeuristics = 0.1 * ( height * size );
+
+					for ( var i = 0; i < textGeo.faces.length; i ++ ) {
+
+						var face = textGeo.faces[ i ];
+
+						if ( face.materialIndex == 1 ) {
+
+							for ( var j = 0; j < face.vertexNormals.length; j ++ ) {
+
+								face.vertexNormals[ j ].z = 0;
+								face.vertexNormals[ j ].normalize();
+
+							}
+
+							var va = textGeo.vertices[ face.a ];
+							var vb = textGeo.vertices[ face.b ];
+							var vc = textGeo.vertices[ face.c ];
+
+							var s = THREE.GeometryUtils.triangleArea( va, vb, vc );
+
+							if ( s > triangleAreaHeuristics ) {
+
+								for ( var j = 0; j < face.vertexNormals.length; j ++ ) {
+
+									face.vertexNormals[ j ].copy( face.normal );
+
+								}
+
+							}
+
+						}
+
+					}
+
+				}
+
+				var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
+
+				textMesh1 = new THREE.Mesh( textGeo, material );
+
+				textMesh1.position.x = centerOffset;
+				textMesh1.position.y = hover;
+				textMesh1.position.z = 0;
+
+				textMesh1.rotation.x = 0;
+				textMesh1.rotation.y = Math.PI * 2;
+
+				group.add( textMesh1 );
+
+				if ( mirror ) {
+
+					textMesh2 = new THREE.Mesh( textGeo, material );
+
+					textMesh2.position.x = centerOffset;
+					textMesh2.position.y = -hover;
+					textMesh2.position.z = height;
+
+					textMesh2.rotation.x = Math.PI;
+					textMesh2.rotation.y = Math.PI * 2;
+
+					group.add( textMesh2 );
+
+				}
+
+			}
+
+			function refreshText() {
+
+				updatePermalink();
+
+				group.remove( textMesh1 );
+				if ( mirror ) group.remove( textMesh2 );
+
+				if ( !text ) return;
+
+				createText();
+
+			}
+
+			function onDocumentMouseDown( event ) {
+
+				event.preventDefault();
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.addEventListener( 'mouseout', onDocumentMouseOut, false );
+
+				mouseXOnMouseDown = event.clientX - windowHalfX;
+				targetRotationOnMouseDown = targetRotation;
+
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = event.clientX - windowHalfX;
+
+				targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
+
+			}
+
+			function onDocumentMouseUp( event ) {
+
+				document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+
+			}
+
+			function onDocumentMouseOut( event ) {
+
+				document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+
+			}
+
+			function onDocumentTouchStart( event ) {
+
+				if ( event.touches.length == 1 ) {
+
+					event.preventDefault();
+
+					mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
+					targetRotationOnMouseDown = targetRotation;
+
+				}
+
+			}
+
+			function onDocumentTouchMove( event ) {
+
+				if ( event.touches.length == 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
+
+				}
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
+
+				camera.lookAt( cameraTarget );
+
+				renderer.clear();
+
+				if ( postprocessing.enabled ) {
+
+					composer.render( 0.05 );
+
+				} else {
+
+					renderer.render( scene, camera );
+
+				}
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 4 - 4
examples/webgl_interactive_raycasting_pointcloud.html

@@ -106,7 +106,7 @@
 			
 				var geometry = generatePointCloudGeometry( color, width, length );
 				
-				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
 				var pointcloud = new THREE.PointCloud( geometry, material );
 				
 				return pointcloud;
@@ -134,7 +134,7 @@
 				
 				geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
 				
-				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
 				var pointcloud = new THREE.PointCloud( geometry, material );
 				
 				return pointcloud;
@@ -165,7 +165,7 @@
 				var offset = { start: 0, count: indices.length, index: 0 };
 				geometry.offsets.push( offset );
 				
-				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
 				var pointcloud = new THREE.PointCloud( geometry, material );
 				
 				return pointcloud;
@@ -209,7 +209,7 @@
 				geometry.colors = colors;
 				geometry.computeBoundingBox();
 				
-				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: THREE.VertexColors } );
 				var pointcloud = new THREE.PointCloud( geometry, material );
 				
 				return pointcloud;

+ 3 - 2
examples/webgl_loader_collada_keyframe.html

@@ -47,6 +47,7 @@
 
 			var stats;
 			var scene;
+			var pointLight;
 			var camera;
 			var renderer;
 			var model;
@@ -126,8 +127,6 @@
 				// Lights
 
 				pointLight = new THREE.PointLight( 0xffffff, 1.75 );
-				pointLight.position = camera.position;
-
 				scene.add( pointLight );
 
 				// Renderer
@@ -224,6 +223,8 @@
 
 				}
 
+				pointLight.position.copy( camera.position );
+
 				progress += frameTime;
 				lastTimestamp = timestamp;
 				renderer.render( scene, camera );

+ 0 - 2
examples/webgl_loader_scene.html

@@ -162,8 +162,6 @@
 
 			function handle_update( result, pieces ) {
 
-				//renderer.initWebGLObjects( result.scene );
-
 				var m, material, count = 0;
 
 				for ( m in result.materials ) {

+ 0 - 4
examples/webgl_materials_cubemap_dynamic.html

@@ -964,9 +964,6 @@
 
 					cubeCamera.position.copy( currentCar.root.position );
 
-					renderer.autoUpdateObjects = false;
-					renderer.initWebGLObjects( scene );
-
 					renderer.autoClear = true;
 					cubeCamera.updateCubeMap( renderer, scene );
 
@@ -979,7 +976,6 @@
 
 				renderer.autoClear = false;
 				renderer.shadowMapEnabled = true;
-				renderer.autoUpdateObjects = true;
 
 				camera.lookAt( cameraTarget );
 

+ 220 - 0
examples/webgl_objects_update.html

@@ -0,0 +1,220 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - geometries</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer;
+			
+			var objectNewGeometry;
+			var objectToggleAddRemove;
+			var objectRandomizeFaces;
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera.position.y = 1500;
+
+				scene = new THREE.Scene();
+
+				var light, object;
+
+				scene.add( new THREE.AmbientLight( 0x404040 ) );
+
+				light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 0, 1, 0 );
+				scene.add( light );
+
+				var map = THREE.ImageUtils.loadTexture( 'textures/UV_Grid_Sm.jpg' );
+				map.wrapS = map.wrapT = THREE.RepeatWrapping;
+				map.anisotropy = 16;
+
+				//var material = new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map, side: THREE.DoubleSide } );
+
+				//
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( -400, 0, 200 );
+				scene.add( object );
+				objectNewGeometry = object
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( -200, 0, 200 );
+				scene.add( object );
+				objectToggleAddRemove = object 
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( 0, 0, 200 );
+				scene.add( object );
+				objectRandomizeFaces = object
+/*
+				These are not yet used but they are ready to be shown
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( 200, 0, 200 );
+				scene.add( object );
+
+				//
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( -400, 0, 0 );
+				scene.add( object );
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( -200, 0, 0 );
+				scene.add( object );
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( 0, 0, 0 );
+				scene.add( object );
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( 200, 0, 0 );
+				scene.add( object );
+
+				object = createObject( createMeshFaceMaterial(), 4 );
+				object.position.set( 400, 0, 0 );
+				scene.add( object );
+				*/
+				//
+
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+			
+			function createObject(material, segments ){
+				var geometry = createGeometry(segments);
+				var mesh = new THREE.Mesh( geometry , material);
+				return mesh;
+			}
+			function createGeometry(segments){
+				var matrix = new THREE.Matrix4();
+				var euler = new THREE.Euler()
+				var geometry = new THREE.BoxGeometry( 100, 100, 100, segments, segments, segments );
+				geometry.applyMatrix(matrix.makeRotationFromEuler(euler.set(parseInt(Math.random()*2,10)*Math.PI,parseInt(Math.random()*2,10)*Math.PI,parseInt(Math.random()*2,10)*Math.PI)))
+				return geometry;
+			}
+			
+			function createMeshFaceMaterial(){
+				var materials = [];
+				materials.push(new THREE.MeshBasicMaterial({color: 0xff0000}))
+				materials.push(new THREE.MeshBasicMaterial({color: 0xffff00}))
+				materials.push(new THREE.MeshBasicMaterial({color: 0x00ff00}))
+				materials.push(new THREE.MeshBasicMaterial({color: 0x00ffff}))
+				materials.push(new THREE.MeshBasicMaterial({color: 0x0000ff}))
+				materials.push(new THREE.MeshBasicMaterial({color: 0xff00ff}))
+				var material = new THREE.MeshFaceMaterial(materials);
+				return material;
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+			
+			function randomizeFaces(object){
+				for(var i = 0,l=object.geometry.faces.length;i<l;i++){
+					
+					object.geometry.faces[i].materialIndex = Math.floor(Math.random() * 6);
+					
+				}
+				object.geometry.groupsNeedUpdate = true;
+			};
+
+			function render() {
+
+				var timer = Date.now() * 0.001;
+				
+				if (parseInt(timer,10)%2 === 0){
+
+					if (scene.children.indexOf(objectToggleAddRemove) === -1) {
+						
+					
+						objectNewGeometry.geometry = createGeometry(1);
+						objectNewGeometry.geometry.buffersNeedUpdate = true;
+						randomizeFaces(objectRandomizeFaces);
+					
+						scene.add(objectToggleAddRemove);
+						
+					};
+					
+				} else {
+					
+					if (scene.children.indexOf(objectToggleAddRemove) !== -1) {
+											
+						objectNewGeometry.geometry = createGeometry(1);
+						objectNewGeometry.geometry.buffersNeedUpdate = true;
+						randomizeFaces(objectRandomizeFaces);
+					
+						scene.remove(objectToggleAddRemove);
+						
+					};
+					
+				};
+
+				camera.lookAt( scene.position );
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 1 - 1
examples/webgl_particles_billboards_colors.html

@@ -86,7 +86,7 @@
 
 				geometry.colors = colors;
 
-				material = new THREE.PointCloudMaterial( { size: 85, map: sprite, vertexColors: true, transparent: true } );
+				material = new THREE.PointCloudMaterial( { size: 85, map: sprite, vertexColors: THREE.VertexColors, transparent: true } );
 				material.color.setHSL( 1.0, 0.2, 0.7 );
 
 				particles = new THREE.PointCloud( geometry, material );

+ 142 - 0
examples/webgl_postprocessing_glitch.html

@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - postprocessing - digital glitch</title>
+		<meta charset="utf-8">
+		<style>
+			body {
+				margin: 0px;
+				background-color: #000000;
+				overflow: hidden;
+			}
+
+			div {
+				position: absolute;
+				z-index: 10;
+				color: #fff;
+				font-family: monospace;
+				text-align: center;
+				margin: 10px;
+				width: 100%;
+			}
+
+			label, input {
+				cursor: pointer;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/shaders/CopyShader.js"></script>
+		<script src="js/shaders/DigitalGlitch.js"></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/postprocessing/GlitchPass.js"></script>
+
+		<div>
+			<label for="dotScreen">Glitch me wild:</label><input id="wildGlitch" type="checkbox" onchange="updateOptions()"/><br />
+		</div>
+
+		<script>
+
+			var camera, scene, renderer, composer;
+			var object, light;
+
+			var glitchPass;
+
+			init();
+			animate();
+
+			function updateOptions() {
+				var wildGlitch = document.getElementById('wildGlitch');
+				glitchPass.goWild=wildGlitch.checked;
+			}
+
+			function init() {
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+				//
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.z = 400;
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0x000000, 1, 1000 );
+
+				object = new THREE.Object3D();
+				scene.add( object );
+
+				var geometry = new THREE.SphereGeometry( 1, 4, 4 );
+				var material = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
+
+				for ( var i = 0; i < 100; i ++ ) {
+					material = new THREE.MeshPhongMaterial( { color: 0xffffff * Math.random(), shading: THREE.FlatShading } );
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.position.set( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 ).normalize();
+					mesh.position.multiplyScalar( Math.random() * 400 );
+					mesh.rotation.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
+					mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 50;
+					object.add( mesh );
+
+				}
+
+				scene.add( new THREE.AmbientLight( 0x222222 ) );
+
+				light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 1, 1, 1 );
+				scene.add( light );
+
+				// postprocessing
+
+				composer = new THREE.EffectComposer( renderer );
+				composer.addPass( new THREE.RenderPass( scene, camera ) );
+
+				glitchPass = new THREE.GlitchPass();
+				glitchPass.renderToScreen = true;
+				composer.addPass( glitchPass );
+
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				updateOptions();
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				var time = Date.now();
+
+				object.rotation.x += 0.005;
+				object.rotation.y += 0.01;
+
+				composer.render();
+				//renderer.render(scene, camera);
+
+			}
+
+		</script>
+	</body>
+</html>

+ 0 - 5
examples/webgl_shading_physical.html

@@ -565,9 +565,6 @@
 
 				// render shadow map
 
-				renderer.autoUpdateObjects = false;
-
-				renderer.initWebGLObjects( scene );
 				renderer.updateShadowMap( scene, camera );
 
 				// render cube map
@@ -583,8 +580,6 @@
 
 				// render scene
 
-				renderer.autoUpdateObjects = true;
-
 				//renderer.render( scene, camera );
 				//renderer.clearTarget( null, 1, 1, 1 );
 				composer.render( 0.1 );

+ 0 - 6
examples/webgl_terrain_dynamic.html

@@ -512,8 +512,6 @@
 
 					morphs.push( meshAnim );
 
-					renderer.initWebGLObjects( scene );
-
 				}
 
 				function morphColorsToFaceColors( geometry ) {
@@ -560,10 +558,6 @@
 
 				} );
 
-				// PRE-INIT
-
-				renderer.initWebGLObjects( scene );
-
 			}
 
 			//

+ 10 - 15
src/core/Geometry.js

@@ -48,6 +48,7 @@ THREE.Geometry = function () {
 	this.lineDistancesNeedUpdate = false;
 
 	this.buffersNeedUpdate = false;
+	this.groupsNeedUpdate = false;
 
 };
 
@@ -678,12 +679,13 @@ THREE.Geometry.prototype = {
 		return function ( usesFaceMaterial, maxVerticesInGroup ) {
 
 			var f, fl, face, materialIndex,
-				groupHash, hash_map = {};
+				groupHash, hash_map = {},geometryGroup;
 
 			var numMorphTargets = this.morphTargets.length;
 			var numMorphNormals = this.morphNormals.length;
 
 			this.geometryGroups = {};
+			this.geometryGroupsList = [];
 
 			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
 
@@ -700,8 +702,9 @@ THREE.Geometry.prototype = {
 
 				if ( ! ( groupHash in this.geometryGroups ) ) {
 
-					this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
-
+					geometryGroup = { 'id': geometryGroupCounter++, 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+					this.geometryGroups[ groupHash ] = geometryGroup;
+					this.geometryGroupsList.push(geometryGroup);
 				}
 
 				if ( this.geometryGroups[ groupHash ].vertices + 3 > maxVerticesInGroup ) {
@@ -711,8 +714,10 @@ THREE.Geometry.prototype = {
 
 					if ( ! ( groupHash in this.geometryGroups ) ) {
 
-						this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
-
+						geometryGroup = { 'id': geometryGroupCounter++, 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+						this.geometryGroups[ groupHash ] = geometryGroup;
+						this.geometryGroupsList.push(geometryGroup);
+						
 					}
 
 				}
@@ -722,16 +727,6 @@ THREE.Geometry.prototype = {
 
 			}
 
-			this.geometryGroupsList = [];
-
-			for ( var g in this.geometryGroups ) {
-
-				this.geometryGroups[ g ].id = geometryGroupCounter ++;
-
-				this.geometryGroupsList.push( this.geometryGroups[ g ] );
-
-			}
-
 		};
 
 	} )(),

+ 39 - 1
src/core/Object3D.js

@@ -297,10 +297,22 @@ THREE.Object3D.prototype = {
 
 	add: function ( object ) {
 
+		if ( arguments.length > 1 ) {
+
+			for ( var i = 0; i < arguments.length; i++ ) {
+
+				this.add( arguments[ i ] );
+
+			}
+
+			return this;
+
+		};
+
 		if ( object === this ) {
 
 			console.warn( "THREE.Object3D.add: An object can't be added as a child of itself." );
-			return;
+			return this;
 
 		}
 
@@ -335,10 +347,22 @@ THREE.Object3D.prototype = {
 
 		}
 
+		return this;
+
 	},
 
 	remove: function ( object ) {
 
+		if ( arguments.length > 1 ) {
+
+			for ( var i = 0; i < arguments.length; i++ ) {
+
+				this.remove( arguments[ i ] );
+
+			}
+
+		};
+
 		var index = this.children.indexOf( object );
 
 		if ( index !== - 1 ) {
@@ -382,6 +406,20 @@ THREE.Object3D.prototype = {
 
 	},
 
+	traverseVisible: function ( callback ) {
+
+		if ( this.visible === false ) return;
+
+		callback( this );
+
+		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
+
+			this.children[ i ].traverseVisible( callback );
+
+		}
+
+	},
+
 	getObjectById: function ( id, recursive ) {
 
 		for ( var i = 0, l = this.children.length; i < l; i ++ ) {

+ 58 - 73
src/core/Projector.js

@@ -80,65 +80,6 @@ THREE.Projector = function () {
 
 	};
 
-	var projectObject = function ( object ) {
-
-		if ( object.visible === false ) return;
-
-		if ( object instanceof THREE.Light ) {
-
-			_renderData.lights.push( object );
-
-		} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
-
-			if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
-
-				_object = getNextObjectInPool();
-				_object.id = object.id;
-				_object.object = object;
-
-				if ( object.renderDepth !== null ) {
-
-					_object.z = object.renderDepth;
-
-				} else {
-
-					_vector3.setFromMatrixPosition( object.matrixWorld );
-					_vector3.applyProjection( _viewProjectionMatrix );
-					_object.z = _vector3.z;
-
-				}
-
-				_renderData.objects.push( _object );
-
-			}
-
-		}
-
-		for ( var i = 0, l = object.children.length; i < l; i ++ ) {
-
-			projectObject( object.children[ i ] );
-
-		}
-
-	};
-
-	var projectGraph = function ( root, sortObjects ) {
-
-		_objectCount = 0;
-
-		_renderData.objects.length = 0;
-		_renderData.lights.length = 0;
-
-		projectObject( root );
-
-		if ( sortObjects === true ) {
-
-			_renderData.objects.sort( painterSort );
-
-		}
-
-	};
-
 	var RenderList = function () {
 
 		var normals = [];
@@ -303,9 +244,6 @@ THREE.Projector = function () {
 
 	this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
 
-		var object, geometry, vertices, faces, face, faceVertexNormals, faceVertexUvs,
-		isFaceMaterial, objectMaterials;
-
 		_faceCount = 0;
 		_lineCount = 0;
 		_spriteCount = 0;
@@ -320,12 +258,59 @@ THREE.Projector = function () {
 
 		_frustum.setFromMatrix( _viewProjectionMatrix );
 
-		projectGraph( scene, sortObjects );
+		//
+
+		_objectCount = 0;
+
+		_renderData.objects.length = 0;
+		_renderData.lights.length = 0;
+
+		scene.traverseVisible( function ( object ) {
+
+			if ( object instanceof THREE.Light ) {
+
+				_renderData.lights.push( object );
+
+			} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
+
+				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
+
+					_object = getNextObjectInPool();
+					_object.id = object.id;
+					_object.object = object;
+
+					if ( object.renderDepth !== null ) {
+
+						_object.z = object.renderDepth;
+
+					} else {
+
+						_vector3.setFromMatrixPosition( object.matrixWorld );
+						_vector3.applyProjection( _viewProjectionMatrix );
+						_object.z = _vector3.z;
+
+					}
+
+					_renderData.objects.push( _object );
+
+				}
+
+			}
+
+		} );
+
+		if ( sortObjects === true ) {
+
+			_renderData.objects.sort( painterSort );
+
+		}
+
+		//
 
 		for ( var o = 0, ol = _renderData.objects.length; o < ol; o ++ ) {
 
-			object = _renderData.objects[ o ].object;
-			geometry = object.geometry;
+			var object = _renderData.objects[ o ].object;
+			var geometry = object.geometry;
 
 			renderList.setObject( object );
 
@@ -415,14 +400,14 @@ THREE.Projector = function () {
 
 				} else if ( geometry instanceof THREE.Geometry ) {
 
-					vertices = geometry.vertices;
-					faces = geometry.faces;
-					faceVertexUvs = geometry.faceVertexUvs[ 0 ];
+					var vertices = geometry.vertices;
+					var faces = geometry.faces;
+					var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
 
 					_normalMatrix.getNormalMatrix( _modelMatrix );
 
-					isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
-					objectMaterials = isFaceMaterial === true ? object.material : null;
+					var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
+					var objectMaterials = isFaceMaterial === true ? object.material : null;
 
 					for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {
 
@@ -433,7 +418,7 @@ THREE.Projector = function () {
 
 					for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
 
-						face = faces[ f ];
+						var face = faces[ f ];
 
 						var material = isFaceMaterial === true
 							 ? objectMaterials.materials[ face.materialIndex ]
@@ -518,7 +503,7 @@ THREE.Projector = function () {
 
 						_face.normalModel.applyMatrix3( _normalMatrix ).normalize();
 
-						faceVertexNormals = face.vertexNormals;
+						var faceVertexNormals = face.vertexNormals;
 
 						for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {
 
@@ -604,7 +589,7 @@ THREE.Projector = function () {
 
 					_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
 
-					vertices = object.geometry.vertices;
+					var vertices = object.geometry.vertices;
 
 					if ( vertices.length === 0 ) continue;
 

+ 9 - 1
src/extras/FontUtils.js

@@ -33,7 +33,15 @@ THREE.FontUtils = {
 
 	getFace: function () {
 
-		return this.faces[ this.face ][ this.weight ][ this.style ];
+		try {
+
+			return this.faces[ this.face ][ this.weight ][ this.style ];
+
+		} catch (e) {
+
+			throw "The font " + this.face + " with " + this.weight + " weight and " + this.style + " style is missing."
+
+		};
 
 	},
 

+ 0 - 7
src/extras/geometries/ExtrudeGeometry.js

@@ -35,8 +35,6 @@ THREE.ExtrudeGeometry = function ( shapes, options ) {
 
 	shapes = shapes instanceof Array ? shapes : [ shapes ];
 
-	this.shapebb = shapes[ shapes.length - 1 ].getBoundingBox();
-
 	this.addShapeList( shapes, options );
 
 	this.computeFaceNormals();
@@ -85,11 +83,6 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 	// Use default WorldUVGenerator if no UV generators are specified.
 	var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
 
-	var shapebb = this.shapebb;
-	//shapebb = shape.getBoundingBox();
-
-
-
 	var splineTube, binormal, normal, position2;
 	if ( extrudePath ) {
 

+ 0 - 4
src/extras/geometries/ShapeGeometry.js

@@ -20,8 +20,6 @@ THREE.ShapeGeometry = function ( shapes, options ) {
 
 	if ( shapes instanceof Array === false ) shapes = [ shapes ];
 
-	this.shapebb = shapes[ shapes.length - 1 ].getBoundingBox();
-
 	this.addShapeList( shapes, options );
 
 	this.computeFaceNormals();
@@ -56,8 +54,6 @@ THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
 	var material = options.material;
 	var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
 
-	var shapebb = this.shapebb;
-
 	//
 
 	var i, l, hole, s;

+ 2 - 0
src/extras/geometries/TubeGeometry.js

@@ -174,6 +174,7 @@ THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
 
 	initialNormal3();
 
+	/*
 	function initialNormal1(lastBinormal) {
 		// fixed start binormal. Has dangers of 0 vectors
 		normals[ 0 ] = new THREE.Vector3();
@@ -195,6 +196,7 @@ THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
 		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ).normalize();
 
 	}
+	*/
 
 	function initialNormal3() {
 		// select an initial normal vector perpenicular to the first tangent vector,

+ 1 - 1
src/extras/helpers/SkeletonHelper.js

@@ -26,7 +26,7 @@ THREE.SkeletonHelper = function ( object ) {
 
 	}
 
-	var material = new THREE.LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, transparent: true } );
+	var material = new THREE.LineBasicMaterial( { vertexColors: THREE.VertexColors, depthTest: false, depthWrite: false, transparent: true } );
 
 	THREE.Line.call( this, geometry, material, THREE.LinePieces );
 

+ 55 - 51
src/extras/helpers/WireframeHelper.js

@@ -65,38 +65,42 @@ THREE.WireframeHelper = function ( object, hex ) {
 
 		geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
 
-	} else if ( object.geometry instanceof THREE.BufferGeometry && object.geometry.attributes.index !== undefined ) { // Indexed BufferGeometry
+	} else if ( object.geometry instanceof THREE.BufferGeometry ) {
 
-		var vertices = object.geometry.attributes.position.array;
-		var indices = object.geometry.attributes.index.array;
-		var offsets = object.geometry.offsets;
-		var numEdges = 0;
+		if ( object.geometry.attributes.index !== undefined ) { // Indexed BufferGeometry
 
-		// allocate maximal size
-		var edges = new Uint32Array( 2 * indices.length );
+			var vertices = object.geometry.attributes.position.array;
+			var indices = object.geometry.attributes.index.array;
+			var offsets = object.geometry.offsets;
+			var numEdges = 0;
 
-		for ( var o = 0, ol = offsets.length; o < ol; ++ o ) {
+			// allocate maximal size
+			var edges = new Uint32Array( 2 * indices.length );
 
-			var start = offsets[ o ].start;
-			var count = offsets[ o ].count;
-			var index = offsets[ o ].index;
+			for ( var o = 0, ol = offsets.length; o < ol; ++ o ) {
 
-			for ( var i = start, il = start + count; i < il; i += 3 ) {
+				var start = offsets[ o ].start;
+				var count = offsets[ o ].count;
+				var index = offsets[ o ].index;
 
-				for ( var j = 0; j < 3; j ++ ) {
+				for ( var i = start, il = start + count; i < il; i += 3 ) {
+
+					for ( var j = 0; j < 3; j ++ ) {
+
+						edge[ 0 ] = index + indices[ i + j ];
+						edge[ 1 ] = index + indices[ i + ( j + 1 ) % 3 ];
+						edge.sort( sortFunction );
 
-					edge[ 0 ] = index + indices[ i + j ];
-					edge[ 1 ] = index + indices[ i + ( j + 1 ) % 3 ];
-					edge.sort( sortFunction );
+						var key = edge.toString();
 
-					var key = edge.toString();
+						if ( hash[ key ] === undefined ) {
 
-					if ( hash[ key ] === undefined ) {
+							edges[ 2 * numEdges ] = edge[ 0 ];
+							edges[ 2 * numEdges + 1 ] = edge[ 1 ];
+							hash[ key ] = true;
+							numEdges ++;
 
-						edges[ 2 * numEdges ] = edge[ 0 ];
-						edges[ 2 * numEdges + 1 ] = edge[ 1 ];
-						hash[ key ] = true;
-						numEdges ++;
+						}
 
 					}
 
@@ -104,55 +108,55 @@ THREE.WireframeHelper = function ( object, hex ) {
 
 			}
 
-		}
+			var coords = new Float32Array( numEdges * 2 * 3 );
 
-		var coords = new Float32Array( numEdges * 2 * 3 );
+			for ( var i = 0, l = numEdges; i < l; i ++ ) {
 
-		for ( var i = 0, l = numEdges; i < l; i ++ ) {
+				for ( var j = 0; j < 2; j ++ ) {
 
-			for ( var j = 0; j < 2; j ++ ) {
+					var index = 6 * i + 3 * j;
+					var index2 = 3 * edges[ 2 * i + j];
+					coords[ index + 0 ] = vertices[ index2 ];
+					coords[ index + 1 ] = vertices[ index2 + 1 ];
+					coords[ index + 2 ] = vertices[ index2 + 2 ];
 
-				var index = 6 * i + 3 * j;
-				var index2 = 3 * edges[ 2 * i + j];
-				coords[ index + 0 ] = vertices[ index2 ];
-				coords[ index + 1 ] = vertices[ index2 + 1 ];
-				coords[ index + 2 ] = vertices[ index2 + 2 ];
+				}
 
 			}
 
-		}
+			geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
 
-		geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
+		} else { // non-indexed BufferGeometry
 
-	} else if ( object.geometry instanceof THREE.BufferGeometry ) { // non-indexed BufferGeometry
+			var vertices = object.geometry.attributes.position.array;
+			var numEdges = vertices.length / 3;
+			var numTris = numEdges / 3;
 
-		var vertices = object.geometry.attributes.position.array;
-		var numEdges = vertices.length / 3;
-		var numTris = numEdges / 3;
+			var coords = new Float32Array( numEdges * 2 * 3 );
 
-		var coords = new Float32Array( numEdges * 2 * 3 );
+			for ( var i = 0, l = numTris; i < l; i ++ ) {
 
-		for ( var i = 0, l = numTris; i < l; i ++ ) {
+				for ( var j = 0; j < 3; j ++ ) {
 
-			for ( var j = 0; j < 3; j ++ ) {
+					var index = 18 * i + 6 * j;
 
-				var index = 18 * i + 6 * j;
+					var index1 = 9 * i + 3 * j;
+					coords[ index + 0 ] = vertices[ index1 ];
+					coords[ index + 1 ] = vertices[ index1 + 1 ];
+					coords[ index + 2 ] = vertices[ index1 + 2 ];
 
-				var index1 = 9 * i + 3 * j;
-				coords[ index + 0 ] = vertices[ index1 ];
-				coords[ index + 1 ] = vertices[ index1 + 1 ];
-				coords[ index + 2 ] = vertices[ index1 + 2 ];
+					var index2 = 9 * i + 3 * ( ( j + 1 ) % 3 );
+					coords[ index + 3 ] = vertices[ index2 ];
+					coords[ index + 4 ] = vertices[ index2 + 1 ];
+					coords[ index + 5 ] = vertices[ index2 + 2 ];
 
-				var index2 = 9 * i + 3 * ( ( j + 1 ) % 3 );
-				coords[ index + 3 ] = vertices[ index2 ];
-				coords[ index + 4 ] = vertices[ index2 + 1 ];
-				coords[ index + 5 ] = vertices[ index2 + 2 ];
+				}
 
 			}
 
-		}
+			geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
 
-		geometry.addAttribute( 'position', new THREE.BufferAttribute( coords, 3 ) );
+		}
 
 	}
 

+ 56 - 51
src/extras/renderers/plugins/DepthPassPlugin.js

@@ -12,7 +12,8 @@ THREE.DepthPassPlugin = function () {
 	_depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
 
 	_frustum = new THREE.Frustum(),
-	_projScreenMatrix = new THREE.Matrix4();
+	_projScreenMatrix = new THREE.Matrix4(),
+	_renderList = [];
 
 	this.init = function ( renderer ) {
 
@@ -76,84 +77,61 @@ THREE.DepthPassPlugin = function () {
 		_renderer.clear();
 
 		// set object matrices & frustum culling
-
-		renderList = scene.__webglObjects;
-
-		for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
-
-			webglObject = renderList[ j ];
-			object = webglObject.object;
-
-			webglObject.render = false;
-
-			if ( object.visible ) {
-
-				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
-
-					object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
-
-					webglObject.render = true;
-
-				}
-
-			}
-
-		}
+		
+		_renderList.length = 0;
+		projectObject(scene,scene,camera);
 
 		// render regular objects
 
 		var objectMaterial, useMorphing, useSkinning;
 
-		for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
-
-			webglObject = renderList[ j ];
-
-			if ( webglObject.render ) {
+		for ( j = 0, jl = _renderList.length; j < jl; j ++ ) {
 
-				object = webglObject.object;
-				buffer = webglObject.buffer;
+			webglObject = _renderList[ j ];
 
-				// todo: create proper depth material for particles
+			object = webglObject.object;
+			buffer = webglObject.buffer;
 
-				if ( object instanceof THREE.PointCloud && ! object.customDepthMaterial ) continue;
+			// todo: create proper depth material for particles
 
-				objectMaterial = getObjectMaterial( object );
+			if ( object instanceof THREE.PointCloud && ! object.customDepthMaterial ) continue;
 
-				if ( objectMaterial ) _renderer.setMaterialFaces( object.material );
+			objectMaterial = getObjectMaterial( object );
 
-				useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
-				useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;
+			if ( objectMaterial ) _renderer.setMaterialFaces( object.material );
 
-				if ( object.customDepthMaterial ) {
+			useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
+			useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;
 
-					material = object.customDepthMaterial;
+			if ( object.customDepthMaterial ) {
 
-				} else if ( useSkinning ) {
+				material = object.customDepthMaterial;
 
-					material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
+			} else if ( useSkinning ) {
 
-				} else if ( useMorphing ) {
+				material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
 
-					material = _depthMaterialMorph;
+			} else if ( useMorphing ) {
 
-				} else {
+				material = _depthMaterialMorph;
 
-					material = _depthMaterial;
+			} else {
 
-				}
+				material = _depthMaterial;
 
-				if ( buffer instanceof THREE.BufferGeometry ) {
+			}
 
-					_renderer.renderBufferDirect( camera, scene.__lights, fog, material, buffer, object );
+			if ( buffer instanceof THREE.BufferGeometry ) {
 
-				} else {
+				_renderer.renderBufferDirect( camera, scene.__lights, fog, material, buffer, object );
 
-					_renderer.renderBuffer( camera, scene.__lights, fog, material, buffer, object );
+			} else {
 
-				}
+				_renderer.renderBuffer( camera, scene.__lights, fog, material, buffer, object );
 
 			}
 
+
 		}
 
 		// set matrices and render immediate objects
@@ -184,6 +162,33 @@ THREE.DepthPassPlugin = function () {
 		_gl.enable( _gl.BLEND );
 
 	};
+	
+	function projectObject(scene, object,camera){
+		
+		if ( object.visible ) {
+	
+			var webglObjects = scene.__webglObjects[object.id];
+	
+			if (webglObjects && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {
+		
+		
+				for (var i = 0, l = webglObjects.length; i < l; i++){
+			
+					var webglObject = webglObjects[i];
+					
+					object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
+					_renderList.push(webglObject);
+					
+				}
+			}
+	
+			for(var i = 0, l = object.children.length; i < l; i++) {
+				
+				projectObject(scene, object.children[i], camera);
+			}
+		
+		}
+	}
 
 	// For the moment just ignore objects that have multiple materials with different animation methods
 	// Only the first material will be taken into account for deciding which depth material to use

+ 18 - 11
src/extras/renderers/plugins/LensFlarePlugin.js

@@ -5,6 +5,8 @@
 
 THREE.LensFlarePlugin = function () {
 
+	var flares = [];
+
 	var _gl, _renderer, _precision, _lensFlare = {};
 
 	this.init = function ( renderer ) {
@@ -105,10 +107,19 @@ THREE.LensFlarePlugin = function () {
 
 	this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
 
-		var flares = scene.__webglFlares,
-			nFlares = flares.length;
+		flares.length = 0;
+
+		scene.traverseVisible( function ( child ) {
+
+			if ( child instanceof THREE.LensFlare ) {
 
-		if ( ! nFlares ) return;
+				flares.push( child );
+
+			}
+
+		} );
+
+		if ( flares.length === 0 ) return;
 
 		var tempPosition = new THREE.Vector3();
 
@@ -147,18 +158,14 @@ THREE.LensFlarePlugin = function () {
 		_gl.disable( _gl.CULL_FACE );
 		_gl.depthMask( false );
 
-		var i, j, jl, flare, sprite;
-
-		for ( i = 0; i < nFlares; i ++ ) {
+		for ( var i = 0, l = flares.length; i < l; i ++ ) {
 
 			size = 16 / viewportHeight;
 			scale.set( size * invAspect, size );
 
 			// calc object screen position
 
-			flare = flares[ i ];
-
-			if ( flare.visible === false ) continue;
+			var flare = flares[ i ];
 			
 			tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] );
 
@@ -235,9 +242,9 @@ THREE.LensFlarePlugin = function () {
 				_gl.uniform1i( uniforms.renderType, 2 );
 				_gl.enable( _gl.BLEND );
 
-				for ( j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
+				for ( var j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
 
-					sprite = flare.lensFlares[ j ];
+					var sprite = flare.lensFlares[ j ];
 
 					if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
 

+ 61 - 56
src/extras/renderers/plugins/ShadowMapPlugin.js

@@ -14,7 +14,9 @@ THREE.ShadowMapPlugin = function () {
 	_min = new THREE.Vector3(),
 	_max = new THREE.Vector3(),
 
-	_matrixPosition = new THREE.Vector3();
+	_matrixPosition = new THREE.Vector3(),
+	
+	_renderList = [];
 
 	this.init = function ( renderer ) {
 
@@ -51,7 +53,6 @@ THREE.ShadowMapPlugin = function () {
 		shadowMap, shadowMatrix, shadowCamera,
 		program, buffer, material,
 		webglObject, object, light,
-		renderList,
 
 		lights = [],
 		k = 0,
@@ -230,85 +231,62 @@ THREE.ShadowMapPlugin = function () {
 
 			// set object matrices & frustum culling
 
-			renderList = scene.__webglObjects;
+			_renderList.length = 0;
+			projectObject(scene,scene,shadowCamera);
 
-			for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
-
-				webglObject = renderList[ j ];
-				object = webglObject.object;
-
-				webglObject.render = false;
-
-				if ( object.visible && object.castShadow ) {
-
-					if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
-
-						object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
-
-						webglObject.render = true;
-
-					}
-
-				}
-
-			}
 
 			// render regular objects
 
 			var objectMaterial, useMorphing, useSkinning;
 
-			for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
-
-				webglObject = renderList[ j ];
-
-				if ( webglObject.render ) {
+			for ( j = 0, jl = _renderList.length; j < jl; j ++ ) {
 
-					object = webglObject.object;
-					buffer = webglObject.buffer;
+				webglObject = _renderList[ j ];
 
-					// culling is overriden globally for all objects
-					// while rendering depth map
+				object = webglObject.object;
+				buffer = webglObject.buffer;
 
-					// need to deal with MeshFaceMaterial somehow
-					// in that case just use the first of material.materials for now
-					// (proper solution would require to break objects by materials
-					//  similarly to regular rendering and then set corresponding
-					//  depth materials per each chunk instead of just once per object)
+				// culling is overriden globally for all objects
+				// while rendering depth map
 
-					objectMaterial = getObjectMaterial( object );
+				// need to deal with MeshFaceMaterial somehow
+				// in that case just use the first of material.materials for now
+				// (proper solution would require to break objects by materials
+				//  similarly to regular rendering and then set corresponding
+				//  depth materials per each chunk instead of just once per object)
 
-					useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
-					useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;
+				objectMaterial = getObjectMaterial( object );
 
-					if ( object.customDepthMaterial ) {
+				useMorphing = object.geometry.morphTargets !== undefined && object.geometry.morphTargets.length > 0 && objectMaterial.morphTargets;
+				useSkinning = object instanceof THREE.SkinnedMesh && objectMaterial.skinning;
 
-						material = object.customDepthMaterial;
+				if ( object.customDepthMaterial ) {
 
-					} else if ( useSkinning ) {
+					material = object.customDepthMaterial;
 
-						material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
+				} else if ( useSkinning ) {
 
-					} else if ( useMorphing ) {
+					material = useMorphing ? _depthMaterialMorphSkin : _depthMaterialSkin;
 
-						material = _depthMaterialMorph;
+				} else if ( useMorphing ) {
 
-					} else {
+					material = _depthMaterialMorph;
 
-						material = _depthMaterial;
+				} else {
 
-					}
+					material = _depthMaterial;
 
-					_renderer.setMaterialFaces( objectMaterial );
+				}
 
-					if ( buffer instanceof THREE.BufferGeometry ) {
+				_renderer.setMaterialFaces( objectMaterial );
 
-						_renderer.renderBufferDirect( shadowCamera, scene.__lights, fog, material, buffer, object );
+				if ( buffer instanceof THREE.BufferGeometry ) {
 
-					} else {
+					_renderer.renderBufferDirect( shadowCamera, scene.__lights, fog, material, buffer, object );
 
-						_renderer.renderBuffer( shadowCamera, scene.__lights, fog, material, buffer, object );
+				} else {
 
-					}
+					_renderer.renderBuffer( shadowCamera, scene.__lights, fog, material, buffer, object );
 
 				}
 
@@ -316,7 +294,7 @@ THREE.ShadowMapPlugin = function () {
 
 			// set matrices and render immediate objects
 
-			renderList = scene.__webglObjectsImmediate;
+			var renderList = scene.__webglObjectsImmediate;
 
 			for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
 
@@ -350,6 +328,33 @@ THREE.ShadowMapPlugin = function () {
 		}
 
 	};
+	
+	function projectObject(scene, object,shadowCamera){
+		
+		if ( object.visible ) {
+	
+			var webglObjects = scene.__webglObjects[object.id];
+	
+			if (webglObjects && object.castShadow && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {
+		
+		
+				for (var i = 0, l = webglObjects.length; i < l; i++){
+			
+					var webglObject = webglObjects[i];
+					
+					object._modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
+					_renderList.push(webglObject);
+					
+				}
+			}
+	
+			for(var i = 0, l = object.children.length; i < l; i++) {
+				
+				projectObject(scene, object.children[i],shadowCamera);
+			}
+		
+		}
+	}
 
 	function createVirtualLight( light, cascade ) {
 

+ 34 - 21
src/extras/renderers/plugins/SpritePlugin.js

@@ -7,6 +7,8 @@ THREE.SpritePlugin = function () {
 
 	var _gl, _renderer, _texture;
 
+	var sprites = [];
+
 	var vertices, faces, vertexBuffer, elementBuffer;
 	var program, attributes, uniforms;
 
@@ -65,17 +67,35 @@ THREE.SpritePlugin = function () {
 
 			alphaTest:			_gl.getUniformLocation( program, 'alphaTest' )
 		};
-
-		_texture = new THREE.Texture();
+		
+		var canvas = document.createElement( 'canvas' );
+		canvas.width = 8;
+		canvas.height = 8;
+		
+		var context = canvas.getContext( '2d' );
+		context.fillStyle = 'white';
+		context.fillRect( 0, 0, 8, 8 );
+
+		_texture = new THREE.Texture( canvas );
+		_texture.needsUpdate = true;
 
 	};
 
 	this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
 
-		var sprites = scene.__webglSprites,
-			nSprites = sprites.length;
+		sprites.length = 0;
+
+		scene.traverseVisible( function ( child ) {
+
+			if ( child instanceof THREE.Sprite ) {
+
+				sprites.push( child );
+
+			}
+
+		} );
 
-		if ( ! nSprites ) return;
+		if ( sprites.length === 0 ) return;
 
 		// setup gl
 
@@ -136,14 +156,10 @@ THREE.SpritePlugin = function () {
 
 		// update positions and sort
 
-		var i, sprite, material, fogType, scale = [];
+		for ( var i = 0, l = sprites.length; i < l; i ++ ) {
 
-		for( i = 0; i < nSprites; i ++ ) {
-
-			sprite = sprites[ i ];
-			material = sprite.material;
-
-			if ( sprite.visible === false ) continue;
+			var sprite = sprites[ i ];
+			var material = sprite.material;
 
 			sprite._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld );
 			sprite.z = - sprite._modelViewMatrix.elements[ 14 ];
@@ -154,13 +170,12 @@ THREE.SpritePlugin = function () {
 
 		// render all sprites
 
-		for( i = 0; i < nSprites; i ++ ) {
+		var scale = [];
 
-			sprite = sprites[ i ];
+		for ( var i = 0, l = sprites.length; i < l; i ++ ) {
 
-			if ( sprite.visible === false ) continue;
-
-			material = sprite.material;
+			var sprite = sprites[ i ];
+			var material = sprite.material;
 
 			_gl.uniform1f( uniforms.alphaTest, material.alphaTest );
 			_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
@@ -168,14 +183,12 @@ THREE.SpritePlugin = function () {
 			scale[ 0 ] = sprite.scale.x;
 			scale[ 1 ] = sprite.scale.y;
 
+			var fogType = 0;
+
 			if ( scene.fog && material.fog ) {
 
 				fogType = sceneFogType;
 
-			} else {
-
-				fogType = 0;
-
 			}
 
 			if ( oldFogType !== fogType ) {

+ 6 - 0
src/loaders/Loader.js

@@ -358,6 +358,12 @@ THREE.Loader.prototype = {
 
 		}
 
+		if ( m.mapAlpha && texturePath ) {
+
+			create_texture( mpars, 'alphaMap', m.mapAlpha, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
+
+		}
+
 		//
 
 		if ( m.mapBumpScale ) {

+ 6 - 0
src/materials/MeshBasicMaterial.js

@@ -11,6 +11,8 @@
  *
  *  specularMap: new THREE.Texture( <Image> ),
  *
+ *  alphaMap: new THREE.Texture( <Image> ),
+ *
  *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
  *  combine: THREE.Multiply,
  *  reflectivity: <float>,
@@ -45,6 +47,8 @@ THREE.MeshBasicMaterial = function ( parameters ) {
 
 	this.specularMap = null;
 
+	this.alphaMap = null;
+
 	this.envMap = null;
 	this.combine = THREE.MultiplyOperation;
 	this.reflectivity = 1;
@@ -84,6 +88,8 @@ THREE.MeshBasicMaterial.prototype.clone = function () {
 
 	material.specularMap = this.specularMap;
 
+	material.alphaMap = this.alphaMap;
+
 	material.envMap = this.envMap;
 	material.combine = this.combine;
 	material.reflectivity = this.reflectivity;

+ 6 - 0
src/materials/MeshLambertMaterial.js

@@ -14,6 +14,8 @@
  *
  *  specularMap: new THREE.Texture( <Image> ),
  *
+ *  alphaMap: new THREE.Texture( <Image> ),
+ *
  *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
  *  combine: THREE.Multiply,
  *  reflectivity: <float>,
@@ -54,6 +56,8 @@ THREE.MeshLambertMaterial = function ( parameters ) {
 
 	this.specularMap = null;
 
+	this.alphaMap = null;
+
 	this.envMap = null;
 	this.combine = THREE.MultiplyOperation;
 	this.reflectivity = 1;
@@ -99,6 +103,8 @@ THREE.MeshLambertMaterial.prototype.clone = function () {
 
 	material.specularMap = this.specularMap;
 
+	material.alphaMap = this.alphaMap;
+
 	material.envMap = this.envMap;
 	material.combine = this.combine;
 	material.reflectivity = this.reflectivity;

+ 6 - 0
src/materials/MeshPhongMaterial.js

@@ -22,6 +22,8 @@
  *
  *  specularMap: new THREE.Texture( <Image> ),
  *
+ *  alphaMap: new THREE.Texture( <Image> ),
+ *
  *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
  *  combine: THREE.Multiply,
  *  reflectivity: <float>,
@@ -72,6 +74,8 @@ THREE.MeshPhongMaterial = function ( parameters ) {
 
 	this.specularMap = null;
 
+	this.alphaMap = null;
+
 	this.envMap = null;
 	this.combine = THREE.MultiplyOperation;
 	this.reflectivity = 1;
@@ -127,6 +131,8 @@ THREE.MeshPhongMaterial.prototype.clone = function () {
 
 	material.specularMap = this.specularMap;
 
+	material.alphaMap = this.alphaMap;
+
 	material.envMap = this.envMap;
 	material.combine = this.combine;
 	material.reflectivity = this.reflectivity;

+ 8 - 1
src/materials/PointCloudMaterial.js

@@ -63,9 +63,16 @@ THREE.PointCloudMaterial.prototype.clone = function () {
 
 // backwards compatibility
 
+THREE.ParticleBasicMaterial = function ( parameters ) {
+
+	console.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointCloudMaterial.' );
+	return new THREE.PointCloudMaterial( parameters );
+
+};
+
 THREE.ParticleSystemMaterial = function ( parameters ) {
 
 	console.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointCloudMaterial.' );
 	return new THREE.PointCloudMaterial( parameters );
 
-}
+};

+ 7 - 7
src/materials/ShaderMaterial.js

@@ -2,12 +2,11 @@
  * @author alteredq / http://alteredqualia.com/
  *
  * parameters = {
- *  fragmentShader: <string>,
- *  vertexShader: <string>,
- *
+ *  defines: { "label" : "value" },
  *  uniforms: { "parameter1": { type: "f", value: 1.0 }, "parameter2": { type: "i" value2: 2 } },
  *
- *  defines: { "label" : "value" },
+ *  fragmentShader: <string>,
+ *  vertexShader: <string>,
  *
  *  shading: THREE.SmoothShading,
  *  blending: THREE.NormalBlending,
@@ -33,12 +32,13 @@ THREE.ShaderMaterial = function ( parameters ) {
 
 	THREE.Material.call( this );
 
-	this.fragmentShader = 'void main() {}';
-	this.vertexShader = 'void main() {}';
-	this.uniforms = {};
 	this.defines = {};
+	this.uniforms = {};
 	this.attributes = null;
 
+	this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
+	this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
+
 	this.shading = THREE.SmoothShading;
 
 	this.linewidth = 1;

+ 2 - 0
src/renderers/CanvasRenderer.js

@@ -782,6 +782,8 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 	function textureToPattern( texture ) {
 
+		if ( texture instanceof THREE.CompressedTexture ) return;
+
 		var repeatX = texture.wrapS === THREE.RepeatWrapping;
 		var repeatY = texture.wrapT === THREE.RepeatWrapping;
 

File diff suppressed because it is too large
+ 310 - 294
src/renderers/WebGLRenderer.js


+ 1 - 1739
src/renderers/shaders/ShaderChunk.js

@@ -1,1739 +1 @@
-/**
- * Shader chunks for WebLG Shader library
- *
- * @author alteredq / http://alteredqualia.com/
- * @author mrdoob / http://mrdoob.com/
- * @author mikael emtinger / http://gomo.se/
- */
-
-THREE.ShaderChunk = {
-
-	// FOG
-
-	fog_pars_fragment: [
-
-		"#ifdef USE_FOG",
-
-		"	uniform vec3 fogColor;",
-
-		"	#ifdef FOG_EXP2",
-
-		"		uniform float fogDensity;",
-
-		"	#else",
-
-		"		uniform float fogNear;",
-		"		uniform float fogFar;",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	fog_fragment: [
-
-		"#ifdef USE_FOG",
-
-		"	#ifdef USE_LOGDEPTHBUF_EXT",
-
-		"		float depth = gl_FragDepthEXT / gl_FragCoord.w;",
-
-		"	#else",
-
-		"		float depth = gl_FragCoord.z / gl_FragCoord.w;",
-
-		"	#endif",
-
-		"	#ifdef FOG_EXP2",
-
-		"		const float LOG2 = 1.442695;",
-		"		float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );",
-		"		fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );",
-
-		"	#else",
-
-		"		float fogFactor = smoothstep( fogNear, fogFar, depth );",
-
-		"	#endif",
-
-		"	gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );",
-
-		"#endif"
-
-	].join("\n"),
-
-	// ENVIRONMENT MAP
-
-	envmap_pars_fragment: [
-
-		"#ifdef USE_ENVMAP",
-
-		"	uniform float reflectivity;",
-		"	uniform samplerCube envMap;",
-		"	uniform float flipEnvMap;",
-		"	uniform int combine;",
-
-		"	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
-
-		"		uniform bool useRefract;",
-		"		uniform float refractionRatio;",
-
-		"	#else",
-
-		"		varying vec3 vReflect;",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	envmap_fragment: [
-
-		"#ifdef USE_ENVMAP",
-
-		"	vec3 reflectVec;",
-
-		"	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
-
-		"		vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
-
-				// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations
-				// "Transforming Normal Vectors with the Inverse Transformation"
-
-		"		vec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );",
-
-		"		if ( useRefract ) {",
-
-		"			reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );",
-
-		"		} else { ",
-
-		"			reflectVec = reflect( cameraToVertex, worldNormal );",
-
-		"		}",
-
-		"	#else",
-
-		"		reflectVec = vReflect;",
-
-		"	#endif",
-
-		"	#ifdef DOUBLE_SIDED",
-
-		"		float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
-		"		vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
-
-		"	#else",
-
-		"		vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
-
-		"	#endif",
-
-		"	#ifdef GAMMA_INPUT",
-
-		"		cubeColor.xyz *= cubeColor.xyz;",
-
-		"	#endif",
-
-		"	if ( combine == 1 ) {",
-
-		"		gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
-
-		"	} else if ( combine == 2 ) {",
-
-		"		gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;",
-
-		"	} else {",
-
-		"		gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
-
-		"	}",
-
-		"#endif"
-
-	].join("\n"),
-
-	envmap_pars_vertex: [
-
-		"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
-
-		"	varying vec3 vReflect;",
-
-		"	uniform float refractionRatio;",
-		"	uniform bool useRefract;",
-
-		"#endif"
-
-	].join("\n"),
-
-	worldpos_vertex : [
-
-		"#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )",
-
-		"	#ifdef USE_SKINNING",
-
-		"		vec4 worldPosition = modelMatrix * skinned;",
-
-		"	#endif",
-
-		"	#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
-
-		"		vec4 worldPosition = modelMatrix * vec4( morphed, 1.0 );",
-
-		"	#endif",
-
-		"	#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
-
-		"		vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	envmap_vertex : [
-
-		"#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
-
-		"	vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;",
-		"	worldNormal = normalize( worldNormal );",
-
-		"	vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );",
-
-		"	if ( useRefract ) {",
-
-		"		vReflect = refract( cameraToVertex, worldNormal, refractionRatio );",
-
-		"	} else {",
-
-		"		vReflect = reflect( cameraToVertex, worldNormal );",
-
-		"	}",
-
-		"#endif"
-
-	].join("\n"),
-
-	// COLOR MAP (particles)
-
-	map_particle_pars_fragment: [
-
-		"#ifdef USE_MAP",
-
-		"	uniform sampler2D map;",
-
-		"#endif"
-
-	].join("\n"),
-
-
-	map_particle_fragment: [
-
-		"#ifdef USE_MAP",
-
-		"	gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );",
-
-		"#endif"
-
-	].join("\n"),
-
-	// COLOR MAP (triangles)
-
-	map_pars_vertex: [
-
-		"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
-
-		"	varying vec2 vUv;",
-		"	uniform vec4 offsetRepeat;",
-
-		"#endif"
-
-	].join("\n"),
-
-	map_pars_fragment: [
-
-		"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
-
-		"	varying vec2 vUv;",
-
-		"#endif",
-
-		"#ifdef USE_MAP",
-
-		"	uniform sampler2D map;",
-
-		"#endif"
-
-	].join("\n"),
-
-	map_vertex: [
-
-		"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
-
-		"	vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
-
-		"#endif"
-
-	].join("\n"),
-
-	map_fragment: [
-
-		"#ifdef USE_MAP",
-
-		"	vec4 texelColor = texture2D( map, vUv );",
-
-		"	#ifdef GAMMA_INPUT",
-
-		"		texelColor.xyz *= texelColor.xyz;",
-
-		"	#endif",
-
-		"	gl_FragColor = gl_FragColor * texelColor;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// LIGHT MAP
-
-	lightmap_pars_fragment: [
-
-		"#ifdef USE_LIGHTMAP",
-
-		"	varying vec2 vUv2;",
-		"	uniform sampler2D lightMap;",
-
-		"#endif"
-
-	].join("\n"),
-
-	lightmap_pars_vertex: [
-
-		"#ifdef USE_LIGHTMAP",
-
-		"	varying vec2 vUv2;",
-
-		"#endif"
-
-	].join("\n"),
-
-	lightmap_fragment: [
-
-		"#ifdef USE_LIGHTMAP",
-
-		"	gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );",
-
-		"#endif"
-
-	].join("\n"),
-
-	lightmap_vertex: [
-
-		"#ifdef USE_LIGHTMAP",
-
-		"	vUv2 = uv2;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// BUMP MAP
-
-	bumpmap_pars_fragment: [
-
-		"#ifdef USE_BUMPMAP",
-
-		"	uniform sampler2D bumpMap;",
-		"	uniform float bumpScale;",
-
-			// Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
-			//	http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
-
-			// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
-
-		"	vec2 dHdxy_fwd() {",
-
-		"		vec2 dSTdx = dFdx( vUv );",
-		"		vec2 dSTdy = dFdy( vUv );",
-
-		"		float Hll = bumpScale * texture2D( bumpMap, vUv ).x;",
-		"		float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;",
-		"		float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;",
-
-		"		return vec2( dBx, dBy );",
-
-		"	}",
-
-		"	vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {",
-
-		"		vec3 vSigmaX = dFdx( surf_pos );",
-		"		vec3 vSigmaY = dFdy( surf_pos );",
-		"		vec3 vN = surf_norm;",		// normalized
-
-		"		vec3 R1 = cross( vSigmaY, vN );",
-		"		vec3 R2 = cross( vN, vSigmaX );",
-
-		"		float fDet = dot( vSigmaX, R1 );",
-
-		"		vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );",
-		"		return normalize( abs( fDet ) * surf_norm - vGrad );",
-
-		"	}",
-
-		"#endif"
-
-	].join("\n"),
-
-	// NORMAL MAP
-
-	normalmap_pars_fragment: [
-
-		"#ifdef USE_NORMALMAP",
-
-		"	uniform sampler2D normalMap;",
-		"	uniform vec2 normalScale;",
-
-			// Per-Pixel Tangent Space Normal Mapping
-			// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
-
-		"	vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {",
-
-		"		vec3 q0 = dFdx( eye_pos.xyz );",
-		"		vec3 q1 = dFdy( eye_pos.xyz );",
-		"		vec2 st0 = dFdx( vUv.st );",
-		"		vec2 st1 = dFdy( vUv.st );",
-
-		"		vec3 S = normalize( q0 * st1.t - q1 * st0.t );",
-		"		vec3 T = normalize( -q0 * st1.s + q1 * st0.s );",
-		"		vec3 N = normalize( surf_norm );",
-
-		"		vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;",
-		"		mapN.xy = normalScale * mapN.xy;",
-		"		mat3 tsn = mat3( S, T, N );",
-		"		return normalize( tsn * mapN );",
-
-		"	}",
-
-		"#endif"
-
-	].join("\n"),
-
-	// SPECULAR MAP
-
-	specularmap_pars_fragment: [
-
-		"#ifdef USE_SPECULARMAP",
-
-		"	uniform sampler2D specularMap;",
-
-		"#endif"
-
-	].join("\n"),
-
-	specularmap_fragment: [
-
-		"float specularStrength;",
-
-		"#ifdef USE_SPECULARMAP",
-
-		"	vec4 texelSpecular = texture2D( specularMap, vUv );",
-		"	specularStrength = texelSpecular.r;",
-
-		"#else",
-
-		"	specularStrength = 1.0;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// LIGHTS LAMBERT
-
-	lights_lambert_pars_vertex: [
-
-		"uniform vec3 ambient;",
-		"uniform vec3 diffuse;",
-		"uniform vec3 emissive;",
-
-		"uniform vec3 ambientLightColor;",
-
-		"#if MAX_DIR_LIGHTS > 0",
-
-		"	uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
-		"	uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_HEMI_LIGHTS > 0",
-
-		"	uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
-		"	uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
-		"	uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_POINT_LIGHTS > 0",
-
-		"	uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
-		"	uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
-		"	uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_SPOT_LIGHTS > 0",
-
-		"	uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
-		"	uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
-		"	uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
-		"	uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
-		"	uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];",
-		"	uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
-
-		"#endif",
-
-		"#ifdef WRAP_AROUND",
-
-		"	uniform vec3 wrapRGB;",
-
-		"#endif"
-
-	].join("\n"),
-
-	lights_lambert_vertex: [
-
-		"vLightFront = vec3( 0.0 );",
-
-		"#ifdef DOUBLE_SIDED",
-
-		"	vLightBack = vec3( 0.0 );",
-
-		"#endif",
-
-		"transformedNormal = normalize( transformedNormal );",
-
-		"#if MAX_DIR_LIGHTS > 0",
-
-		"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
-
-		"	vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
-		"	vec3 dirVector = normalize( lDirection.xyz );",
-
-		"	float dotProduct = dot( transformedNormal, dirVector );",
-		"	vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );",
-
-		"	#ifdef DOUBLE_SIDED",
-
-		"		vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
-
-		"		#ifdef WRAP_AROUND",
-
-		"			vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
-
-		"		#endif",
-
-		"	#endif",
-
-		"	#ifdef WRAP_AROUND",
-
-		"		vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
-		"		directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );",
-
-		"		#ifdef DOUBLE_SIDED",
-
-		"			directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );",
-
-		"		#endif",
-
-		"	#endif",
-
-		"	vLightFront += directionalLightColor[ i ] * directionalLightWeighting;",
-
-		"	#ifdef DOUBLE_SIDED",
-
-		"		vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;",
-
-		"	#endif",
-
-		"}",
-
-		"#endif",
-
-		"#if MAX_POINT_LIGHTS > 0",
-
-		"	for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
-
-		"		vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
-		"		vec3 lVector = lPosition.xyz - mvPosition.xyz;",
-
-		"		float lDistance = 1.0;",
-		"		if ( pointLightDistance[ i ] > 0.0 )",
-		"			lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
-
-		"		lVector = normalize( lVector );",
-		"		float dotProduct = dot( transformedNormal, lVector );",
-
-		"		vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );",
-
-		"		#ifdef DOUBLE_SIDED",
-
-		"			vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
-
-		"			#ifdef WRAP_AROUND",
-
-		"				vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
-
-		"			#endif",
-
-		"		#endif",
-
-		"		#ifdef WRAP_AROUND",
-
-		"			vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
-		"			pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );",
-
-		"			#ifdef DOUBLE_SIDED",
-
-		"				pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );",
-
-		"			#endif",
-
-		"		#endif",
-
-		"		vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;",
-
-		"		#ifdef DOUBLE_SIDED",
-
-		"			vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;",
-
-		"		#endif",
-
-		"	}",
-
-		"#endif",
-
-		"#if MAX_SPOT_LIGHTS > 0",
-
-		"	for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
-
-		"		vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
-		"		vec3 lVector = lPosition.xyz - mvPosition.xyz;",
-
-		"		float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) );",
-
-		"		if ( spotEffect > spotLightAngleCos[ i ] ) {",
-
-		"			spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );",
-
-		"			float lDistance = 1.0;",
-		"			if ( spotLightDistance[ i ] > 0.0 )",
-		"				lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
-
-		"			lVector = normalize( lVector );",
-
-		"			float dotProduct = dot( transformedNormal, lVector );",
-		"			vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );",
-
-		"			#ifdef DOUBLE_SIDED",
-
-		"				vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
-
-		"				#ifdef WRAP_AROUND",
-
-		"					vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
-
-		"				#endif",
-
-		"			#endif",
-
-		"			#ifdef WRAP_AROUND",
-
-		"				vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
-		"				spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );",
-
-		"				#ifdef DOUBLE_SIDED",
-
-		"					spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );",
-
-		"				#endif",
-
-		"			#endif",
-
-		"			vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;",
-
-		"			#ifdef DOUBLE_SIDED",
-
-		"				vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;",
-
-		"			#endif",
-
-		"		}",
-
-		"	}",
-
-		"#endif",
-
-		"#if MAX_HEMI_LIGHTS > 0",
-
-		"	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
-
-		"		vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
-		"		vec3 lVector = normalize( lDirection.xyz );",
-
-		"		float dotProduct = dot( transformedNormal, lVector );",
-
-		"		float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
-		"		float hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;",
-
-		"		vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
-
-		"		#ifdef DOUBLE_SIDED",
-
-		"			vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );",
-
-		"		#endif",
-
-		"	}",
-
-		"#endif",
-
-		"vLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;",
-
-		"#ifdef DOUBLE_SIDED",
-
-		"	vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// LIGHTS PHONG
-
-	lights_phong_pars_vertex: [
-
-		"#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )",
-
-		"	varying vec3 vWorldPosition;",
-
-		"#endif"
-
-	].join("\n"),
-
-
-	lights_phong_vertex: [
-
-		"#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )",
-
-		"	vWorldPosition = worldPosition.xyz;",
-
-		"#endif"
-
-	].join("\n"),
-
-	lights_phong_pars_fragment: [
-
-		"uniform vec3 ambientLightColor;",
-
-		"#if MAX_DIR_LIGHTS > 0",
-
-		"	uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
-		"	uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_HEMI_LIGHTS > 0",
-
-		"	uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
-		"	uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
-		"	uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_POINT_LIGHTS > 0",
-
-		"	uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
-
-		"	uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
-		"	uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_SPOT_LIGHTS > 0",
-
-		"	uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
-		"	uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
-		"	uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
-		"	uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];",
-		"	uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
-
-		"	uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
-
-		"#endif",
-
-		"#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )",
-
-		"	varying vec3 vWorldPosition;",
-
-		"#endif",
-
-		"#ifdef WRAP_AROUND",
-
-		"	uniform vec3 wrapRGB;",
-
-		"#endif",
-
-		"varying vec3 vViewPosition;",
-		"varying vec3 vNormal;"
-
-	].join("\n"),
-
-	lights_phong_fragment: [
-
-		"vec3 normal = normalize( vNormal );",
-		"vec3 viewPosition = normalize( vViewPosition );",
-
-		"#ifdef DOUBLE_SIDED",
-
-		"	normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
-
-		"#endif",
-
-		"#ifdef USE_NORMALMAP",
-
-		"	normal = perturbNormal2Arb( -vViewPosition, normal );",
-
-		"#elif defined( USE_BUMPMAP )",
-
-		"	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
-
-		"#endif",
-
-		"#if MAX_POINT_LIGHTS > 0",
-
-		"	vec3 pointDiffuse = vec3( 0.0 );",
-		"	vec3 pointSpecular = vec3( 0.0 );",
-
-		"	for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
-
-		"		vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
-		"		vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
-
-		"		float lDistance = 1.0;",
-		"		if ( pointLightDistance[ i ] > 0.0 )",
-		"			lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
-
-		"		lVector = normalize( lVector );",
-
-				// diffuse
-
-		"		float dotProduct = dot( normal, lVector );",
-
-		"		#ifdef WRAP_AROUND",
-
-		"			float pointDiffuseWeightFull = max( dotProduct, 0.0 );",
-		"			float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
-
-		"			vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
-
-		"		#else",
-
-		"			float pointDiffuseWeight = max( dotProduct, 0.0 );",
-
-		"		#endif",
-
-		"		pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;",
-
-				// specular
-
-		"		vec3 pointHalfVector = normalize( lVector + viewPosition );",
-		"		float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
-		"		float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
-
-		"		float specularNormalization = ( shininess + 2.0 ) / 8.0;",
-
-		"		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );",
-		"		pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;",
-
-		"	}",
-
-		"#endif",
-
-		"#if MAX_SPOT_LIGHTS > 0",
-
-		"	vec3 spotDiffuse = vec3( 0.0 );",
-		"	vec3 spotSpecular = vec3( 0.0 );",
-
-		"	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
-
-		"		vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
-		"		vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
-
-		"		float lDistance = 1.0;",
-		"		if ( spotLightDistance[ i ] > 0.0 )",
-		"			lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
-
-		"		lVector = normalize( lVector );",
-
-		"		float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
-
-		"		if ( spotEffect > spotLightAngleCos[ i ] ) {",
-
-		"			spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );",
-
-					// diffuse
-
-		"			float dotProduct = dot( normal, lVector );",
-
-		"			#ifdef WRAP_AROUND",
-
-		"				float spotDiffuseWeightFull = max( dotProduct, 0.0 );",
-		"				float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
-
-		"				vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
-
-		"			#else",
-
-		"				float spotDiffuseWeight = max( dotProduct, 0.0 );",
-
-		"			#endif",
-
-		"			spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;",
-
-					// specular
-
-		"			vec3 spotHalfVector = normalize( lVector + viewPosition );",
-		"			float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
-		"			float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );",
-
-		"			float specularNormalization = ( shininess + 2.0 ) / 8.0;",
-
-		"			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );",
-		"			spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;",
-
-		"		}",
-
-		"	}",
-
-		"#endif",
-
-		"#if MAX_DIR_LIGHTS > 0",
-
-		"	vec3 dirDiffuse = vec3( 0.0 );",
-		"	vec3 dirSpecular = vec3( 0.0 );" ,
-
-		"	for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
-
-		"		vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
-		"		vec3 dirVector = normalize( lDirection.xyz );",
-
-				// diffuse
-
-		"		float dotProduct = dot( normal, dirVector );",
-
-		"		#ifdef WRAP_AROUND",
-
-		"			float dirDiffuseWeightFull = max( dotProduct, 0.0 );",
-		"			float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
-
-		"			vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );",
-
-		"		#else",
-
-		"			float dirDiffuseWeight = max( dotProduct, 0.0 );",
-
-		"		#endif",
-
-		"		dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;",
-
-		// specular
-
-		"		vec3 dirHalfVector = normalize( dirVector + viewPosition );",
-		"		float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
-		"		float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
-
-		/*
-		// fresnel term from skin shader
-		"		const float F0 = 0.128;",
-
-		"		float base = 1.0 - dot( viewPosition, dirHalfVector );",
-		"		float exponential = pow( base, 5.0 );",
-
-		"		float fresnel = exponential + F0 * ( 1.0 - exponential );",
-		*/
-
-		/*
-		// fresnel term from fresnel shader
-		"		const float mFresnelBias = 0.08;",
-		"		const float mFresnelScale = 0.3;",
-		"		const float mFresnelPower = 5.0;",
-
-		"		float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );",
-		*/
-
-		"		float specularNormalization = ( shininess + 2.0 ) / 8.0;",
-
-		// "		dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;",
-
-		"		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );",
-		"		dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
-
-
-		"	}",
-
-		"#endif",
-
-		"#if MAX_HEMI_LIGHTS > 0",
-
-		"	vec3 hemiDiffuse = vec3( 0.0 );",
-		"	vec3 hemiSpecular = vec3( 0.0 );" ,
-
-		"	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
-
-		"		vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
-		"		vec3 lVector = normalize( lDirection.xyz );",
-
-		// diffuse
-
-		"		float dotProduct = dot( normal, lVector );",
-		"		float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
-
-		"		vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
-
-		"		hemiDiffuse += diffuse * hemiColor;",
-
-		// specular (sky light)
-
-		"		vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
-		"		float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
-		"		float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );",
-
-		// specular (ground light)
-
-		"		vec3 lVectorGround = -lVector;",
-
-		"		vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
-		"		float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
-		"		float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );",
-
-		"		float dotProductGround = dot( normal, lVectorGround );",
-
-		"		float specularNormalization = ( shininess + 2.0 ) / 8.0;",
-
-		"		vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );",
-		"		vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );",
-		"		hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
-
-		"	}",
-
-		"#endif",
-
-		"vec3 totalDiffuse = vec3( 0.0 );",
-		"vec3 totalSpecular = vec3( 0.0 );",
-
-		"#if MAX_DIR_LIGHTS > 0",
-
-		"	totalDiffuse += dirDiffuse;",
-		"	totalSpecular += dirSpecular;",
-
-		"#endif",
-
-		"#if MAX_HEMI_LIGHTS > 0",
-
-		"	totalDiffuse += hemiDiffuse;",
-		"	totalSpecular += hemiSpecular;",
-
-		"#endif",
-
-		"#if MAX_POINT_LIGHTS > 0",
-
-		"	totalDiffuse += pointDiffuse;",
-		"	totalSpecular += pointSpecular;",
-
-		"#endif",
-
-		"#if MAX_SPOT_LIGHTS > 0",
-
-		"	totalDiffuse += spotDiffuse;",
-		"	totalSpecular += spotSpecular;",
-
-		"#endif",
-
-		"#ifdef METAL",
-
-		"	gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );",
-
-		"#else",
-
-		"	gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// VERTEX COLORS
-
-	color_pars_fragment: [
-
-		"#ifdef USE_COLOR",
-
-		"	varying vec3 vColor;",
-
-		"#endif"
-
-	].join("\n"),
-
-
-	color_fragment: [
-
-		"#ifdef USE_COLOR",
-
-		"	gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );",
-
-		"#endif"
-
-	].join("\n"),
-
-	color_pars_vertex: [
-
-		"#ifdef USE_COLOR",
-
-		"	varying vec3 vColor;",
-
-		"#endif"
-
-	].join("\n"),
-
-
-	color_vertex: [
-
-		"#ifdef USE_COLOR",
-
-		"	#ifdef GAMMA_INPUT",
-
-		"		vColor = color * color;",
-
-		"	#else",
-
-		"		vColor = color;",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	// SKINNING
-
-	skinning_pars_vertex: [
-
-		"#ifdef USE_SKINNING",
-
-		"	uniform mat4 bindMatrix;",
-		"	uniform mat4 bindMatrixInverse;",
-
-		"	#ifdef BONE_TEXTURE",
-
-		"		uniform sampler2D boneTexture;",
-		"		uniform int boneTextureWidth;",
-		"		uniform int boneTextureHeight;",
-
-		"		mat4 getBoneMatrix( const in float i ) {",
-
-		"			float j = i * 4.0;",
-		"			float x = mod( j, float( boneTextureWidth ) );",
-		"			float y = floor( j / float( boneTextureWidth ) );",
-
-		"			float dx = 1.0 / float( boneTextureWidth );",
-		"			float dy = 1.0 / float( boneTextureHeight );",
-
-		"			y = dy * ( y + 0.5 );",
-
-		"			vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );",
-		"			vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );",
-		"			vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );",
-		"			vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );",
-
-		"			mat4 bone = mat4( v1, v2, v3, v4 );",
-
-		"			return bone;",
-
-		"		}",
-
-		"	#else",
-
-		"		uniform mat4 boneGlobalMatrices[ MAX_BONES ];",
-
-		"		mat4 getBoneMatrix( const in float i ) {",
-
-		"			mat4 bone = boneGlobalMatrices[ int(i) ];",
-		"			return bone;",
-
-		"		}",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	skinbase_vertex: [
-
-		"#ifdef USE_SKINNING",
-
-		"	mat4 boneMatX = getBoneMatrix( skinIndex.x );",
-		"	mat4 boneMatY = getBoneMatrix( skinIndex.y );",
-		"	mat4 boneMatZ = getBoneMatrix( skinIndex.z );",
-		"	mat4 boneMatW = getBoneMatrix( skinIndex.w );",
-
-		"#endif"
-
-	].join("\n"),
-
-	skinning_vertex: [
-
-		"#ifdef USE_SKINNING",
-
-		"	#ifdef USE_MORPHTARGETS",
-
-		"	vec4 skinVertex = bindMatrix * vec4( morphed, 1.0 );",
-
-		"	#else",
-
-		"	vec4 skinVertex = bindMatrix * vec4( position, 1.0 );",
-
-		"	#endif",
-
-		"	vec4 skinned = vec4( 0.0 );",
-		"	skinned += boneMatX * skinVertex * skinWeight.x;",
-		"	skinned += boneMatY * skinVertex * skinWeight.y;",
-		"	skinned += boneMatZ * skinVertex * skinWeight.z;",
-		"	skinned += boneMatW * skinVertex * skinWeight.w;",
-		"	skinned  = bindMatrixInverse * skinned;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// MORPHING
-
-	morphtarget_pars_vertex: [
-
-		"#ifdef USE_MORPHTARGETS",
-
-		"	#ifndef USE_MORPHNORMALS",
-
-		"	uniform float morphTargetInfluences[ 8 ];",
-
-		"	#else",
-
-		"	uniform float morphTargetInfluences[ 4 ];",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	morphtarget_vertex: [
-
-		"#ifdef USE_MORPHTARGETS",
-
-		"	vec3 morphed = vec3( 0.0 );",
-		"	morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];",
-		"	morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];",
-		"	morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];",
-		"	morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];",
-
-		"	#ifndef USE_MORPHNORMALS",
-
-		"	morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];",
-		"	morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];",
-		"	morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];",
-		"	morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];",
-
-		"	#endif",
-
-		"	morphed += position;",
-
-		"#endif"
-
-	].join("\n"),
-
-	default_vertex : [
-
-		"vec4 mvPosition;",
-
-		"#ifdef USE_SKINNING",
-
-		"	mvPosition = modelViewMatrix * skinned;",
-
-		"#endif",
-
-		"#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )",
-
-		"	mvPosition = modelViewMatrix * vec4( morphed, 1.0 );",
-
-		"#endif",
-
-		"#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )",
-
-		"	mvPosition = modelViewMatrix * vec4( position, 1.0 );",
-
-		"#endif",
-
-		"gl_Position = projectionMatrix * mvPosition;"
-
-	].join("\n"),
-
-	morphnormal_vertex: [
-
-		"#ifdef USE_MORPHNORMALS",
-
-		"	vec3 morphedNormal = vec3( 0.0 );",
-
-		"	morphedNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];",
-		"	morphedNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];",
-		"	morphedNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];",
-		"	morphedNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];",
-
-		"	morphedNormal += normal;",
-
-		"#endif"
-
-	].join("\n"),
-
-	skinnormal_vertex: [
-
-		"#ifdef USE_SKINNING",
-
-		"	mat4 skinMatrix = mat4( 0.0 );",
-		"	skinMatrix += skinWeight.x * boneMatX;",
-		"	skinMatrix += skinWeight.y * boneMatY;",
-		"	skinMatrix += skinWeight.z * boneMatZ;",
-		"	skinMatrix += skinWeight.w * boneMatW;",
-		"	skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;",
-
-		"	#ifdef USE_MORPHNORMALS",
-
-		"	vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );",
-
-		"	#else",
-
-		"	vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	defaultnormal_vertex: [
-
-		"vec3 objectNormal;",
-
-		"#ifdef USE_SKINNING",
-
-		"	objectNormal = skinnedNormal.xyz;",
-
-		"#endif",
-
-		"#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )",
-
-		"	objectNormal = morphedNormal;",
-
-		"#endif",
-
-		"#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )",
-
-		"	objectNormal = normal;",
-
-		"#endif",
-
-		"#ifdef FLIP_SIDED",
-
-		"	objectNormal = -objectNormal;",
-
-		"#endif",
-
-		"vec3 transformedNormal = normalMatrix * objectNormal;"
-
-	].join("\n"),
-
-	// SHADOW MAP
-
-	// based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
-	// http://spidergl.org/example.php?id=6
-	// http://fabiensanglard.net/shadowmapping
-
-	shadowmap_pars_fragment: [
-
-		"#ifdef USE_SHADOWMAP",
-
-		"	uniform sampler2D shadowMap[ MAX_SHADOWS ];",
-		"	uniform vec2 shadowMapSize[ MAX_SHADOWS ];",
-
-		"	uniform float shadowDarkness[ MAX_SHADOWS ];",
-		"	uniform float shadowBias[ MAX_SHADOWS ];",
-
-		"	varying vec4 vShadowCoord[ MAX_SHADOWS ];",
-
-		"	float unpackDepth( const in vec4 rgba_depth ) {",
-
-		"		const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );",
-		"		float depth = dot( rgba_depth, bit_shift );",
-		"		return depth;",
-
-		"	}",
-
-		"#endif"
-
-	].join("\n"),
-
-	shadowmap_fragment: [
-
-		"#ifdef USE_SHADOWMAP",
-
-		"	#ifdef SHADOWMAP_DEBUG",
-
-		"		vec3 frustumColors[3];",
-		"		frustumColors[0] = vec3( 1.0, 0.5, 0.0 );",
-		"		frustumColors[1] = vec3( 0.0, 1.0, 0.8 );",
-		"		frustumColors[2] = vec3( 0.0, 0.5, 1.0 );",
-
-		"	#endif",
-
-		"	#ifdef SHADOWMAP_CASCADE",
-
-		"		int inFrustumCount = 0;",
-
-		"	#endif",
-
-		"	float fDepth;",
-		"	vec3 shadowColor = vec3( 1.0 );",
-
-		"	for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
-
-		"		vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
-
-				// "if ( something && something )" breaks ATI OpenGL shader compiler
-				// "if ( all( something, something ) )" using this instead
-
-		"		bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );",
-		"		bool inFrustum = all( inFrustumVec );",
-
-				// don't shadow pixels outside of light frustum
-				// use just first frustum (for cascades)
-				// don't shadow pixels behind far plane of light frustum
-
-		"		#ifdef SHADOWMAP_CASCADE",
-
-		"			inFrustumCount += int( inFrustum );",
-		"			bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );",
-
-		"		#else",
-
-		"			bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );",
-
-		"		#endif",
-
-		"		bool frustumTest = all( frustumTestVec );",
-
-		"		if ( frustumTest ) {",
-
-		"			shadowCoord.z += shadowBias[ i ];",
-
-		"			#if defined( SHADOWMAP_TYPE_PCF )",
-
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
-
-		"				float shadow = 0.0;",
-
-		/*
-						// nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
-						// must enroll loop manually
-
-		"				for ( float y = -1.25; y <= 1.25; y += 1.25 )",
-		"					for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
-
-		"						vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
-
-								// doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
-								//"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
-
-		"						float fDepth = unpackDepth( rgbaDepth );",
-
-		"						if ( fDepth < shadowCoord.z )",
-		"							shadow += 1.0;",
-
-		"				}",
-
-		"				shadow /= 9.0;",
-
-		*/
-
-		"				const float shadowDelta = 1.0 / 9.0;",
-
-		"				float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
-		"				float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
-
-		"				float dx0 = -1.25 * xPixelOffset;",
-		"				float dy0 = -1.25 * yPixelOffset;",
-		"				float dx1 = 1.25 * xPixelOffset;",
-		"				float dy1 = 1.25 * yPixelOffset;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
-		"				if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
-
-		"				shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
-
-		"			#elif defined( SHADOWMAP_TYPE_PCF_SOFT )",
-
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
-
-		"				float shadow = 0.0;",
-
-		"				float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
-		"				float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
-
-		"				float dx0 = -1.0 * xPixelOffset;",
-		"				float dy0 = -1.0 * yPixelOffset;",
-		"				float dx1 = 1.0 * xPixelOffset;",
-		"				float dy1 = 1.0 * yPixelOffset;",
-
-		"				mat3 shadowKernel;",
-		"				mat3 depthKernel;",
-
-		"				depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
-		"				depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
-		"				depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
-		"				depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
-		"				depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
-		"				depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
-		"				depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
-		"				depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
-		"				depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
-
-		"				vec3 shadowZ = vec3( shadowCoord.z );",
-		"				shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));",
-		"				shadowKernel[0] *= vec3(0.25);",
-
-		"				shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));",
-		"				shadowKernel[1] *= vec3(0.25);",
-
-		"				shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));",
-		"				shadowKernel[2] *= vec3(0.25);",
-
-		"				vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );",
-
-		"				shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );",
-		"				shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );",
-
-		"				vec4 shadowValues;",
-		"				shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );",
-		"				shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );",
-		"				shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );",
-		"				shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );",
-
-		"				shadow = dot( shadowValues, vec4( 1.0 ) );",
-
-		"				shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
-
-		"			#else",
-
-		"				vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
-		"				float fDepth = unpackDepth( rgbaDepth );",
-
-		"				if ( fDepth < shadowCoord.z )",
-
-		// spot with multiple shadows is darker
-
-		"					shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );",
-
-		// spot with multiple shadows has the same color as single shadow spot
-
-		// "					shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );",
-
-		"			#endif",
-
-		"		}",
-
-
-		"		#ifdef SHADOWMAP_DEBUG",
-
-		"			#ifdef SHADOWMAP_CASCADE",
-
-		"				if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];",
-
-		"			#else",
-
-		"				if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];",
-
-		"			#endif",
-
-		"		#endif",
-
-		"	}",
-
-		"	#ifdef GAMMA_OUTPUT",
-
-		"		shadowColor *= shadowColor;",
-
-		"	#endif",
-
-		"	gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;",
-
-		"#endif"
-
-	].join("\n"),
-
-	shadowmap_pars_vertex: [
-
-		"#ifdef USE_SHADOWMAP",
-
-		"	varying vec4 vShadowCoord[ MAX_SHADOWS ];",
-		"	uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
-
-		"#endif"
-
-	].join("\n"),
-
-	shadowmap_vertex: [
-
-		"#ifdef USE_SHADOWMAP",
-
-		"	for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
-
-		"		vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;",
-
-		"	}",
-
-		"#endif"
-
-	].join("\n"),
-
-	// ALPHATEST
-
-	alphatest_fragment: [
-
-		"#ifdef ALPHATEST",
-
-		"	if ( gl_FragColor.a < ALPHATEST ) discard;",
-
-		"#endif"
-
-	].join("\n"),
-
-	// LINEAR SPACE
-
-	linear_to_gamma_fragment: [
-
-		"#ifdef GAMMA_OUTPUT",
-
-		"	gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
-
-		"#endif"
-
-	].join("\n"),
-
-	// LOGARITHMIC DEPTH BUFFER
-	// http://outerra.blogspot.com/2012/11/maximizing-depth-buffer-range-and.html
-
-	// WebGL doesn't support gl_FragDepth out of the box, unless the EXT_frag_depth extension is available.  On platforms
-	// without EXT_frag_depth, we have to fall back on linear z-buffer in the fragment shader, which means that some long
-	// faces close to the camera may have issues.	This can be worked around by tesselating the model more finely when
-	// the camera is near the surface.
-
-	logdepthbuf_pars_vertex: [
-
-		"#ifdef USE_LOGDEPTHBUF",
-
-		"	#ifdef USE_LOGDEPTHBUF_EXT",
-
-		"		varying float vFragDepth;",
-
-		"	#endif",
-
-		"	uniform float logDepthBufFC;",
-
-		"#endif",
-
-	].join('\n'),
-
-	logdepthbuf_vertex: [
-
-		"#ifdef USE_LOGDEPTHBUF",
-
-		"	gl_Position.z = log2(max(1e-6, gl_Position.w + 1.0)) * logDepthBufFC;",
-
-		"	#ifdef USE_LOGDEPTHBUF_EXT",
-
-		"		vFragDepth = 1.0 + gl_Position.w;",
-
-		"#else",
-
-		"		gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;",
-
-		"	#endif",
-
-		"#endif"
-
-	].join("\n"),
-
-	logdepthbuf_pars_fragment: [
-
-		"#ifdef USE_LOGDEPTHBUF",
-
-		"	uniform float logDepthBufFC;",
-
-		"	#ifdef USE_LOGDEPTHBUF_EXT",
-
-		"		#extension GL_EXT_frag_depth : enable",
-		"		varying float vFragDepth;",
-
-		"	#endif",
-
-		"#endif"
-
-	].join('\n'),
-
-	logdepthbuf_fragment: [
-
-		"#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)",
-
-		"	gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;",
-
-		"#endif"
-
-	].join("\n")
-
-};
+THREE.ShaderChunk = {};

+ 5 - 0
src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl

@@ -0,0 +1,5 @@
+#ifdef USE_ALPHAMAP
+
+	gl_FragColor.a *= texture2D( alphaMap, vUv ).g;
+
+#endif

+ 5 - 0
src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl

@@ -0,0 +1,5 @@
+#ifdef USE_ALPHAMAP
+
+	uniform sampler2D alphaMap;
+
+#endif

+ 5 - 0
src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl

@@ -0,0 +1,5 @@
+#ifdef ALPHATEST
+
+	if ( gl_FragColor.a < ALPHATEST ) discard;
+
+#endif

+ 40 - 0
src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl

@@ -0,0 +1,40 @@
+#ifdef USE_BUMPMAP
+
+	uniform sampler2D bumpMap;
+	uniform float bumpScale;
+
+			// Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
+			//	http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
+
+			// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
+
+	vec2 dHdxy_fwd() {
+
+		vec2 dSTdx = dFdx( vUv );
+		vec2 dSTdy = dFdy( vUv );
+
+		float Hll = bumpScale * texture2D( bumpMap, vUv ).x;
+		float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;
+		float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;
+
+		return vec2( dBx, dBy );
+
+	}
+
+	vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {
+
+		vec3 vSigmaX = dFdx( surf_pos );
+		vec3 vSigmaY = dFdy( surf_pos );
+		vec3 vN = surf_norm;		// normalized
+
+		vec3 R1 = cross( vSigmaY, vN );
+		vec3 R2 = cross( vN, vSigmaX );
+
+		float fDet = dot( vSigmaX, R1 );
+
+		vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
+		return normalize( abs( fDet ) * surf_norm - vGrad );
+
+	}
+
+#endif

+ 5 - 0
src/renderers/shaders/ShaderChunk/color_fragment.glsl

@@ -0,0 +1,5 @@
+#ifdef USE_COLOR
+
+	gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );
+
+#endif

+ 5 - 0
src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl

@@ -0,0 +1,5 @@
+#ifdef USE_COLOR
+
+	varying vec3 vColor;
+
+#endif

+ 5 - 0
src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl

@@ -0,0 +1,5 @@
+#ifdef USE_COLOR
+
+	varying vec3 vColor;
+
+#endif

+ 13 - 0
src/renderers/shaders/ShaderChunk/color_vertex.glsl

@@ -0,0 +1,13 @@
+#ifdef USE_COLOR
+
+	#ifdef GAMMA_INPUT
+
+		vColor = color * color;
+
+	#else
+
+		vColor = color;
+
+	#endif
+
+#endif

+ 21 - 0
src/renderers/shaders/ShaderChunk/default_vertex.glsl

@@ -0,0 +1,21 @@
+vec4 mvPosition;
+
+#ifdef USE_SKINNING
+
+	mvPosition = modelViewMatrix * skinned;
+
+#endif
+
+#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )
+
+	mvPosition = modelViewMatrix * vec4( morphed, 1.0 );
+
+#endif
+
+#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )
+
+	mvPosition = modelViewMatrix * vec4( position, 1.0 );
+
+#endif
+
+gl_Position = projectionMatrix * mvPosition;

+ 27 - 0
src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl

@@ -0,0 +1,27 @@
+vec3 objectNormal;
+
+#ifdef USE_SKINNING
+
+	objectNormal = skinnedNormal.xyz;
+
+#endif
+
+#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )
+
+	objectNormal = morphedNormal;
+
+#endif
+
+#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )
+
+	objectNormal = normal;
+
+#endif
+
+#ifdef FLIP_SIDED
+
+	objectNormal = -objectNormal;
+
+#endif
+
+vec3 transformedNormal = normalMatrix * objectNormal;

+ 61 - 0
src/renderers/shaders/ShaderChunk/envmap_fragment.glsl

@@ -0,0 +1,61 @@
+#ifdef USE_ENVMAP
+
+	vec3 reflectVec;
+
+	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )
+
+		vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );
+
+		// http://en.wikibooks.org/wiki/GLSL_Programming/Applying_Matrix_Transformations
+		// Transforming Normal Vectors with the Inverse Transformation
+
+		vec3 worldNormal = normalize( vec3( vec4( normal, 0.0 ) * viewMatrix ) );
+
+		if ( useRefract ) {
+
+			reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );
+
+		} else { 
+
+			reflectVec = reflect( cameraToVertex, worldNormal );
+
+		}
+
+	#else
+
+		reflectVec = vReflect;
+
+	#endif
+
+	#ifdef DOUBLE_SIDED
+
+		float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );
+		vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
+
+	#else
+
+		vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
+
+	#endif
+
+	#ifdef GAMMA_INPUT
+
+		cubeColor.xyz *= cubeColor.xyz;
+
+	#endif
+
+	if ( combine == 1 ) {
+
+		gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );
+
+	} else if ( combine == 2 ) {
+
+		gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;
+
+	} else {
+
+		gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );
+
+	}
+
+#endif

+ 19 - 0
src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl

@@ -0,0 +1,19 @@
+#ifdef USE_ENVMAP
+
+	uniform float reflectivity;
+	uniform samplerCube envMap;
+	uniform float flipEnvMap;
+	uniform int combine;
+
+	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )
+
+		uniform bool useRefract;
+		uniform float refractionRatio;
+
+	#else
+
+		varying vec3 vReflect;
+
+	#endif
+
+#endif

+ 8 - 0
src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl

@@ -0,0 +1,8 @@
+#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )
+
+	varying vec3 vReflect;
+
+	uniform float refractionRatio;
+	uniform bool useRefract;
+
+#endif

+ 18 - 0
src/renderers/shaders/ShaderChunk/envmap_vertex.glsl

@@ -0,0 +1,18 @@
+#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )
+
+	vec3 worldNormal = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;
+	worldNormal = normalize( worldNormal );
+
+	vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );
+
+	if ( useRefract ) {
+
+		vReflect = refract( cameraToVertex, worldNormal, refractionRatio );
+
+	} else {
+
+		vReflect = reflect( cameraToVertex, worldNormal );
+
+	}
+
+#endif

+ 27 - 0
src/renderers/shaders/ShaderChunk/fog_fragment.glsl

@@ -0,0 +1,27 @@
+#ifdef USE_FOG
+
+	#ifdef USE_LOGDEPTHBUF_EXT
+
+		float depth = gl_FragDepthEXT / gl_FragCoord.w;
+
+	#else
+
+		float depth = gl_FragCoord.z / gl_FragCoord.w;
+
+	#endif
+
+	#ifdef FOG_EXP2
+
+		const float LOG2 = 1.442695;
+		float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );
+		fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );
+
+	#else
+
+		float fogFactor = smoothstep( fogNear, fogFar, depth );
+
+	#endif
+	
+	gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );
+
+#endif

+ 15 - 0
src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl

@@ -0,0 +1,15 @@
+#ifdef USE_FOG
+
+	uniform vec3 fogColor;
+
+	#ifdef FOG_EXP2
+
+		uniform float fogDensity;
+
+	#else
+
+		uniform float fogNear;
+		uniform float fogFar;
+	#endif
+
+#endif

+ 5 - 0
src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl

@@ -0,0 +1,5 @@
+#ifdef USE_LIGHTMAP
+
+	gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );
+
+#endif

+ 6 - 0
src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl

@@ -0,0 +1,6 @@
+#ifdef USE_LIGHTMAP
+
+	varying vec2 vUv2;
+	uniform sampler2D lightMap;
+
+#endif

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