浏览代码

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

Conflicts:
	editor/js/Loader.js
Daniel 9 年之前
父节点
当前提交
49d091453a
共有 43 个文件被更改,包括 1599 次插入980 次删除
  1. 122 190
      build/three.js
  2. 60 65
      build/three.min.js
  3. 77 89
      docs/api/loaders/JSONLoader.html
  4. 1 1
      docs/api/math/Matrix4.html
  5. 3 1
      editor/index.html
  6. 25 8
      editor/js/Loader.js
  7. 2 2
      examples/canvas_interactive_cubes.html
  8. 2 2
      examples/canvas_interactive_cubes_tween.html
  9. 2 2
      examples/canvas_interactive_voxelpainter.html
  10. 3 5
      examples/js/loaders/AMFLoader.js
  11. 3 5
      examples/js/loaders/ColladaLoader.js
  12. 664 0
      examples/js/loaders/ColladaLoader2.js
  13. 54 0
      examples/js/loaders/KMZLoader.js
  14. 0 5
      examples/js/postprocessing/GlitchPass.js
  15. 1 0
      examples/misc_controls_pointerlock.html
  16. 0 0
      examples/models/md2/ratamahatta/w_chaingun.md2
  17. 0 1
      examples/webgl_geometry_extrude_splines.html
  18. 2 3
      examples/webgl_geometry_terrain_raycast.html
  19. 1 1
      examples/webgl_interactive_raycasting_points.html
  20. 33 33
      examples/webgl_shadowmap_pointlight.html
  21. 25 1
      src/Three.js
  22. 3 3
      src/cameras/CubeCamera.js
  23. 16 1
      src/core/BufferGeometry.js
  24. 2 10
      src/core/Clock.js
  25. 49 16
      src/core/Object3D.js
  26. 0 10
      src/lights/AmbientLight.js
  27. 0 11
      src/lights/DirectionalLight.js
  28. 0 12
      src/lights/HemisphereLight.js
  29. 21 4
      src/lights/Light.js
  30. 0 13
      src/lights/PointLight.js
  31. 0 14
      src/lights/SpotLight.js
  32. 8 0
      src/loaders/ImageLoader.js
  33. 6 4
      src/loaders/ObjectLoader.js
  34. 0 25
      src/objects/Line.js
  35. 0 25
      src/objects/Mesh.js
  36. 0 25
      src/objects/Points.js
  37. 0 17
      src/objects/Sprite.js
  38. 165 29
      src/renderers/WebGLRenderTarget.js
  39. 61 37
      src/renderers/WebGLRenderer.js
  40. 175 231
      src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl
  41. 0 24
      src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl
  42. 0 32
      src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl
  43. 13 23
      src/renderers/webgl/WebGLShadowMap.js

文件差异内容过多而无法显示
+ 122 - 190
build/three.js


文件差异内容过多而无法显示
+ 60 - 65
build/three.min.js


+ 77 - 89
docs/api/loaders/JSONLoader.html

@@ -1,90 +1,78 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
+<!DOCTYPE html>
+<html lang="en">
+	<head>
 		<meta charset="utf-8" />
-		<base href="../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		[page:Loader] &rarr;
-		<h1>[name]</h1>
-
-		<div class="desc">A loader for loading objects in JSON format.</div>
-
-
-		<h2>Constructor</h2>
-
-		<h3>[name]()</h3>
-		<div>
-		Creates a new [name].
-		</div>
-
-
-		<h2>Properties</h2>
-
-		<h3>[property:boolean withCredentials]</h3>
-		<div>
-		If true, the ajax request will use cookies.
-		</div>
-
-
-		<h2>Methods</h2>
-
-		<h3>[method:null load]( [page:String url], [page:Function callback], [page:String texturePath] )</h3>
-		<div>
-		[page:String url] — required<br />
-		[page:Function callback] — required. Will be called when load completes. The arguments will be the loaded [page:Object3D] and the loaded [page:Array materials].<br />
-		[page:String texturePath] — optional. If not specified, textures will be assumed to be in the same folder as the Javascript model file.
-		</div>
-
-		<h3>[method:null loadAjaxJSON]([page:JSONLoader context], [page:String url], [page:Function callback], [page:String texturePath], [page:Function callbackProgress])</h3>
-		<div>
-		[page:JSONLoader context] — The [page:JSONLoader] instance<br />
-		[page:String url] — required<br />
-		[page:Function callback] — required. This function will be called with the loaded model as an instance of [page:Geometry geometry] when the load is completed.<br />
-		[page:String texturePath] — Base path for textures.<br />
-		[page:Function callbackProgress] — Will be called while load progresses. The argument will be an [page:Object] containing two attributes: .[page:Integer total] and .[page:Integer loaded] bytes.
-		</div>
-		<div>
-		Begin loading from url and call <em>callback</em> with the parsed response content.
-		</div>
-
-		<h3>[method:Object3D parse]( [page:Object json], [page:String texturePath] )</h3>
-		<div>
-		[page:String json] — JSON object to parse.<br />
-		[page:String texturePath] — Base path for textures.
-		</div>
-		<div>
-		Parse a <em>JSON</em> structure and return an [page:Object] containing the parsed .[page:Geometry] and .[page:Array materials].
-		</div>
-
-
-		<h2>Example</h2>
-
-		<code>
-		// instantiate a loader
-		var loader = new THREE.JSONLoader();
-
-		// load a resource
-		loader.load(
-			// resource URL
-			'models/animated/monster/monster.js',
-			// Function when resource is loaded
-			function ( geometry, materials ) {
-				var material = new THREE.MeshFaceMaterial( materials );
-				var object = new THREE.Mesh( geometry, material );
-				scene.add( object );
-			}
-		);
-		</code>
-
-		[example:webgl_loader_json_blender]
-
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-	</body>
-</html>
+		<base href="../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Loader] &rarr;
+		<h1>[name]</h1>
+
+		<div class="desc">A loader for loading objects in JSON format.</div>
+
+
+		<h2>Constructor</h2>
+
+		<h3>[name]()</h3>
+		<div>
+		Creates a new [name].
+		</div>
+
+
+		<h2>Properties</h2>
+
+		<h3>[property:boolean withCredentials]</h3>
+		<div>
+		If true, the ajax request will use cookies.
+		</div>
+
+
+		<h2>Methods</h2>
+
+		<h3>[method:null load]( [page:String url], [page:Function callback], [page:String texturePath] )</h3>
+		<div>
+		[page:String url] — required<br />
+		[page:Function callback] — required. Will be called when load completes. The arguments will be the loaded [page:Object3D] and the loaded [page:Array materials].<br />
+		[page:String texturePath] — optional. If not specified, textures will be assumed to be in the same folder as the Javascript model file.
+		</div>
+
+		<h3>[method:Object3D parse]( [page:Object json], [page:String texturePath] )</h3>
+		<div>
+		[page:String json] — JSON object to parse.<br />
+		[page:String texturePath] — Base path for textures.
+		</div>
+		<div>
+		Parse a <em>JSON</em> structure and return an [page:Object] containing the parsed .[page:Geometry] and .[page:Array materials].
+		</div>
+
+
+		<h2>Example</h2>
+
+		<code>
+		// instantiate a loader
+		var loader = new THREE.JSONLoader();
+
+		// load a resource
+		loader.load(
+			// resource URL
+			'models/animated/monster/monster.js',
+			// Function when resource is loaded
+			function ( geometry, materials ) {
+				var material = new THREE.MeshFaceMaterial( materials );
+				var object = new THREE.Mesh( geometry, material );
+				scene.add( object );
+			}
+		);
+		</code>
+
+		[example:webgl_loader_json_blender]
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

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

@@ -223,7 +223,7 @@
 		Creates a perspective projection matrix.
 		</div>
 
-		<h3>[method:Matrix4 makeOrthographic]( [page:Float left], [page:Float right], [page:Float bottom], [page:Float top], [page:Float near], [page:Float far] ) [page:Matrix4 this]</h3>
+		<h3>[method:Matrix4 makeOrthographic]( [page:Float left], [page:Float right], [page:Float top], [page:Float bottom], [page:Float near], [page:Float far] ) [page:Matrix4 this]</h3>
 		<div>
 		Creates an orthographic projection matrix.
 		</div>

+ 3 - 1
editor/index.html

@@ -14,10 +14,13 @@
 
 		<script src="../examples/js/controls/EditorControls.js"></script>
 		<script src="../examples/js/controls/TransformControls.js"></script>
+
+		<script src="../examples/js/libs/jszip.min.js"></script>
 		<script src="../examples/js/loaders/AMFLoader.js"></script>
 		<script src="../examples/js/loaders/AWDLoader.js"></script>
 		<script src="../examples/js/loaders/BabylonLoader.js"></script>
 		<script src="../examples/js/loaders/ColladaLoader.js"></script>
+		<script src="../examples/js/loaders/KMZLoader.js"></script>
 		<script src="../examples/js/loaders/MD2Loader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
@@ -68,7 +71,6 @@
 		<script src="js/libs/ternjs/doc_comment.js"></script>
 		<script src="js/libs/tern-threejs/threejs.js"></script>
 
-		<script src="../examples/js/libs/jszip.min.js"></script>
 		<script src="js/libs/sortable.min.js"></script>
 		<script src="js/libs/signals.min.js"></script>
 		<script src="js/libs/ui.js"></script>

+ 25 - 8
editor/js/Loader.js

@@ -127,11 +127,8 @@ var Loader = function ( editor ) {
 
 					var contents = event.target.result;
 
-					var parser = new DOMParser();
-					var xml = parser.parseFromString( contents, 'text/xml' );
-
 					var loader = new THREE.ColladaLoader();
-					var collada = loader.parse( xml );
+					var collada = loader.parse( contents );
 
 					collada.scene.name = filename;
 
@@ -200,6 +197,25 @@ var Loader = function ( editor ) {
 
 				break;
 
+
+				case 'kmz':
+
+					var reader = new FileReader();
+					reader.addEventListener( 'load', function ( event ) {
+
+						var loader = new THREE.KMZLoader();
+						var collada = loader.parse( event.target.result );
+
+						collada.scene.name = filename;
+
+						editor.execute( new CmdAddObject( collada.scene ) );
+						editor.select( collada.scene );
+
+					}, false );
+					reader.readAsArrayBuffer( file );
+
+					break;
+
 				case 'md2':
 
 					var reader = new FileReader();
@@ -213,11 +229,12 @@ var Loader = function ( editor ) {
 							morphNormals: true
 						} );
 
-						var object = new THREE.MorphAnimMesh( geometry, material );
-						object.name = filename;
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.mixer = new THREE.AnimationMixer( mesh )
+						mesh.name = filename;
 
-						editor.execute( new CmdAddObject( object ) );
-						editor.select( object );
+						editor.execute( new CmdAddObject( mesh ) );
+						editor.select( mesh );
 
 					}, false );
 					reader.readAsArrayBuffer( file );

+ 2 - 2
examples/canvas_interactive_cubes.html

@@ -139,8 +139,8 @@
 
 				event.preventDefault();
 
-				mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
-				mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
+				mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
+				mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
 
 				raycaster.setFromCamera( mouse, camera );
 

+ 2 - 2
examples/canvas_interactive_cubes_tween.html

@@ -119,8 +119,8 @@
 
 				event.preventDefault();
 
-				mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
-				mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
+				mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
+				mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
 
 				raycaster.setFromCamera( mouse, camera );
 

+ 2 - 2
examples/canvas_interactive_voxelpainter.html

@@ -141,8 +141,8 @@
 
 				event.preventDefault();
 
-				mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
-				mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
+				mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
+				mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
 
 				raycaster.setFromCamera( mouse, camera );
 

+ 3 - 5
examples/js/loaders/AMFLoader.js

@@ -36,11 +36,9 @@ THREE.AMFLoader.prototype = {
 		var loader = new THREE.XHRLoader( scope.manager );
 		loader.setCrossOrigin( this.crossOrigin );
 		loader.setResponseType( 'arraybuffer' );
-
 		loader.load( url, function( text ) {
 
-			var amfObject = scope.parse( text );
-			onLoad( amfObject );
+			onLoad( scope.parse( text ) );
 
 		}, onProgress, onError );
 
@@ -77,7 +75,7 @@ THREE.AMFLoader.prototype = {
 
 				for ( file in zip.files ) {
 
-					if ( file.toLowerCase().endsWith( ".amf" ) ) {
+					if ( file.toLowerCase().substr( - 4 ) === '.amf' ) {
 
 						break;
 
@@ -299,7 +297,7 @@ THREE.AMFLoader.prototype = {
 							normalArray.push(nz);
 
 						}
-						
+
 						vNode = vNode.nextElementSibling;
 
 					}

+ 3 - 5
examples/js/loaders/ColladaLoader.js

@@ -100,9 +100,7 @@
 					parts.pop();
 					baseUrl = ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
 
-					var xmlParser = new DOMParser();
-					var responseXML = xmlParser.parseFromString( text, "application/xml" );
-					onLoad( scope.parse( responseXML, url ) );
+					onLoad( scope.parse( text, url ) );
 
 				}, onProgress, onError );
 
@@ -120,9 +118,9 @@
 
 		},
 
-		parse: function( doc ) {
+		parse: function( text ) {
 
-			COLLADA = doc;
+			COLLADA = new DOMParser().parseFromString( text, 'text/xml' );
 
 			this.parseAsset();
 			this.setUpConversion();

+ 664 - 0
examples/js/loaders/ColladaLoader2.js

@@ -0,0 +1,664 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.ColladaLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+};
+
+THREE.ColladaLoader.prototype = {
+
+	constructor: THREE.ColladaLoader,
+
+	load: function ( url, onLoad, onProgress, onError ) {
+
+		function getBaseUrl( url ) {
+
+			var parts = url.split( '/' );
+			parts.pop();
+			return ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
+
+		}
+
+		var scope = this;
+
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setCrossOrigin( scope.crossOrigin );
+		loader.load( url, function ( text ) {
+
+			onLoad( scope.parse( text, getBaseUrl( url ) ) );
+
+		}, onProgress, onError );
+
+	},
+
+	options: {
+
+		set convertUpAxis ( value ) {
+			console.log( 'ColladaLoder.options.convertUpAxis: TODO' );
+		}
+
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
+	parse: function ( text, baseUrl ) {
+
+		function parseFloats( text ) {
+
+			var parts = text.trim().split( /\s+/ );
+			var array = new Array( parts.length );
+
+			for ( var i = 0, l = parts.length; i < l; i ++ ) {
+				array[ i ] = parseFloat( parts[ i ] );
+			}
+
+			return array;
+
+		}
+
+		function parseInts( text ) {
+
+			var parts = text.trim().split( /\s+/ );
+			var array = new Array( parts.length );
+
+			for ( var i = 0, l = parts.length; i < l; i ++ ) {
+				array[ i ] = parseInt( parts[ i ] );
+			}
+
+			return array;
+
+		}
+
+		function parseId( text ) {
+
+			return text.substring( 1 );
+
+		}
+
+		// library
+
+		function buildLibrary( data, libraryName, nodeName, parser ) {
+
+			var library = xml.getElementsByTagName( libraryName )[ 0 ];
+
+			if ( library !== undefined ) {
+
+				var elements = library.getElementsByTagName( nodeName );
+
+				for ( var i = 0; i < elements.length; i ++ ) {
+
+					var element = elements[ i ];
+					data[ element.getAttribute( 'id' ) ] = parser( element );
+
+				}
+
+			}
+
+		}
+
+		// image
+
+		var imageLoader = new THREE.ImageLoader();
+
+		function parseImage( xml ) {
+
+			var url = xml.getElementsByTagName( 'init_from' )[ 0 ].textContent;
+
+			if ( baseUrl !== undefined ) url = baseUrl + url;
+
+			return imageLoader.load( url );
+
+		}
+
+		// effect
+
+		function parseEffect( xml ) {
+
+			// console.log( xml );
+
+		}
+
+		// camera
+
+		function parseCamera( xml ) {
+
+			console.log( 'ColladaLoader.parseCamera: TODO')
+
+			var camera = new THREE.PerspectiveCamera();
+			camera.name = xml.getAttribute( 'name' );
+			return camera;
+
+		}
+
+		// light
+
+		function parseLight( xml ) {
+
+			var data = {};
+
+			for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {
+
+				var child = xml.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'technique_common':
+						data = parseLightTechnique( child );
+						break;
+
+				}
+
+			}
+
+			//
+
+			var light;
+
+			switch ( data.technique ) {
+
+				case 'directional':
+					light = new THREE.DirectionalLight();
+					break;
+
+				case 'point':
+					light = new THREE.PointLight();
+					break;
+
+				case 'spot':
+					light = new THREE.SpotLight();
+					break;
+
+				case 'ambient':
+					light = new THREE.AmbientLight();
+					break;
+
+			}
+
+			if ( data.parameters.color ) light.color.copy( data.parameters.color );
+			if ( data.parameters.distance ) light.distance = data.parameters.distance;
+
+			return light;
+
+		}
+
+		function parseLightTechnique( xml ) {
+
+			var data = {};
+
+			for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {
+
+				var child = xml.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'directional':
+					case 'point':
+					case 'spot':
+					case 'ambient':
+
+						data.technique = child.nodeName;
+						data.parameters = parseLightParameters( child );
+
+				}
+
+			}
+
+			return data;
+
+		}
+
+		function parseLightParameters( xml ) {
+
+			var data = {};
+
+			for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {
+
+				var child = xml.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'color':
+						var array = parseFloats( child.textContent );
+						data.color = new THREE.Color().fromArray( array );
+						break;
+
+					case 'falloff_angle':
+						data.falloffAngle = parseFloat( child.textContent );
+						break;
+
+					case 'quadratic_attenuation':
+						var f = parseFloat( child.textContent );
+						data.distance = f ? Math.sqrt( 1 / f ) : 0;
+						break;
+
+				}
+
+			}
+
+			return data;
+
+		}
+
+		// geometry
+
+		var lineMaterial = new THREE.LineBasicMaterial();
+		var meshMaterial = new THREE.MeshPhongMaterial();
+
+		function parseGeometry( xml ) {
+
+			var data = {
+				id: xml.getAttribute( 'id' ),
+				name: xml.getAttribute( 'name' ),
+				sources: {},
+				primitives: []
+			};
+
+			var mesh = xml.getElementsByTagName( 'mesh' )[ 0 ];
+
+			for ( var i = 0; i < mesh.childNodes.length; i ++ ) {
+
+				var child = mesh.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'source':
+						data.sources[ child.getAttribute( 'id' ) ] = parseFloats( child.getElementsByTagName( 'float_array' )[ 0 ].textContent );
+						break;
+
+					case 'vertices':
+						data.sources[ child.getAttribute( 'id' ) ] = data.sources[ parseId( child.getElementsByTagName( 'input' )[ 0 ].getAttribute( 'source' ) ) ];
+						break;
+
+					case 'polygons':
+						console.log( 'ColladaLoader: Unsupported primitive type: ', child.nodeName );
+						break;
+
+					case 'lines':
+					case 'linestrips':
+					case 'polylist':
+					case 'triangles':
+						data.primitives.push( parseGeometryPrimitive( child ) );
+						break;
+
+					default:
+						console.log( child );
+
+				}
+
+			}
+
+			//
+
+			var group = new THREE.Group();
+
+			var sources = data.sources;
+			var primitives = data.primitives;
+
+			if ( primitives.length === 0 ) return group;
+
+			for ( var p = 0; p < primitives.length; p ++ ) {
+
+				var primitive = primitives[ p ];
+
+				var inputs = primitive.inputs;
+				var stride = primitive.stride;
+				var vcount = primitive.vcount;
+
+				var indices = primitive.p;
+				var vcount = primitive.vcount;
+
+				var maxcount = 0;
+
+				var geometry = new THREE.BufferGeometry();
+				if ( data.name ) geometry.name = data.name;
+
+				for ( var name in inputs ) {
+
+					var input = inputs[ name ];
+
+					var source = sources[ input.id ];
+					var offset = input.offset;
+
+					var array = [];
+
+					function pushVector( i ) {
+
+						var index = indices[ i + offset ] * 3;
+						array.push( source[ index + 0 ], source[ index + 1 ], source[ index + 2 ] );
+
+					}
+
+					if ( primitive.vcount !== undefined ) {
+
+						var index = 0;
+
+						for ( var i = 0, l = vcount.length; i < l; i ++ ) {
+
+							var count = vcount[ i ];
+
+							if ( count === 4 ) {
+
+								var a = index + stride * 0;
+								var b = index + stride * 1;
+								var c = index + stride * 2;
+								var d = index + stride * 3;
+
+								pushVector( a ); pushVector( b ); pushVector( d );
+								pushVector( b ); pushVector( c ); pushVector( d );
+
+							} else if ( count === 3 ) {
+
+								var a = index + stride * 0;
+								var b = index + stride * 1;
+								var c = index + stride * 2;
+
+								pushVector( a ); pushVector( b ); pushVector( c );
+
+							} else {
+
+								maxcount = Math.max( maxcount, count );
+
+							}
+
+							index += stride * count;
+
+						}
+
+					} else {
+
+						for ( var i = 0, l = indices.length; i < l; i += stride ) {
+
+							pushVector( i );
+
+						}
+
+					}
+
+					switch ( name )	{
+
+						case 'VERTEX':
+							geometry.addAttribute( 'position', new THREE.Float32Attribute( array, 3 ) );
+							break;
+
+						case 'NORMAL':
+							geometry.addAttribute( 'normal', new THREE.Float32Attribute( array, 3 ) );
+							break;
+
+					}
+
+				}
+
+				if ( maxcount > 0 ) {
+
+					console.log( 'ColladaLoader: Geometry', data.id, 'has faces with more than 4 vertices.' );
+
+				}
+
+				switch ( primitive.type ) {
+
+					case 'lines':
+						group.add( new THREE.LineSegments( geometry, lineMaterial ) );
+						break;
+
+					case 'linestrips':
+						group.add( new THREE.Line( geometry, lineMaterial ) );
+						break;
+
+					case 'triangles':
+					case 'polylist':
+						group.add( new THREE.Mesh( geometry, meshMaterial ) );
+						break;
+
+				}
+
+			}
+
+			// flatten
+
+			if ( group.children.length === 1 ) {
+
+				return group.children[ 0 ];
+
+			}
+
+			return group;
+
+		}
+
+		function parseGeometryPrimitive( xml ) {
+
+			var primitive = {
+				type: xml.nodeName,
+				inputs: {},
+				stride: 0
+			};
+
+			for ( var i = 0, l = xml.childNodes.length; i < l; i ++ ) {
+
+				var child = xml.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'input':
+						var id = parseId( child.getAttribute( 'source' ) );
+						var semantic = child.getAttribute( 'semantic' );
+						var offset = parseInt( child.getAttribute( 'offset' ) );
+						primitive.inputs[ semantic ] = { id: id, offset: offset };
+						primitive.stride = Math.max( primitive.stride, offset + 1 );
+						break;
+
+					case 'vcount':
+						primitive.vcount = parseInts( child.textContent );
+						break;
+
+					case 'p':
+						primitive.p = parseInts( child.textContent );
+						break;
+
+				}
+
+			}
+
+			return primitive;
+
+		}
+
+		// nodes
+
+		var matrix = new THREE.Matrix4();
+		var vector = new THREE.Vector3();
+
+		function parseNode( xml ) {
+
+			var node = {
+				name: xml.getAttribute( 'name' ),
+				matrix: new THREE.Matrix4(),
+				children: []
+			};
+
+			for ( var i = 0; i < xml.childNodes.length; i ++ ) {
+
+				var child = xml.childNodes[ i ];
+
+				if ( child.nodeType !== 1 ) continue;
+
+				switch ( child.nodeName ) {
+
+					case 'instance_camera':
+						node.camera = library.cameras[ parseId( child.getAttribute( 'url' ) ) ];
+						break;
+
+					case 'instance_light':
+						node.light = library.lights[ parseId( child.getAttribute( 'url' ) ) ];
+						break;
+
+					case 'instance_geometry':
+						node.geometry = library.geometries[ parseId( child.getAttribute( 'url' ) ) ];
+						break;
+
+					case 'instance_node':
+						node.children.push( library.nodes[ parseId( child.getAttribute( 'url' ) ) ] );
+						break;
+
+					case 'matrix':
+						var array = parseFloats( child.textContent );
+						node.matrix.multiply( matrix.fromArray( array ).transpose() ); // .transpose() when Z_UP?
+						break;
+
+					case 'node':
+						node.children.push( parseNode( child ) );
+						break;
+
+					case 'translate':
+						var array = parseFloats( child.textContent );
+						vector.fromArray( array );
+						node.matrix.multiply( matrix.makeTranslation( vector.x, vector.y, vector.z ) );
+						break;
+
+					case 'rotate':
+						var array = parseFloats( child.textContent );
+						var angle = THREE.Math.degToRad( array[ 3 ] );
+						node.matrix.multiply( matrix.makeRotationAxis( vector.fromArray( array ), angle ) );
+						break;
+
+					case 'scale':
+						var array = parseFloats( child.textContent );
+						node.matrix.scale( vector.fromArray( array ) );
+						break;
+
+					case 'extra':
+						break;
+
+					default:
+						console.log( child );
+						break;
+
+				}
+
+			}
+
+			//
+
+			var object;
+
+			if ( node.camera !== undefined ) {
+
+				object = node.camera.clone();
+
+			} else if ( node.light !== undefined) {
+
+				object = node.light.clone();
+
+			} else if ( node.geometry !== undefined ) {
+
+				object = node.geometry.clone();
+
+			} else {
+
+				object = new THREE.Group();
+
+			}
+
+			object.name = node.name;
+			node.matrix.decompose( object.position, object.quaternion, object.scale );
+
+			var children = node.children;
+
+			for ( var i = 0, l = children.length; i < l; i ++ ) {
+
+				object.add( children[ i ] );
+
+			}
+
+			return object;
+
+		}
+
+		// visual scenes
+
+		function parseVisualScene( xml ) {
+
+			var group = new THREE.Group();
+			group.name = xml.getAttribute( 'name' );
+
+			var elements = xml.getElementsByTagName( 'node' );
+
+			for ( var i = 0; i < elements.length; i ++ ) {
+
+				var element = elements[ i ];
+				group.add( parseNode( element ) );
+
+			}
+
+			return group;
+
+		}
+
+		// scenes
+
+		function parseScene( xml ) {
+
+			var scene = xml.getElementsByTagName( 'scene' )[ 0 ];
+			var instance = scene.getElementsByTagName( 'instance_visual_scene' )[ 0 ];
+			return library.visualScenes[ parseId( instance.getAttribute( 'url' ) ) ];
+
+		}
+
+		console.time( 'ColladaLoader' );
+
+		console.time( 'ColladaLoader: DOMParser' );
+
+		var xml = new DOMParser().parseFromString( text, 'text/xml' );
+
+		console.timeEnd( 'ColladaLoader: DOMParser' );
+
+		var library = {
+			images: {},
+			effects: {},
+			cameras: {},
+			lights: {},
+			geometries: {},
+			nodes: {},
+			visualScenes: {}
+		};
+
+		buildLibrary( library.images, 'library_images', 'image', parseImage );
+		buildLibrary( library.effects, 'library_effects', 'effect', parseEffect );
+		buildLibrary( library.cameras, 'library_cameras', 'camera', parseCamera );
+		buildLibrary( library.lights, 'library_lights', 'light', parseLight );
+		buildLibrary( library.geometries, 'library_geometries', 'geometry', parseGeometry );
+		buildLibrary( library.nodes, 'library_nodes', 'node', parseNode );
+		buildLibrary( library.visualScenes, 'library_visual_scenes', 'visual_scene', parseVisualScene );
+
+		var scene = parseScene( xml );
+
+		console.timeEnd( 'ColladaLoader' );
+
+		// console.log( scene );
+
+		return {
+			animations: [],
+			kinematics: { joints: [] },
+			scene: scene
+		};
+
+	}
+
+};

+ 54 - 0
examples/js/loaders/KMZLoader.js

@@ -0,0 +1,54 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.KMZLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+};
+
+THREE.KMZLoader.prototype = {
+
+	constructor: THREE.KMZLoader,
+
+	load: function ( url, onLoad, onProgress, onError ) {
+
+		var scope = this;
+
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function ( text ) {
+
+			onLoad( scope.parse( text ) );
+
+		}, onProgress, onError );
+
+	},
+
+	parse: function ( data ) {
+
+		var zip = new JSZip( data );
+
+		// console.log( zip );
+
+		for ( var name in zip.files ) {
+
+			if ( name.toLowerCase().substr( - 4 ) === '.dae' ) {
+
+				return new THREE.ColladaLoader().parse( zip.file( name ).asText() );
+
+			}
+
+		}
+
+		console.error( 'KZMLoader: Couldn\'t find .dae file.' );
+
+		return {
+			scene: new THREE.Group()
+		}
+
+	}
+
+};

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

@@ -21,8 +21,6 @@ THREE.GlitchPass = function ( dt_size ) {
 		fragmentShader: shader.fragmentShader
 	} );
 
-	console.log( this.material );
-	
 	this.enabled = true;
 	this.renderToScreen = false;
 	this.needsSwap = true;
@@ -95,7 +93,6 @@ THREE.GlitchPass.prototype = {
 	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 ++ ) {
@@ -108,8 +105,6 @@ THREE.GlitchPass.prototype = {
 		}
 		
 		var texture = new THREE.DataTexture( data_arr, dt_size, dt_size, THREE.RGBFormat, THREE.FloatType );
-		console.log( texture );
-		console.log( dt_size );
 		texture.needsUpdate = true;
 		return texture;
 

+ 1 - 0
examples/misc_controls_pointerlock.html

@@ -181,6 +181,7 @@
 			var moveBackward = false;
 			var moveLeft = false;
 			var moveRight = false;
+			var canJump = false;
 
 			var prevTime = performance.now();
 			var velocity = new THREE.Vector3();

+ 0 - 0
examples/models/md2/ratamahatta/w_chaingun.MD2 → examples/models/md2/ratamahatta/w_chaingun.md2


+ 0 - 1
examples/webgl_geometry_extrude_splines.html

@@ -105,7 +105,6 @@
 
 			var radiusSegments = parseInt(document.getElementById('radiusSegments').value);
 
-			console.log('adding tube', value, closed2, radiusSegments);
 			if (tubeMesh) parent.remove(tubeMesh);
 
 			extrudePath = splines[value];

+ 2 - 3
examples/webgl_geometry_terrain_raycast.html

@@ -252,9 +252,8 @@
 
 			function onMouseMove( event ) {
 
-				mouse.x = ( event.clientX / renderer.domElement.width ) * 2 - 1;
-				mouse.y = - ( event.clientY / renderer.domElement.height ) * 2 + 1;
-
+				mouse.x = ( event.clientX / renderer.domElement.clientWidth ) * 2 - 1;
+				mouse.y = - ( event.clientY / renderer.domElement.clientHeight ) * 2 + 1;
 				raycaster.setFromCamera( mouse, camera );
 
 				// See if the ray from the camera into the world hits one of our meshes

+ 1 - 1
examples/webgl_interactive_raycasting_points.html

@@ -271,7 +271,7 @@
 				//
 
 				raycaster = new THREE.Raycaster();
-				raycaster.params.PointCloud.threshold = threshold;
+				raycaster.params.Points.threshold = threshold;
 
 				//
 

+ 33 - 33
examples/webgl_shadowmap_pointlight.html

@@ -36,7 +36,7 @@
 			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
 
 			var camera, scene, renderer, stats;
-			var dirLight, pointLight;
+			var pointLight, pointLight2;
 			var torusKnot;
 			var cubeMaterial;
 			var wallMaterial;
@@ -67,40 +67,34 @@
 				var ambient = new THREE.AmbientLight( 0x404040 );
 				scene.add( ambient );
 
-				pointLight = new THREE.PointLight( 0xffffff );
-				pointLight.castShadow = true;
-				pointLight.shadowCameraNear = 1;
-				pointLight.shadowCameraFar = 30;
-				pointLight.shadowDarkness = 0.5;
-				// pointLight.shadowCameraVisible = true;
-				pointLight.shadowMapWidth = 2048;
-				pointLight.shadowMapHeight = 1024;
-				pointLight.shadowBias = 0.01;
-				scene.add( pointLight );
+				function createLight( color ) {
 
-				var geometry = new THREE.SphereGeometry( 0.3, 32, 32 );
-				var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
-				var sphere = new THREE.Mesh( geometry, material );
-				sphere.castShadow = false;
-				sphere.receiveShadow = false;
-				pointLight.add( sphere );
+					var pointLight = new THREE.PointLight( color );
+					pointLight.castShadow = true;
+					pointLight.shadowCameraNear = 1;
+					pointLight.shadowCameraFar = 30;
+					pointLight.shadowDarkness = 0.5;
+					// pointLight.shadowCameraVisible = true;
+					pointLight.shadowMapWidth = 2048;
+					pointLight.shadowMapHeight = 1024;
+					pointLight.shadowBias = 0.01;
 
-				/*
-				dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
-				dirLight.position.set( 0, 50, 0 );
-				dirLight.castShadow = true;
-				dirLight.shadowCameraNear = 1;
-				dirLight.shadowCameraFar = 100;
-				dirLight.shadowCameraRight = 15;
-				dirLight.shadowCameraLeft = -15;
-				dirLight.shadowCameraTop = 15;
-				dirLight.shadowCameraBottom = -15;
-				dirLight.shadowDarkness = 0.5;
-				dirLight.shadowCameraVisible = true;
-				dirLight.shadowMapWidth = 1024;
-				dirLight.shadowMapHeight = 1024;
-				scene.add( dirLight );
-				*/
+					var geometry = new THREE.SphereGeometry( 0.3, 32, 32 );
+					var material = new THREE.MeshBasicMaterial( { color: color } );
+					var sphere = new THREE.Mesh( geometry, material );
+					sphere.castShadow = false;
+					sphere.receiveShadow = false;
+					pointLight.add( sphere );
+
+					return pointLight
+
+				}
+
+				pointLight = createLight( 0xffffff );
+				scene.add( pointLight );
+
+				pointLight2 = createLight( 0xff0000 );
+				scene.add( pointLight2 );
 
 				cubeMaterial = new THREE.MeshPhongMaterial( {
 					color: 0xff0000,
@@ -227,6 +221,12 @@
 				pointLight.position.y = Math.sin( time * 1.1 ) * 9 + 5;
 				pointLight.position.z = Math.sin( time * 1.2 ) * 9;
 
+				time += 10000;
+
+				pointLight2.position.x = Math.sin( time ) * 9;
+				pointLight2.position.y = Math.sin( time * 1.1 ) * 9 + 5;
+				pointLight2.position.z = Math.sin( time * 1.2 ) * 9;
+
 				renderScene();
 
 				torusKnot.rotation.y = time * 0.1;

+ 25 - 1
src/Three.js

@@ -62,7 +62,31 @@ if ( self.requestAnimationFrame === undefined || self.cancelAnimationFrame === u
 
 		}
 
-	}() );
+	} )();
+
+}
+
+//
+
+if ( self.performance === undefined ) {
+
+	self.performance = {};
+
+}
+
+if ( self.performance.now === undefined ) {
+
+	( function () {
+
+		var start = Date.now();
+
+		self.performance.now = function () {
+
+			return Date.now() - start;
+
+		}
+
+	} )();
 
 }
 

+ 3 - 3
src/cameras/CubeCamera.js

@@ -50,9 +50,9 @@ THREE.CubeCamera = function ( near, far, cubeResolution ) {
 		if ( this.parent === null ) this.updateMatrixWorld();
 
 		var renderTarget = this.renderTarget;
-		var generateMipmaps = renderTarget.generateMipmaps;
+		var generateMipmaps = renderTarget.texture.generateMipmaps;
 
-		renderTarget.generateMipmaps = false;
+		renderTarget.texture.generateMipmaps = false;
 
 		renderTarget.activeCubeFace = 0;
 		renderer.render( scene, cameraPX, renderTarget );
@@ -69,7 +69,7 @@ THREE.CubeCamera = function ( near, far, cubeResolution ) {
 		renderTarget.activeCubeFace = 4;
 		renderer.render( scene, cameraPZ, renderTarget );
 
-		renderTarget.generateMipmaps = generateMipmaps;
+		renderTarget.texture.generateMipmaps = generateMipmaps;
 
 		renderTarget.activeCubeFace = 5;
 		renderer.render( scene, cameraNZ, renderTarget );

+ 16 - 1
src/core/BufferGeometry.js

@@ -329,7 +329,7 @@ THREE.BufferGeometry.prototype = {
 
 				var lineDistances = new THREE.Float32Attribute( geometry.lineDistances.length, 1 );
 
-				this.addAttribute( 'lineDistance',  lineDistances.copyArray( geometry.lineDistances ) );
+				this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );
 
 			}
 
@@ -434,6 +434,21 @@ THREE.BufferGeometry.prototype = {
 
 		}
 
+		if ( geometry.uvsNeedUpdate ) {
+
+				var attribute = this.attributes.uv;
+
+				if ( attribute !== undefined ) {
+
+						attribute.copyVector2sArray( geometry.uvs );
+						attribute.needsUpdate = true;
+
+				}
+
+				geometry.uvsNeedUpdate = false;
+
+		}
+
 		if ( geometry.lineDistancesNeedUpdate ) {
 
 			var attribute = this.attributes.lineDistance;

+ 2 - 10
src/core/Clock.js

@@ -18,17 +18,9 @@ THREE.Clock.prototype = {
 
 	constructor: THREE.Clock,
 
-	_now: function () {
-
-		return self.performance !== undefined && self.performance.now !== undefined
-			? self.performance.now()
-			: Date.now();
-
-	},
-
 	start: function () {
 
-		this.startTime = this._now();
+		this.startTime = self.performance.now();
 
 		this.oldTime = this.startTime;
 		this.running = true;
@@ -61,7 +53,7 @@ THREE.Clock.prototype = {
 
 		if ( this.running ) {
 
-			var newTime = this._now();
+			var newTime = self.performance.now();
 
 			diff = 0.001 * ( newTime - this.oldTime );
 			this.oldTime = newTime;

+ 49 - 16
src/core/Object3D.js

@@ -25,17 +25,17 @@ THREE.Object3D = function () {
 	var quaternion = new THREE.Quaternion();
 	var scale = new THREE.Vector3( 1, 1, 1 );
 
-	var onRotationChange = function () {
+	function onRotationChange() {
 
 		quaternion.setFromEuler( rotation, false );
 
-	};
+	}
 
-	var onQuaternionChange = function () {
+	function onQuaternionChange() {
 
 		rotation.setFromQuaternion( quaternion, undefined, false );
 
-	};
+	}
 
 	rotation.onChange( onRotationChange );
 	quaternion.onChange( onQuaternionChange );
@@ -94,7 +94,7 @@ THREE.Object3D.prototype = {
 
 	get eulerOrder () {
 
-		console.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' );
+		console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
 
 		return this.rotation.order;
 
@@ -102,7 +102,7 @@ THREE.Object3D.prototype = {
 
 	set eulerOrder ( value ) {
 
-		console.warn( 'THREE.Object3D: .eulerOrder has been moved to .rotation.order.' );
+		console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );
 
 		this.rotation.order = value;
 
@@ -126,6 +126,8 @@ THREE.Object3D.prototype = {
 
 	},
 
+	//
+
 	applyMatrix: function ( matrix ) {
 
 		this.matrix.multiplyMatrices( matrix, this.matrix );
@@ -595,8 +597,7 @@ THREE.Object3D.prototype = {
 
 		var isRootObject = ( meta === undefined );
 
-		var data = {};
-		var output = { object: data };
+		var output = {};
 
 		// meta is a hash used to collect geometries, materials.
 		// not providing it implies that this is the root object
@@ -621,22 +622,52 @@ THREE.Object3D.prototype = {
 
 		// standard Object3D serialization
 
-		data.uuid = this.uuid;
-		data.type = this.type;
+		var object = {};
+
+		object.uuid = this.uuid;
+		object.type = this.type;
+
+		if ( this.name !== '' ) object.name = this.name;
+		if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
+		if ( this.visible !== true ) object.visible = this.visible;
+
+		object.matrix = this.matrix.toArray();
 
-		if ( this.name !== '' ) data.name = this.name;
-		if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
-		if ( this.visible !== true ) data.visible = this.visible;
+		//
 
-		data.matrix = this.matrix.toArray();
+		if ( this.geometry !== undefined ) {
+
+			if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
+
+				meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON( meta );
+
+			}
+
+			object.geometry = this.geometry.uuid;
+
+		}
+
+		if ( this.material !== undefined ) {
+
+			if ( meta.materials[ this.material.uuid ] === undefined ) {
+
+				meta.materials[ this.material.uuid ] = this.material.toJSON( meta );
+
+			}
+
+			object.material = this.material.uuid;
+
+		}
+
+		//
 
 		if ( this.children.length > 0 ) {
 
-			data.children = [];
+			object.children = [];
 
 			for ( var i = 0; i < this.children.length; i ++ ) {
 
-				data.children.push( this.children[ i ].toJSON( meta ).object );
+				object.children.push( this.children[ i ].toJSON( meta ).object );
 
 			}
 
@@ -656,6 +687,8 @@ THREE.Object3D.prototype = {
 
 		}
 
+		output.object = object;
+
 		return output;
 
 		// extract data from the cache hash

+ 0 - 10
src/lights/AmbientLight.js

@@ -12,13 +12,3 @@ THREE.AmbientLight = function ( color ) {
 
 THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype );
 THREE.AmbientLight.prototype.constructor = THREE.AmbientLight;
-
-THREE.AmbientLight.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	data.object.color = this.color.getHex();
-
-	return data;
-
-};

+ 0 - 11
src/lights/DirectionalLight.js

@@ -74,14 +74,3 @@ THREE.DirectionalLight.prototype.copy = function ( source ) {
 	return this;
 
 };
-
-THREE.DirectionalLight.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	data.object.color = this.color.getHex();
-	data.object.intensity = this.intensity;
-
-	return data;
-
-};

+ 0 - 12
src/lights/HemisphereLight.js

@@ -29,15 +29,3 @@ THREE.HemisphereLight.prototype.copy = function ( source ) {
 	return this;
 
 };
-
-THREE.HemisphereLight.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	data.object.color = this.color.getHex();
-	data.object.groundColor = this.groundColor.getHex();
-	data.object.intensity = this.intensity;
-
-	return data;
-
-};

+ 21 - 4
src/lights/Light.js

@@ -17,11 +17,28 @@ THREE.Light.prototype = Object.create( THREE.Object3D.prototype );
 THREE.Light.prototype.constructor = THREE.Light;
 
 THREE.Light.prototype.copy = function ( source ) {
-	
+
 	THREE.Object3D.prototype.copy.call( this, source );
-	
+
 	this.color.copy( source.color );
-	
+
 	return this;
 
-};
+};
+
+THREE.Light.prototype.toJSON = function ( meta ) {
+
+	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.color = this.color.getHex();
+	if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
+
+	if ( this.intensity !== undefined ) data.object.intensity = this.intensity;
+	if ( this.distance !== undefined ) data.object.distance = this.distance;
+	if ( this.angle !== undefined ) data.object.angle = this.angle;
+	if ( this.decay !== undefined ) data.object.decay = this.decay;
+	if ( this.exponent !== undefined ) data.object.exponent = this.exponent;
+
+	return data;
+
+};

+ 0 - 13
src/lights/PointLight.js

@@ -68,16 +68,3 @@ THREE.PointLight.prototype.copy = function ( source ) {
 	return this;
 
 };
-
-THREE.PointLight.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	data.object.color = this.color.getHex();
-	data.object.intensity = this.intensity;
-	data.object.distance = this.distance;
-	data.object.decay = this.decay;
-
-	return data;
-
-};

+ 0 - 14
src/lights/SpotLight.js

@@ -72,19 +72,5 @@ THREE.SpotLight.prototype.copy = function ( source ) {
 	this.shadowMapHeight = source.shadowMapHeight;
 
 	return this;
-}
-
-THREE.SpotLight.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	data.object.color = this.color.getHex();
-	data.object.intensity = this.intensity;
-	data.object.distance = this.distance;
-	data.object.angle = this.angle;
-	data.object.exponent = this.exponent;
-	data.object.decay = this.decay;
-
-	return data;
 
 };

+ 8 - 0
src/loaders/ImageLoader.js

@@ -20,14 +20,22 @@ THREE.ImageLoader.prototype = {
 
 		if ( cached !== undefined ) {
 
+			scope.manager.itemStart( url );
+
 			if ( onLoad ) {
 
 				setTimeout( function () {
 
 					onLoad( cached );
 
+					scope.manager.itemEnd( url );
+
 				}, 0 );
 
+			} else {
+
+				scope.manager.itemEnd( url );
+
 			}
 
 			return cached;

+ 6 - 4
src/loaders/ObjectLoader.js

@@ -447,7 +447,7 @@ THREE.ObjectLoader.prototype = {
 
 			var object;
 
-			var getGeometry = function ( name ) {
+			function getGeometry( name ) {
 
 				if ( geometries[ name ] === undefined ) {
 
@@ -457,9 +457,11 @@ THREE.ObjectLoader.prototype = {
 
 				return geometries[ name ];
 
-			};
+			}
+
+			function getMaterial( name ) {
 
-			var getMaterial = function ( name ) {
+				if ( name === undefined ) return undefined;
 
 				if ( materials[ name ] === undefined ) {
 
@@ -469,7 +471,7 @@ THREE.ObjectLoader.prototype = {
 
 				return materials[ name ];
 
-			};
+			}
 
 			switch ( data.type ) {
 

+ 0 - 25
src/objects/Line.js

@@ -181,31 +181,6 @@ THREE.Line.prototype.clone = function () {
 
 };
 
-THREE.Line.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	// only serialize if not in meta geometries cache
-	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
-
-		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();
-
-	}
-
-	// only serialize if not in meta materials cache
-	if ( meta.materials[ this.material.uuid ] === undefined ) {
-
-		meta.materials[ this.material.uuid ] = this.material.toJSON();
-
-	}
-
-	data.object.geometry = this.geometry.uuid;
-	data.object.material = this.material.uuid;
-
-	return data;
-
-};
-
 // DEPRECATED
 
 THREE.LineStrip = 0;

+ 0 - 25
src/objects/Mesh.js

@@ -354,28 +354,3 @@ THREE.Mesh.prototype.clone = function () {
 	return new this.constructor( this.geometry, this.material ).copy( this );
 
 };
-
-THREE.Mesh.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	// only serialize if not in meta geometries cache
-	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
-
-		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON( meta );
-
-	}
-
-	// only serialize if not in meta materials cache
-	if ( meta.materials[ this.material.uuid ] === undefined ) {
-
-		meta.materials[ this.material.uuid ] = this.material.toJSON( meta );
-
-	}
-
-	data.object.geometry = this.geometry.uuid;
-	data.object.material = this.material.uuid;
-
-	return data;
-
-};

+ 0 - 25
src/objects/Points.js

@@ -126,31 +126,6 @@ THREE.Points.prototype.clone = function () {
 
 };
 
-THREE.Points.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	// only serialize if not in meta geometries cache
-	if ( meta.geometries[ this.geometry.uuid ] === undefined ) {
-
-		meta.geometries[ this.geometry.uuid ] = this.geometry.toJSON();
-
-	}
-
-	// only serialize if not in meta materials cache
-	if ( meta.materials[ this.material.uuid ] === undefined ) {
-
-		meta.materials[ this.material.uuid ] = this.material.toJSON();
-
-	}
-
-	data.object.geometry = this.geometry.uuid;
-	data.object.material = this.material.uuid;
-
-	return data;
-
-};
-
 // Backwards compatibility
 
 THREE.PointCloud = function ( geometry, material ) {

+ 0 - 17
src/objects/Sprite.js

@@ -66,23 +66,6 @@ THREE.Sprite.prototype.clone = function () {
 
 };
 
-THREE.Sprite.prototype.toJSON = function ( meta ) {
-
-	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
-
-	// only serialize if not in meta materials cache
-	if ( meta.materials[ this.material.uuid ] === undefined ) {
-
-		meta.materials[ this.material.uuid ] = this.material.toJSON();
-
-	}
-
-	data.object.material = this.material.uuid;
-
-	return data;
-
-};
-
 // Backwards compatibility
 
 THREE.Particle = THREE.Sprite;

+ 165 - 29
src/renderers/WebGLRenderTarget.js

@@ -12,25 +12,13 @@ THREE.WebGLRenderTarget = function ( width, height, options ) {
 
 	options = options || {};
 
-	this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping;
-	this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping;
+	if ( options.minFilter === undefined ) options.minFilter = THREE.LinearFilter;
 
-	this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter;
-	this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter;
-
-	this.anisotropy = options.anisotropy !== undefined ? options.anisotropy : 1;
-
-	this.offset = new THREE.Vector2( 0, 0 );
-	this.repeat = new THREE.Vector2( 1, 1 );
-
-	this.format = options.format !== undefined ? options.format : THREE.RGBAFormat;
-	this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType;
+	this.texture = new THREE.Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy );
 
 	this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
 	this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
 
-	this.generateMipmaps = true;
-
 	this.shareDepthFrom = options.shareDepthFrom !== undefined ? options.shareDepthFrom : null;
 
 };
@@ -39,6 +27,168 @@ THREE.WebGLRenderTarget.prototype = {
 
 	constructor: THREE.WebGLRenderTarget,
 
+	get wrapS() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
+
+		return this.texture.wrapS;
+
+	},
+
+	set wrapS( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );
+
+		this.texture.wrapS = value;
+
+	},
+
+	get wrapT() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
+
+		return this.texture.wrapT;
+
+	},
+
+	set wrapT( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );
+
+		this.texture.wrapT = value;
+
+	},
+
+	get magFilter() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
+
+		return this.texture.magFilter;
+
+	},
+
+	set magFilter( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );
+
+		this.texture.magFilter = value;
+
+	},
+
+	get minFilter() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
+
+		return this.texture.minFilter;
+
+	},
+
+	set minFilter( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );
+
+		this.texture.minFilter = value;
+
+	},
+
+	get anisotropy() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
+
+		return this.texture.anisotropy;
+
+	},
+
+	set anisotropy( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );
+
+		this.texture.anisotropy = value;
+
+	},
+
+	get offset() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
+
+		return this.texture.offset;
+
+	},
+
+	set offset( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );
+
+		this.texture.offset = value;
+
+	},
+
+	get repeat() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
+
+		return this.texture.repeat;
+
+	},
+
+	set repeat( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );
+
+		this.texture.repeat = value;
+
+	},
+
+	get format() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
+
+		return this.texture.format;
+
+	},
+
+	set format( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );
+
+		this.texture.format = value;
+
+	},
+
+	get type() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
+
+		return this.texture.type;
+
+	},
+
+	set type( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );
+
+		this.texture.type = value;
+
+	},
+
+	get generateMipmaps() {
+
+		console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
+
+		return this.texture.generateMipmaps;
+
+	},
+
+	set generateMipmaps( value ) {
+
+		console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );
+
+		this.texture.generateMipmaps = value;
+
+	},
+
+	//
+
 	setSize: function ( width, height ) {
 
 		if ( this.width !== width || this.height !== height ) {
@@ -63,25 +213,11 @@ THREE.WebGLRenderTarget.prototype = {
 		this.width = source.width;
 		this.height = source.height;
 
-		this.wrapS = source.wrapS;
-		this.wrapT = source.wrapT;
-
-		this.magFilter = source.magFilter;
-		this.minFilter = source.minFilter;
-
-		this.anisotropy = source.anisotropy;
-
-		this.offset.copy( source.offset );
-		this.repeat.copy( source.repeat );
-
-		this.format = source.format;
-		this.type = source.type;
+		this.texture = source.texture.clone();
 
 		this.depthBuffer = source.depthBuffer;
 		this.stencilBuffer = source.stencilBuffer;
 
-		this.generateMipmaps = source.generateMipmaps;
-
 		this.shareDepthFrom = source.shareDepthFrom;
 
 		return this;

+ 61 - 37
src/renderers/WebGLRenderer.js

@@ -32,9 +32,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 	var lights = [];
 
 	var opaqueObjects = [];
-	var opaqueObjectsLastIndex = -1;
+	var opaqueObjectsLastIndex = - 1;
 	var transparentObjects = [];
-	var transparentObjectsLastIndex = -1;
+	var transparentObjectsLastIndex = - 1;
 
 	var morphInfluences = new Float32Array( 8 );
 
@@ -376,11 +376,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	this.getViewport = function ( dimensions ) {
 
-		dimensions.x = _viewportX;
-		dimensions.y = _viewportY;
+		dimensions.x = _viewportX / pixelRatio;
+		dimensions.y = _viewportY / pixelRatio;
 
-		dimensions.z = _viewportWidth;
-		dimensions.w = _viewportHeight;
+		dimensions.z = _viewportWidth / pixelRatio;
+		dimensions.w = _viewportHeight / pixelRatio;
 
 	};
 
@@ -558,10 +558,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function deallocateRenderTarget( renderTarget ) {
 
 		var renderTargetProperties = properties.get( renderTarget );
+		var textureProperties = properties.get( renderTarget.texture );
 
-		if ( ! renderTarget || renderTargetProperties.__webglTexture === undefined ) return;
+		if ( ! renderTarget || textureProperties.__webglTexture === undefined ) return;
 
-		_gl.deleteTexture( renderTargetProperties.__webglTexture );
+		_gl.deleteTexture( textureProperties.__webglTexture );
 
 		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 
@@ -579,6 +580,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
+		properties.delete( renderTarget.texture );
 		properties.delete( renderTarget );
 
 	}
@@ -601,6 +603,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		if ( programInfo !== undefined ) {
 
 			programCache.releaseProgram( programInfo );
+
 		}
 
 	}
@@ -1091,8 +1094,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		lights.length = 0;
 
-		opaqueObjectsLastIndex = -1;
-		transparentObjectsLastIndex = -1;
+		opaqueObjectsLastIndex = - 1;
+		transparentObjectsLastIndex = - 1;
 
 		sprites.length = 0;
 		lensFlares.length = 0;
@@ -1157,9 +1160,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		// Generate mipmap if we're using any kind of mipmap filtering
 
-		if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
+		if ( renderTarget ) {
+
+			var texture = renderTarget.texture;
+			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height );
+			if ( texture.generateMipmaps && isTargetPowerOfTwo && texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) {
 
-			updateRenderTargetMipmap( renderTarget );
+				 updateRenderTargetMipmap( renderTarget );
+
+			}
 
 		}
 
@@ -1328,17 +1337,17 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( object instanceof THREE.ImmediateRenderObject ) {
 
-					setMaterial( material );
+				setMaterial( material );
 
-					var program = setProgram( camera, lights, fog, material, object );
+				var program = setProgram( camera, lights, fog, material, object );
 
-					_currentGeometryProgram = '';
+				_currentGeometryProgram = '';
 
-					object.render( function ( object ) {
+				object.render( function ( object ) {
 
-						_this.renderBufferImmediate( object, program, material );
+					_this.renderBufferImmediate( object, program, material );
 
-					} );
+				} );
 
 			} else {
 
@@ -1800,6 +1809,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( uvScaleMap !== undefined ) {
 
+			if ( uvScaleMap instanceof THREE.WebGLRenderTarget ) uvScaleMap = uvScaleMap.texture;
 			var offset = uvScaleMap.offset;
 			var repeat = uvScaleMap.repeat;
 
@@ -1979,11 +1989,16 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					if ( light instanceof THREE.PointLight ) {
 
+						// for point lights we set the shadow matrix to be a translation-only matrix
+						// equal to inverse of the light's position
+						_vector3.setFromMatrixPosition( light.matrixWorld ).negate();
+						light.shadowMatrix.identity().setPosition( _vector3 );
+
 						// for point lights we set the sign of the shadowDarkness uniform to be negative
 						uniforms.shadowDarkness.value[ j ] = - light.shadowDarkness;
 
 					} else {
-						
+
 						uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
 
 					}
@@ -2314,7 +2329,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
 
-						setCubeTextureDynamic( texture, textureUnit );
+						setCubeTextureDynamic( texture.texture, textureUnit );
+
+					} else if ( texture instanceof THREE.WebGLRenderTarget ) {
+
+						_this.setTexture( texture.texture, textureUnit );
 
 					} else {
 
@@ -2356,9 +2375,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 							setCubeTexture( texture, textureUnit );
 
+						} else if ( texture instanceof THREE.WebGLRenderTarget ) {
+
+							_this.setTexture( texture.texture, textureUnit );
+
 						} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
 
-							setCubeTextureDynamic( texture, textureUnit );
+							setCubeTextureDynamic( texture.texture, textureUnit );
 
 						} else {
 
@@ -2975,7 +2998,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
 
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, properties.get( renderTarget ).__webglTexture, 0 );
+		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
 
 	}
 
@@ -3015,30 +3038,31 @@ THREE.WebGLRenderer = function ( parameters ) {
 		if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
 
 			var renderTargetProperties = properties.get( renderTarget );
+			var textureProperties = properties.get( renderTarget.texture );
 
 			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
 			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
 
 			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
 
-			renderTargetProperties.__webglTexture = _gl.createTexture();
+			textureProperties.__webglTexture = _gl.createTexture();
 
 			_infoMemory.textures ++;
 
 			// Setup texture, create render and frame buffers
 
 			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height ),
-				glFormat = paramThreeToGL( renderTarget.format ),
-				glType = paramThreeToGL( renderTarget.type );
+				glFormat = paramThreeToGL( renderTarget.texture.format ),
+				glType = paramThreeToGL( renderTarget.texture.type );
 
 			if ( isCube ) {
 
 				renderTargetProperties.__webglFramebuffer = [];
 				renderTargetProperties.__webglRenderbuffer = [];
 
-				state.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTargetProperties.__webglTexture );
+				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
 
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
+				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
 
 				for ( var i = 0; i < 6; i ++ ) {
 
@@ -3051,7 +3075,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				if ( renderTarget.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+				if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 
 			} else {
 
@@ -3067,8 +3091,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				state.bindTexture( _gl.TEXTURE_2D, renderTargetProperties.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
+				state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
+				setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
 
 				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
@@ -3092,7 +3116,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				if ( renderTarget.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
+				if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
 
 			}
 
@@ -3158,8 +3182,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( isCube ) {
 
-			var renderTargetProperties = properties.get( renderTarget );
-			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0,  _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, renderTargetProperties.__webglTexture, 0 );
+			var textureProperties = properties.get( renderTarget.texture );
+			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0,  _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, 0 );
 
 		}
 
@@ -3189,14 +3213,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			}
 
-			if ( renderTarget.format !== THREE.RGBAFormat && paramThreeToGL( renderTarget.format ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
+			if ( renderTarget.texture.format !== THREE.RGBAFormat && paramThreeToGL( renderTarget.texture.format ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
 
 				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
 				return;
 
 			}
 
-			if ( renderTarget.type !== THREE.UnsignedByteType && paramThreeToGL( renderTarget.type ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) ) {
+			if ( renderTarget.texture.type !== THREE.UnsignedByteType && paramThreeToGL( renderTarget.texture.type ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) ) {
 
 				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
 				return;
@@ -3205,7 +3229,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
 
-				_gl.readPixels( x, y, width, height, paramThreeToGL( renderTarget.format ), paramThreeToGL( renderTarget.type ), buffer );
+				_gl.readPixels( x, y, width, height, paramThreeToGL( renderTarget.texture.format ), paramThreeToGL( renderTarget.texture.type ), buffer );
 
 			} else {
 
@@ -3226,7 +3250,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function updateRenderTargetMipmap( renderTarget ) {
 
 		var target = renderTarget instanceof THREE.WebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
-		var texture = properties.get( renderTarget ).__webglTexture;
+		var texture = properties.get( renderTarget.texture ).__webglTexture;
 
 		state.bindTexture( target, texture );
 		_gl.generateMipmap( target );

+ 175 - 231
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -1,322 +1,266 @@
 #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
-
-	float fDepth;
-	vec3 shadowColor = vec3( 1.0 );
+	vec3 shadowMask = vec3( 1.0 );
 
 	for( int i = 0; i < MAX_SHADOWS; i ++ ) {
-
-		// to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
-		// whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
-		bool isPointLight = shadowDarkness[ i ] < 0.0;
-
-		// get the real shadow darkness
-		float realShadowDarkness = abs( shadowDarkness[ i ] );
-
-		// for point lights, the uniform @vShadowCoord is re-purposed to hold
-		// the distance from the light to the world-space position of the fragment.
-		vec3 lightToPosition = vShadowCoord[ i ].xyz;
-
-		float texelSizeX =  1.0 / shadowMapSize[ i ].x;
+		
 		float texelSizeY =  1.0 / shadowMapSize[ i ].y;
 
-		vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
-		float shadow = 0.0;
-
-		// if ( something && something ) breaks ATI OpenGL shader compiler
-		// if ( all( something, something ) ) using this instead
+		float shadow = 0.0;	
 
-		bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
-		bool inFrustum = all( inFrustumVec );
+#if defined( POINT_LIGHT_SHADOWS )
 
-		bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
-
-		bool frustumTest = all( frustumTestVec );
+		// to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
+		// whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
+		bool isPointLight = shadowDarkness[ i ] < 0.0;	
 
-		if ( frustumTest || isPointLight ) {			
+		if( isPointLight ) {
 
-			#if defined( SHADOWMAP_TYPE_PCF )
+			// get the real shadow darkness
+			float realShadowDarkness = abs( shadowDarkness[ i ] );
 
-				#if defined(POINT_LIGHT_SHADOWS)
+			// for point lights, the uniform @vShadowCoord is re-purposed to hold
+			// the distance from the light to the world-space position of the fragment.
+			vec3 lightToPosition = vShadowCoord[ i ].xyz;
 
-					if( isPointLight ) {
+	#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
 
-						// bd3D = base direction 3D
-						vec3 bd3D = normalize( lightToPosition );
-						// dp = distance from light to fragment position
-						float dp = length( lightToPosition );
+			// bd3D = base direction 3D
+			vec3 bd3D = normalize( lightToPosition );
+			// dp = distance from light to fragment position
+			float dp = length( lightToPosition );
 
-						shadow = 0.0;						
+			// base measurement
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
 
-						// base measurement
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
+			// Dr = disk radius
 
-						// dr = disk radius
-						const float dr = 1.25;
-						// os = offset scale
-						float os = dr *  2.0 * texelSizeY;
+	#if defined( SHADOWMAP_TYPE_PCF )
+			const float Dr = 1.25;
+	#elif defined( SHADOWMAP_TYPE_PCF_SOFT )
+			const float Dr = 2.25;
+	#endif
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd0 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd1 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd2 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd3 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd4 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd5 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd6 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd7 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd8 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd9 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			// os = offset scale
+			float os = Dr *  2.0 * texelSizeY;
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd10 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd11 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd12 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd13 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd14 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd15 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd16 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd17 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd18 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd19 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			const vec3 Gsd = vec3( - 1, 0, 1 );
 
-						shadow /= 21.0;
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
 
-					} else {
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
 
-				#endif
+			shadow *= realShadowDarkness * ( 1.0 / 21.0 );
 
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
-						
-						/*
-								// 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;
-						*/
+	#else // no percentage-closer filtering:
 
-						shadowCoord.z += shadowBias[ i ];
+			vec3 bd3D = normalize( lightToPosition );
+			float dp = length( lightToPosition );
 
-						const float shadowDelta = 1.0 / 9.0;
+			adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
 
-						float xPixelOffset = texelSizeX;
-						float yPixelOffset = texelSizeY;
+			shadow *= realShadowDarkness;
 
-						float dx0 = -1.25 * xPixelOffset;
-						float dy0 = -1.25 * yPixelOffset;
-						float dx1 = 1.25 * xPixelOffset;
-						float dy1 = 1.25 * yPixelOffset;
+	#endif
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+		} else {
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+#endif // POINT_LIGHT_SHADOWS
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			float texelSizeX =  1.0 / shadowMapSize[ i ].x;
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			// if ( something && something ) breaks ATI OpenGL shader compiler
+			// if ( all( something, something ) ) using this instead
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
+			bool inFrustum = all( inFrustumVec );
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
+			bool frustumTest = all( frustumTestVec );
 
-						fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
-						if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
-
-				#if defined(POINT_LIGHT_SHADOWS)
+			if( frustumTest ) {
 
+	#if defined( SHADOWMAP_TYPE_PCF )
+		
+				// Percentage-close filtering
+				// (9 pixel kernel)
+				// http://fabiensanglard.net/shadowmappingPCF/
+				
+				/*
+						// 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;
+				*/
 
-				#endif
-
-				shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
-
-			#elif defined( SHADOWMAP_TYPE_PCF_SOFT )
+				shadowCoord.z += shadowBias[ i ];
 
-				#if defined(POINT_LIGHT_SHADOWS)
+				const float ShadowDelta = 1.0 / 9.0;
 
-					if( isPointLight ) {
+				float xPixelOffset = texelSizeX;
+				float yPixelOffset = texelSizeY;
 
-						// bd3D = base direction 3D
-						vec3 bd3D = normalize( lightToPosition );
-						// dp = distance from light to fragment position
-						float dp = length( lightToPosition );
+				float dx0 = - 1.25 * xPixelOffset;
+				float dy0 = - 1.25 * yPixelOffset;
+				float dx1 = 1.25 * xPixelOffset;
+				float dy1 = 1.25 * yPixelOffset;
 
-						shadow = 0.0;						
+				float fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						// base measurement
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						// dr = disk radius
-						const float dr = 2.25;
-						// os = offset scale
-						float os = dr *  2.0 * texelSizeY;
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd0 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd1 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd2 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd3 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd4 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd5 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd6 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd7 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd8 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd9 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd10 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd11 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd12 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd13 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd14 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd15 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd16 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd17 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd18 * os, texelSizeY ) ), shadowBias[ i ], shadow );
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd19 * os, texelSizeY ) ), shadowBias[ i ], shadow );
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						shadow /= 21.0;
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-					} else {
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-				#endif
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						// Percentage-close filtering
-						// (9 pixel kernel)
-						// http://fabiensanglard.net/shadowmappingPCF/
+				fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
+				if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
 
-						shadowCoord.z += shadowBias[ i ];
+				shadow *= shadowDarkness[ i ];
 
-						float xPixelOffset = texelSizeX;
-						float yPixelOffset = texelSizeY;
+	#elif defined( SHADOWMAP_TYPE_PCF_SOFT )				
 
-						float dx0 = -1.0 * xPixelOffset;
-						float dy0 = -1.0 * yPixelOffset;
-						float dx1 = 1.0 * xPixelOffset;
-						float dy1 = 1.0 * yPixelOffset;
+				// Percentage-close filtering
+				// (9 pixel kernel)
+				// http://fabiensanglard.net/shadowmappingPCF/
 
-						mat3 shadowKernel;
-						mat3 depthKernel;
+				shadowCoord.z += shadowBias[ i ];
 
-						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 ) ) );
+				float xPixelOffset = texelSizeX;
+				float yPixelOffset = texelSizeY;
 
-						vec3 shadowZ = vec3( shadowCoord.z );
-						shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
-						shadowKernel[0] *= vec3(0.25);
+				float dx0 = - 1.0 * xPixelOffset;
+				float dy0 = - 1.0 * yPixelOffset;
+				float dx1 = 1.0 * xPixelOffset;
+				float dy1 = 1.0 * yPixelOffset;
 
-						shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
-						shadowKernel[1] *= vec3(0.25);
+				mat3 shadowKernel;
+				mat3 depthKernel;
 
-						shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
-						shadowKernel[2] *= vec3(0.25);
+				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 ) ) );
 
-						vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );
+				vec3 shadowZ = vec3( shadowCoord.z );
+				shadowKernel[ 0 ] = vec3( lessThan( depthKernel[ 0 ], shadowZ ) );
+				shadowKernel[ 0 ] *= vec3( 0.25 );
 
-						shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
-						shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );
+				shadowKernel[ 1 ] = vec3( lessThan( depthKernel[ 1 ], shadowZ ) );
+				shadowKernel[ 1 ] *= vec3( 0.25 );
 
-						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 ) );
-
-				#if defined(POINT_LIGHT_SHADOWS)
-					
-					}
+				shadowKernel[ 2 ] = vec3( lessThan( depthKernel[ 2 ], shadowZ ) );
+				shadowKernel[ 2 ] *= vec3( 0.25 );
 
-				#endif
+				vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[ i ].xy );
 
-				shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
+				shadowKernel[ 0 ] = mix( shadowKernel[ 1 ], shadowKernel[ 0 ], fractionalCoord.x );
+				shadowKernel[ 1 ] = mix( shadowKernel[ 2 ], shadowKernel[ 1 ], fractionalCoord.x );
 
-			#else
+				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 );
 
-				#if defined(POINT_LIGHT_SHADOWS)
+				shadow = dot( shadowValues, vec4( 1.0 ) ) * shadowDarkness[ i ];
 
-					if( isPointLight ) {
+	#else // no percentage-closer filtering:
+				
+				shadowCoord.z += shadowBias[ i ];
 
-						vec3 bd3D = normalize( lightToPosition );
-						float dp = length( lightToPosition );
+				vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
+				float fDepth = unpackDepth( rgbaDepth );
 
-						float shadow = 0.0;
+				if ( fDepth < shadowCoord.z )
+					shadow = shadowDarkness[ i ];				
 
-						adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
+	#endif
 
-						shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness * shadow );
+			}
 
-					} else {
+#ifdef SHADOWMAP_DEBUG
 
-				#endif
-						shadowCoord.z += shadowBias[ i ];
+			if ( inFrustum ) {
 
-						vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
-						float fDepth = unpackDepth( rgbaDepth );
+				if ( i == 0 ) {
 
-						if ( fDepth < shadowCoord.z )
+					outgoingLight *= vec3( 1.0, 0.5, 0.0 );
 
-						// spot with multiple shadows is darker
+				} else if ( i == 1 ) {
 
-						shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness );
+					outgoingLight *= vec3( 0.0, 1.0, 0.8 );
 
-						// spot with multiple shadows has the same color as single shadow spot
+				} else {
 
-						// 	shadowColor = min( shadowColor, vec3( realShadowDarkness ) );
+					outgoingLight *= vec3( 0.0, 0.5, 1.0 );
 
-				#if defined(POINT_LIGHT_SHADOWS)
+				}
 
-					}
+			}
 
-				#endif
+#endif
 
-			#endif
+#if defined( POINT_LIGHT_SHADOWS )
 
 		}
 
+#endif
 
-		#ifdef SHADOWMAP_DEBUG
-
-			if ( inFrustum ) outgoingLight *= frustumColors[ i ];
-
-		#endif
+		shadowMask = shadowMask * vec3( 1.0 - shadow );	
 
 	}
 
-	outgoingLight = outgoingLight * shadowColor;
+	outgoingLight = outgoingLight * shadowMask;
 
 #endif

+ 0 - 24
src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl

@@ -101,30 +101,6 @@
 
 		}
 
-		// gsdXX = grid sampling disk XX
-		// these values are used when rendering PCF shadow maps for point lights
-		
-		const vec3 gsd0 = vec3( 1, 1, 1 );
-		const vec3 gsd1 = vec3( 1, - 1, 1 );
-		const vec3 gsd2 = vec3( - 1, - 1, 1 );
-		const vec3 gsd3 = vec3( - 1, 1, 1 );
-		const vec3 gsd4 = vec3( 1, 1, - 1 );
-		const vec3 gsd5 = vec3( 1, - 1, - 1 );
-		const vec3 gsd6 = vec3( - 1, - 1, - 1 );
-		const vec3 gsd7 = vec3( -1, 1, - 1 );
-		const vec3 gsd8 = vec3( 1, 1, 0 );
-		const vec3 gsd9 = vec3( 1, - 1, 0 );
-		const vec3 gsd10 = vec3( - 1, - 1, 0 );
-		const vec3 gsd11 = vec3( - 1, 1, 0 );
-		const vec3 gsd12 = vec3( 1, 0, 1 );
-		const vec3 gsd13 = vec3( - 1, 0, 1 );
-		const vec3 gsd14 = vec3( 1, 0, - 1 );
-		const vec3 gsd15 = vec3( - 1, 0, - 1 );
-		const vec3 gsd16 = vec3( 0, 1, 1 );
-		const vec3 gsd17 = vec3( 0, - 1, 1 );
-		const vec3 gsd18 = vec3( 0, - 1, - 1 );
-		const vec3 gsd19 = vec3( 0, 1, - 1 );
-
 	#endif
 
 #endif

+ 0 - 32
src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl

@@ -2,40 +2,8 @@
 
 	for( int i = 0; i < MAX_SHADOWS; i ++ ) {
 
-		#if defined(POINT_LIGHT_SHADOWS)
-
-			// if shadowDarkness[ i ] < 0.0, that means we have a point light with a cube
-			// shadow map
-			if( shadowDarkness[ i ] < 0.0 ) {
-
-				// calculate vector from light to vertex in view space
-
-				vec3 fromLight = mvPosition.xyz - pointLightPosition[ i ];
-
-				// Transform 'fromLight' into world space by multiplying it on the left
-				// side of 'viewMatrix'. This is equivalent to multiplying it on the right
-				// side of the transpose of 'viewMatrix'. Since 'viewMatrix' is orthogonal, 
-				// its transpose is the same as its inverse.
-
-				fromLight = fromLight * mat3( viewMatrix );
-
-				// We repurpose vShadowCoord to hold the distance in world space from the
-				// light to the vertex. This value will be interpolated correctly in the fragment shader.
-
-				vShadowCoord[ i ] = vec4( fromLight, 1.0 );
-
-			} else {
-
-				vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
-
-			}
-
-		#else
-
 			vShadowCoord[ i ] = shadowMatrix[ i ] * worldPosition;
 
-		#endif
-
 	}
 
 #endif

+ 13 - 23
src/renderers/webgl/WebGLShadowMap.js

@@ -100,27 +100,18 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 		var faceCount, isPointLight;
 
 		if ( scope.enabled === false ) return;
-		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;
-
-		// set GL state for depth map
+		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;	
 
+		// Set GL state for depth map. 
 		_gl.clearColor( 1, 1, 1, 1 );
 		_state.disable( _gl.BLEND );
-
 		_state.enable( _gl.CULL_FACE );
 		_gl.frontFace( _gl.CCW );
+		_gl.cullFace( scope.cullFace === THREE.CullFaceFront ? _gl.FRONT : _gl.BACK );
+		_state.setDepthTest( true );			
 
-		if ( scope.cullFace === THREE.CullFaceFront ) {
-
-			_gl.cullFace( _gl.FRONT );
-
-		} else {
-
-			_gl.cullFace( _gl.BACK );
-
-		}
-
-		_state.setDepthTest( true );
+		// save the existing viewport so it can be restored later
+		_renderer.getViewport( _vector4 );
 
 		// render depth map
 
@@ -128,8 +119,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			var light = _lights[ i ];
 
-			// save the existing viewport so it can be restored later
-			_renderer.getViewport( _vector4 );
+			if ( ! light.castShadow ) continue;
 
 			if ( light instanceof THREE.PointLight ) {
 
@@ -172,8 +162,6 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			}
 
-			if ( ! light.castShadow ) continue;
-
 			if ( ! light.shadowMap ) {
 
 				var shadowFilter = THREE.LinearFilter;
@@ -321,15 +309,17 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 			}
 
-			_renderer.setViewport( _vector4.x, _vector4.y, _vector4.z, _vector4.w );
+			//We must call _renderer.resetGLState() at the end of each iteration of
+			// the light loop in order to force material updates for each light.
+			_renderer.resetGLState();			
 
 		}
 
-		// restore GL state
+		_renderer.setViewport( _vector4.x, _vector4.y, _vector4.z, _vector4.w );
 
+		// Restore GL state. 
 		var clearColor = _renderer.getClearColor(),
 		clearAlpha = _renderer.getClearAlpha();
-
 		_renderer.setClearColor( clearColor, clearAlpha );
 		_state.enable( _gl.BLEND );
 
@@ -339,7 +329,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 		}
 
-		_renderer.resetGLState();
+		_renderer.resetGLState();			
 
 		scope.needsUpdate = false;
 

部分文件因为文件数量过多而无法显示