Browse Source

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

simonThiele 10 years ago
parent
commit
4df16a81a1
37 changed files with 351 additions and 374 deletions
  1. 24 20
      build/three.js
  2. 27 27
      build/three.min.js
  3. 1 1
      docs/api/loaders/MTLLoader.html
  4. 21 46
      docs/api/materials/ShaderMaterial.html
  5. 0 1
      docs/index.html
  6. 0 1
      docs/scenes/js/material.js
  7. 1 1
      editor/index.html
  8. 1 1
      editor/js/Viewport.js
  9. 1 3
      examples/js/MarchingCubes.js
  10. 1 1
      examples/js/controls/OrthographicTrackballControls.js
  11. 54 13
      examples/js/controls/TransformControls.js
  12. 0 0
      examples/js/libs/jszip.min.js
  13. 1 7
      examples/js/loaders/MTLLoader.js
  14. 51 25
      examples/misc_controls_transform.html
  15. 4 4
      examples/webgl_materials_cubemap_dynamic.html
  16. 2 2
      examples/webgl_test_memory2.html
  17. 1 1
      package.json
  18. 1 1
      src/Three.js
  19. 3 3
      src/core/BufferGeometry.js
  20. 1 1
      src/core/InstancedBufferGeometry.js
  21. 1 1
      src/extras/geometries/CircleBufferGeometry.js
  22. 1 1
      src/extras/geometries/PlaneBufferGeometry.js
  23. 1 1
      src/extras/geometries/SphereBufferGeometry.js
  24. 1 1
      src/extras/helpers/BoxHelper.js
  25. 2 1
      src/extras/objects/ImmediateRenderObject.js
  26. 1 1
      src/loaders/BufferGeometryLoader.js
  27. 13 13
      src/loaders/ObjectLoader.js
  28. 1 1
      src/objects/Sprite.js
  29. 51 136
      src/renderers/WebGLRenderer.js
  30. 18 0
      src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl
  31. 0 54
      src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
  32. 28 0
      src/renderers/shaders/ShaderChunk/normal_phong_fragment.glsl
  33. 2 0
      src/renderers/shaders/ShaderLib.js
  34. 9 0
      src/renderers/webgl/WebGLProgram.js
  35. 24 4
      src/renderers/webgl/WebGLPrograms.js
  36. 1 1
      src/renderers/webgl/WebGLShadowMap.js
  37. 2 0
      utils/build/includes/common.json

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


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


+ 1 - 1
docs/api/loaders/MTLLoader.html

@@ -1,4 +1,4 @@
-<!D]OCTYPE html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />

+ 21 - 46
docs/api/materials/ShaderMaterial.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -16,9 +16,13 @@
 		<ul>
 			<li>implement an effect not included with any of the built-in [page:Material materials]</li>
 			<li>combine many objects into a single [page:Geometry] or [page:BufferGeometry] in order to improve performance</li>
-			<li>associate custom data with individual vertices ("custom attributes")</li>
 		</ul>
-		Note that a ShaderMaterial will only be rendered properly by [page:WebGLRenderer], since the GLSL code in the vertexShader and fragmentShader properties must be compiled and run on the GPU using WebGL.
+		There are the following notes to bear in mind when using a *ShaderMaterial*:
+
+		<ul>
+			<li>A *ShaderMaterial* will only be rendered properly by [page:WebGLRenderer], since the GLSL code in the *vertexShader* and *fragmentShader* properties must be compiled and run on the GPU using WebGL.</li>
+			<li>As of THREE r72, directly assigning attributes in a *ShaderMaterial* is no longer supported. A [page:BufferGeometry] instance (instead of a [page:Geometry] instance) must be used instead, using [page:BufferAttribute] instances to define custom attributes.</li>
+		</ul>
 		</div>
 
 		<h3>Example</h3>
@@ -67,66 +71,51 @@
 		</p>
 
 		<h3>Custom attributes and uniforms</h3>
-		Custom attributes and uniforms must be declared both in your GLSL shader code (within *vertexShader* and/or *fragmentShader*), <emph>and</emph> in the *attributes* and *uniforms* properties of your ShaderMaterial. The declaration in the material is necessary to ensure [page:WebGLRenderer] passes your attribute/uniform data in a buffer to the GPU when the shader is run. Note that *varying*s only need to be declared within the shader code (not within the material).
+		<p>Both custom attributes and uniforms must be declared in your GLSL shader code (within *vertexShader* and/or *fragmentShader*). Custom uniforms must be defined in <emph>both</emph> the *uniforms* property of your *ShaderMaterial*, whereas any custom attributes must be defined via [page:BufferAttribute] instances. Note that *varying*s only need to be declared within the shader code (not within the material).
 		</p>
-		<p>
-		To declare a custom attribute, use the *attributes* property of the material:
-		<code>
-		attributes: {
-			vertexOpacity: { type: 'f', value: [] }
-		}
-		</code>
-		Each attribute must have a *type* property and a *value* property.
+
+		<p>To declare a custom attribute, please reference the [page:BufferGeometry] page for an overview, and the [page:BufferAttribute] page for a detailed look at the *BufferAttribute* API.</p>
+		<p>When creating your attributes, each typed array that you create to hold your attribute's data must be a multiple of your data type's size. For example, if your attribute is a [page:Vector3 THREE.Vector3] type, and you have 3000 vertices in your [page:BufferGeometry], your typed array value must be created with a length of 3000 * 3, or 9000 (one value per-component). A table of each data type's size is shown below for reference:</p>
+
 		<table>
-			<caption><a id="attribute-types">Attribute types</a></caption>
+			<caption><a id="attribute-sizes">Attribute sizes</a></caption>
 			<thead>
 				<tr>
-					<th>Attribute *type* string</th>
 					<th>GLSL type</th>
 					<th>JavaScript type</th>
+					<th>Size</th>
 				</tr>
 			</thead>
 			<tbody>
 				<tr>
-					<td><code>'f'</code></td>
 					<td>float</td>
 					<td>[page:Number]</td>
+					<td>1</td>
 				</tr>
 				<tr>
-					<td><code>'v2'</code></td>
 					<td>vec2</td>
 					<td>[page:Vector2 THREE.Vector2]</td>
+					<td>2</td>
 				</tr>
 				<tr>
-					<td><code>'v3'</code></td>
 					<td>vec3</td>
 					<td>[page:Vector3 THREE.Vector3]</td>
+					<td>3</td>
 				</tr>
 				<tr>
-					<td><code>'c'</code></td>
 					<td>vec3</td>
 					<td>[page:Color THREE.Color]</td>
+					<td>3</td>
 				</tr>
 				<tr>
-					<td><code>'v4'</code></td>
 					<td>vec4</td>
 					<td>[page:Vector4 THREE.Vector4]</td>
+					<td>4</td>
 				</tr>
 			</tbody>
 		</table>
-		The way attribute data is stored depends on whether you're using [page:BufferGeometry] or [page:Geometry]:
-		<ul>
-			<li>When using [page:Geometry], attribute data is stored directly on the <emph>material</emph>, using the attribute's *value* array; each element of *value* should correspond to one vertex. To update an attribute, set the *needsUpdate* flag to true on the material attribute:
-			<code>
-			material.attributes.vertexOpacity.needsUpdate = true;
-			</code>
-			</li>
-			<li>When using [page:BufferGeometry], attribute data is stored within a [page:BufferAttribute] on the geometry itself, and the *value* within the material is ignored. To update an attribute, set the *needsUpdate* flag to true on the [page:BufferAttribute] of the geometry:
-			<code>
-			geometry.attributes.vertexOpacity.needsUpdate = true;
-			</code>
-			See [page:BufferGeometry] for details.</li>
-		</ul>
+
+		Note that attribute buffers are <emph>not</emph> refreshed automatically when their values change. To update custom attributes, set the *needsUpdate* flag to true on the [page:BufferAttribute] of the geometry (see [page:BufferGeometry] for further details).
 		</p>
 
 		<p>
@@ -232,20 +221,6 @@
 		where *type* is a <a href="#uniform-types">uniform type string</a>, and *value* is the value of the uniform. Names must match the name of the uniform, as defined in the GLSL code. Note that uniforms are refreshed on every frame, so updating the value of the uniform will immediately update the value available to the GLSL code.
 		</div>
 
-		<h3>[property:Object attributes]</h3>
-		<div>
-		<p>
-		Object specifying the custom attributes to be passed to the shader code; keys are attribute names, values are definitions of the form
-		<code>
-		{ type: 'f', value: [1.0, 0.5, 2.0, ...] }
-		</code>
-		where *type* is an <a href="#attribute-types">attribute type string</a>, and *value* is an array containing an attribute value for each vertex in the geometry (or *undefined* if using [page:BufferGeometry]). Names must match the name of the attribute, as defined in the GLSL code.
-		</p>
-		<p>
-		Note that attribute buffers are <emph>not</emph> refreshed automatically when their values change; if using [page:Geometry], set <code>needsUpdate = true</code> on the attribute definition. If using [page:BufferGeometry], set <code>needsUpdate = true</code> on the [page:BufferAttribute].
-		</p>
-		</div>
-
 		<h3>[property:Object defines]</h3>
 		<div>
 		Defines custom constants using *#define* directives within the GLSL code for both the vertex shader and the fragment shader; each key/value pair yields another directive:

+ 0 - 1
docs/index.html

@@ -417,6 +417,5 @@
 			].join('\n'));
 
 		</script>
-		<script src="../build/three.min.js"></script>
 	</body>
 </html>

+ 0 - 1
docs/scenes/js/material.js

@@ -403,7 +403,6 @@ function guiMeshLambertMaterial ( gui, mesh, material, geometry ) {
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
 	folder.addColor( data, 'emissive' ).onChange( handleColorChange( material.emissive ) );
 
-	folder.add( material, 'shading', constants.shading ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'vertexColors', constants.colors ).onChange( needsUpdate( material, geometry ) );

+ 1 - 1
editor/index.html

@@ -67,7 +67,7 @@
 		<script src="js/libs/ternjs/doc_comment.js"></script>
 		<script src="js/libs/tern-threejs/threejs.js"></script>
 
-		<script src="js/libs/jszip.min.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>

+ 1 - 1
editor/js/Viewport.js

@@ -283,7 +283,7 @@ var Viewport = function ( editor ) {
 
 	signals.snapChanged.add( function ( dist ) {
 
-		transformControls.setSnap( dist );
+		transformControls.setTranslationSnap( dist );
 
 	} );
 

+ 1 - 3
examples/js/MarchingCubes.js

@@ -7,9 +7,7 @@
 
 THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors ) {
 
-	THREE.ImmediateRenderObject.call( this );
-
-	this.material = material;
+	THREE.ImmediateRenderObject.call( this, material );
 
 	this.enableUvs = enableUvs !== undefined ? enableUvs : false;
 	this.enableColors = enableColors !== undefined ? enableColors : false;

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

@@ -245,7 +245,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 			if ( Math.abs( factor - 1.0 ) > EPS && factor > 0.0 ) {
 
-				_this.object.zoom *= factor;
+				_this.object.zoom /= factor;
 
 				if ( _this.staticMoving ) {
 

+ 54 - 13
examples/js/controls/TransformControls.js

@@ -617,7 +617,8 @@
 
 		this.object = undefined;
 		this.visible = false;
-		this.snap = null;
+		this.translationSnap = null;
+		this.rotationSnap = null;
 		this.space = "world";
 		this.size = 1;
 		this.axis = null;
@@ -750,9 +751,15 @@
 
 		};
 
-		this.setSnap = function ( snap ) {
+		this.setTranslationSnap = function ( translationSnap ) {
 
-			scope.snap = snap;
+			scope.translationSnap = translationSnap;
+
+		};
+
+		this.setRotationSnap = function ( rotationSnap ) {
+
+			scope.rotationSnap = rotationSnap;
 
 		};
 
@@ -930,11 +937,23 @@
 
 				}
 
-				if ( scope.snap !== null ) {
+				if ( scope.translationSnap !== null ) {
 
-					if ( scope.axis.search( "X" ) !== - 1 ) scope.object.position.x = Math.round( scope.object.position.x / scope.snap ) * scope.snap;
-					if ( scope.axis.search( "Y" ) !== - 1 ) scope.object.position.y = Math.round( scope.object.position.y / scope.snap ) * scope.snap;
-					if ( scope.axis.search( "Z" ) !== - 1 ) scope.object.position.z = Math.round( scope.object.position.z / scope.snap ) * scope.snap;
+					if ( scope.space === "local" ) {
+
+						scope.object.position.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+
+					}
+
+					if ( scope.axis.search( "X" ) !== - 1 ) scope.object.position.x = Math.round( scope.object.position.x / scope.translationSnap ) * scope.translationSnap;
+					if ( scope.axis.search( "Y" ) !== - 1 ) scope.object.position.y = Math.round( scope.object.position.y / scope.translationSnap ) * scope.translationSnap;
+					if ( scope.axis.search( "Z" ) !== - 1 ) scope.object.position.z = Math.round( scope.object.position.z / scope.translationSnap ) * scope.translationSnap;
+
+					if ( scope.space === "local" ) {
+
+						scope.object.position.applyMatrix4( worldRotationMatrix );
+
+					}
 
 				}
 
@@ -1013,9 +1032,20 @@
 					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
 
 					quaternionXYZ.setFromRotationMatrix( oldRotationMatrix );
-					quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
-					quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
-					quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+
+					if ( scope.rotationSnap !== null ) {
+
+						quaternionX.setFromAxisAngle( unitX, Math.round( ( rotation.x - offsetRotation.x ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionY.setFromAxisAngle( unitY, Math.round( ( rotation.y - offsetRotation.y ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionZ.setFromAxisAngle( unitZ, Math.round( ( rotation.z - offsetRotation.z ) / scope.rotationSnap ) * scope.rotationSnap );
+
+					} else {
+
+						quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
+						quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
+						quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+
+					}
 
 					if ( scope.axis === "X" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionX );
 					if ( scope.axis === "Y" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionY );
@@ -1030,9 +1060,20 @@
 
 					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
 
-					quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
-					quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
-					quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+					if ( scope.rotationSnap !== null ) {
+
+						quaternionX.setFromAxisAngle( unitX, Math.round( ( rotation.x - offsetRotation.x ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionY.setFromAxisAngle( unitY, Math.round( ( rotation.y - offsetRotation.y ) / scope.rotationSnap ) * scope.rotationSnap );
+						quaternionZ.setFromAxisAngle( unitZ, Math.round( ( rotation.z - offsetRotation.z ) / scope.rotationSnap ) * scope.rotationSnap );
+
+					} else {
+
+						quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
+						quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
+						quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+
+					}
+
 					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
 
 					if ( scope.axis === "X" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );

+ 0 - 0
editor/js/libs/jszip.min.js → examples/js/libs/jszip.min.js


+ 1 - 7
examples/js/loaders/MTLLoader.js

@@ -319,7 +319,7 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 					// Diffuse color (color under white light) using RGB values
 
-					params[ 'diffuse' ] = new THREE.Color().fromArray( value );
+					params[ 'color' ] = new THREE.Color().fromArray( value );
 
 					break;
 
@@ -390,12 +390,6 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 		}
 
-		if ( params[ 'diffuse' ] ) {
-
-			params[ 'color' ] = params[ 'diffuse' ];
-
-		}
-
 		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
 		return this.materials[ materialName ];
 

+ 51 - 25
examples/misc_controls_transform.html

@@ -26,7 +26,7 @@
 
 		<div id="info">
 		"W" translate | "E" rotate | "R" scale | "+" increase size | "-" decrease size<br />
-		Press "Q" to toggle world/local space
+		Press "Q" to toggle world/local space, keep "Ctrl" down to snap to grid
 		</div>
 
 		<script src="../build/three.min.js"></script>
@@ -79,30 +79,56 @@
 				window.addEventListener( 'resize', onWindowResize, false );
 
 				window.addEventListener( 'keydown', function ( event ) {
-		            //console.log(event.which);
-		            switch ( event.keyCode ) {
-		              case 81: // Q
-		                control.setSpace( control.space == "local" ? "world" : "local" );
-		                break;
-		              case 87: // W
-		                control.setMode( "translate" );
-		                break;
-		              case 69: // E
-		                control.setMode( "rotate" );
-		                break;
-		              case 82: // R
-		                control.setMode( "scale" );
-		                break;
-					case 187:
-					case 107: // +,=,num+
-						control.setSize( control.size + 0.1 );
-						break;
-					case 189:
-					case 109: // -,_,num-
-						control.setSize( Math.max(control.size - 0.1, 0.1 ) );
-						break;
-		            }
-        		});
+
+					switch ( event.keyCode ) {
+
+						case 81: // Q
+							control.setSpace( control.space === "local" ? "world" : "local" );
+							break;
+
+						case 17: // Ctrl
+							control.setTranslationSnap( 100 );
+							control.setRotationSnap( THREE.Math.degToRad( 15 ) );
+							break;
+
+						case 87: // W
+							control.setMode( "translate" );
+							break;
+
+						case 69: // E
+							control.setMode( "rotate" );
+							break;
+
+						case 82: // R
+							control.setMode( "scale" );
+							break;
+
+						case 187:
+						case 107: // +, =, num+
+							control.setSize( control.size + 0.1 );
+							break;
+
+						case 189:
+						case 109: // -, _, num-
+							control.setSize( Math.max( control.size - 0.1, 0.1 ) );
+							break;
+
+					}
+
+				});
+
+				window.addEventListener( 'keyup', function ( event ) {
+
+					switch ( event.keyCode ) {
+
+						case 17: // Ctrl
+							control.setTranslationSnap( null );
+							control.setRotationSnap( null );
+							break;
+
+					}
+
+				});
 
 			}
 

+ 4 - 4
examples/webgl_materials_cubemap_dynamic.html

@@ -262,11 +262,11 @@
 
 					var params  = {
 
-						"a" : { map: flareA, useScreenCoordinates: false, color: 0xffffff, blending: THREE.AdditiveBlending },
-						"b" : { map: flareB, useScreenCoordinates: false, color: 0xffffff, blending: THREE.AdditiveBlending },
+						"a" : { map: flareA, color: 0xffffff, blending: THREE.AdditiveBlending },
+						"b" : { map: flareB, color: 0xffffff, blending: THREE.AdditiveBlending },
 
-						"ar" : { map: flareA, useScreenCoordinates: false, color: 0xff0000, blending: THREE.AdditiveBlending },
-						"br" : { map: flareB, useScreenCoordinates: false, color: 0xff0000, blending: THREE.AdditiveBlending }
+						"ar" : { map: flareA, color: 0xff0000, blending: THREE.AdditiveBlending },
+						"br" : { map: flareB, color: 0xff0000, blending: THREE.AdditiveBlending }
 
 					};
 

+ 2 - 2
examples/webgl_test_memory2.html

@@ -128,7 +128,7 @@
 
 				renderer.render( scene, camera );
 
-				console.log( "before", renderer.info.memory.programs );
+				console.log( "before", renderer.info.programs.length );
 
 				for ( var i = 0; i < N; i ++ ) {
 
@@ -137,7 +137,7 @@
 
 				}
 
-				console.log( "after", renderer.info.memory.programs );
+				console.log( "after", renderer.info.programs.length );
 
 			}
 

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "three.js",
-  "version": "0.71.0",
+  "version": "0.72.0",
   "description": "JavaScript 3D library",
   "main": "build/three.js",
   "directories": {

+ 1 - 1
src/Three.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-var THREE = { REVISION: '72' };
+var THREE = { REVISION: '73dev' };
 
 //
 

+ 3 - 3
src/core/BufferGeometry.js

@@ -64,7 +64,7 @@ THREE.BufferGeometry.prototype = {
 		if ( name === 'index' ) {
 
 			console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );
-			this.addIndex( attribute );
+			this.setIndex( attribute );
 
 		}
 
@@ -505,7 +505,7 @@ THREE.BufferGeometry.prototype = {
 
 			var TypeArray = geometry.vertices.length > 65535 ? Uint32Array : Uint16Array;
 			var indices = new TypeArray( geometry.indices.length * 3 );
-			this.addIndex( new THREE.BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
+			this.setIndex( new THREE.BufferAttribute( indices, 1 ).copyIndicesArray( geometry.indices ) );
 
 		}
 
@@ -968,7 +968,7 @@ THREE.BufferGeometry.prototype = {
 
 		if ( index !== null ) {
 
-			this.addIndex( index.clone() );
+			this.setIndex( index.clone() );
 
 		}
 

+ 1 - 1
src/core/InstancedBufferGeometry.js

@@ -32,7 +32,7 @@ THREE.InstancedBufferGeometry.prototype.copy = function ( source ) {
 
 	if ( index !== null ) {
 
-		this.addIndex( index.clone() );
+		this.setIndex( index.clone() );
 
 	}
 

+ 1 - 1
src/extras/geometries/CircleBufferGeometry.js

@@ -56,7 +56,7 @@ THREE.CircleBufferGeometry = function ( radius, segments, thetaStart, thetaLengt
 
 	}
 
-	this.addIndex( new THREE.BufferAttribute( new Uint16Array( indices ), 1 ) );
+	this.setIndex( new THREE.BufferAttribute( new Uint16Array( indices ), 1 ) );
 	this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
 	this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
 	this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

+ 1 - 1
src/extras/geometries/PlaneBufferGeometry.js

@@ -85,7 +85,7 @@ THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegme
 
 	}
 
-	this.addIndex( new THREE.BufferAttribute( indices, 1 ) );
+	this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
 	this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
 	this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
 	this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );

+ 1 - 1
src/extras/geometries/SphereBufferGeometry.js

@@ -88,7 +88,7 @@ THREE.SphereBufferGeometry = function ( radius, widthSegments, heightSegments, p
 
 	}
 
-	this.addIndex( new THREE.BufferAttribute( new Uint16Array( indices ), 1 ) );
+	this.setIndex( new THREE.BufferAttribute( new Uint16Array( indices ), 1 ) );
 	this.addAttribute( 'position', positions );
 	this.addAttribute( 'normal', normals );
 	this.addAttribute( 'uv', uvs );

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

@@ -8,7 +8,7 @@ THREE.BoxHelper = function ( object ) {
 	var positions = new Float32Array( 8 * 3 );
 
 	var geometry = new THREE.BufferGeometry();
-	geometry.addIndex( new THREE.BufferAttribute( indices, 1 ) );
+	geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
 	geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
 
 	THREE.LineSegments.call( this, geometry, new THREE.LineBasicMaterial( { color: 0xffff00 } ) );

+ 2 - 1
src/extras/objects/ImmediateRenderObject.js

@@ -2,10 +2,11 @@
  * @author alteredq / http://alteredqualia.com/
  */
 
-THREE.ImmediateRenderObject = function () {
+THREE.ImmediateRenderObject = function ( material ) {
 
 	THREE.Object3D.call( this );
 
+	this.material = material;
 	this.render = function ( renderCallback ) {};
 
 };

+ 1 - 1
src/loaders/BufferGeometryLoader.js

@@ -41,7 +41,7 @@ THREE.BufferGeometryLoader.prototype = {
 		if ( index !== undefined ) {
 
 			var typedArray = new self[ index.type ]( index.array );
-			geometry.addIndex( new THREE.BufferAttribute( typedArray, 1 ) );
+			geometry.setIndex( new THREE.BufferAttribute( typedArray, 1 ) );
 
 		}
 

+ 13 - 13
src/loaders/ObjectLoader.js

@@ -321,31 +321,31 @@ THREE.ObjectLoader.prototype = {
 		var scope = this;
 		var images = {};
 
-		if ( json !== undefined && json.length > 0 ) {
-
-			var manager = new THREE.LoadingManager( onLoad );
+		function loadImage( url ) {
 
-			var loader = new THREE.ImageLoader( manager );
-			loader.setCrossOrigin( this.crossOrigin );
+			scope.manager.itemStart( url );
 
-			var loadImage = function ( url ) {
+			return loader.load( url, function () {
 
-				url = scope.texturePath + url;
+				scope.manager.itemEnd( url );
 
-				scope.manager.itemStart( url );
+			} );
 
-				return loader.load( url, function () {
+		}
 
-					scope.manager.itemEnd( url );
+		if ( json !== undefined && json.length > 0 ) {
 
-				} );
+			var manager = new THREE.LoadingManager( onLoad );
 
-			};
+			var loader = new THREE.ImageLoader( manager );
+			loader.setCrossOrigin( this.crossOrigin );
 
 			for ( var i = 0, l = json.length; i < l; i ++ ) {
 
 				var image = json[ i ];
-				images[ image.uuid ] = loadImage( image.url );
+				var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
+
+				images[ image.uuid ] = loadImage( path );
 
 			}
 

+ 1 - 1
src/objects/Sprite.js

@@ -10,7 +10,7 @@ THREE.Sprite = ( function () {
 	var uvs = new Float32Array( [ 0, 0,   1, 0,   1, 1,   0, 1 ] );
 
 	var geometry = new THREE.BufferGeometry();
-	geometry.addIndex( new THREE.BufferAttribute( indices, 1 ) );
+	geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
 	geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
 	geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 

+ 51 - 136
src/renderers/WebGLRenderer.js

@@ -36,11 +36,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 	var transparentObjects = [];
 	var transparentObjectsLastIndex = -1;
 
-	var opaqueImmediateObjects = [];
-	var opaqueImmediateObjectsLastIndex = -1;
-	var transparentImmediateObjects = [];
-	var transparentImmediateObjectsLastIndex = -1;
-
 	var morphInfluences = new Float32Array( 8 );
 
 
@@ -82,8 +77,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	var _this = this,
 
-	_programs = [],
-
 	// internal state cache
 
 	_currentProgram = null,
@@ -131,7 +124,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	_infoMemory = {
 
-		programs: 0,
 		geometries: 0,
 		textures: 0
 
@@ -150,10 +142,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		render: _infoRender,
 		memory: _infoMemory,
-		programs: _programs
+		programs: null
 
 	};
 
+
 	// initialize
 
 	var _gl;
@@ -215,6 +208,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 	var objects = new THREE.WebGLObjects( _gl, properties, this.info );
 	var programCache = new THREE.WebGLPrograms( this, capabilities );
 
+	this.info.programs = programCache.programs;
+
 	var bufferRenderer = new THREE.WebGLBufferRenderer( _gl, extensions, _infoRender );
 	var indexedBufferRenderer = new THREE.WebGLIndexedBufferRenderer( _gl, extensions, _infoRender );
 
@@ -589,41 +584,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function releaseMaterialProgramReference( material ) {
 
-		var program = properties.get( material ).program.program;
-
-		if ( program === undefined ) return;
+		var programInfo = properties.get( material ).program;
 
 		material.program = undefined;
 
-		for ( var i = 0, n = _programs.length; i !== n; ++ i ) {
-
-			var programInfo = _programs[ i ];
-
-			if ( programInfo.program === program ) {
-
-				var newReferenceCount = -- programInfo.usedTimes;
-
-				if ( newReferenceCount === 0 ) {
-
-					// the last material that has been using the program let
-					// go of it, so remove it from the (unordered) _programs
-					// set and deallocate the GL resource
-
-					var newLength = n - 1;
-
-					_programs[ i ] = _programs[ newLength ];
-					_programs.pop();
-
-					_gl.deleteProgram( program );
-
-					_infoMemory.programs = newLength;
-
-				}
-
-				break;
-
-			}
+		if ( programInfo !== undefined ) {
 
+			programCache.releaseProgram( programInfo );
 		}
 
 	}
@@ -831,7 +798,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		if ( group === undefined ) {
+		if ( group === null ) {
 
 			var count;
 
@@ -1129,9 +1096,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 		opaqueObjectsLastIndex = -1;
 		transparentObjectsLastIndex = -1;
 
-		opaqueImmediateObjectsLastIndex = -1;
-		transparentImmediateObjectsLastIndex = -1;
-
 		sprites.length = 0;
 		lensFlares.length = 0;
 
@@ -1140,9 +1104,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 		opaqueObjects.length = opaqueObjectsLastIndex + 1;
 		transparentObjects.length = transparentObjectsLastIndex + 1;
 
-		opaqueImmediateObjects.length = opaqueImmediateObjectsLastIndex + 1;
-		transparentImmediateObjects.length = transparentImmediateObjectsLastIndex + 1;
-
 		if ( _this.sortObjects === true ) {
 
 			opaqueObjects.sort( painterSortStable );
@@ -1178,22 +1139,16 @@ THREE.WebGLRenderer = function ( parameters ) {
 			renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial );
 			renderObjects( transparentObjects, camera, lights, fog, overrideMaterial );
 
-			renderObjectsImmediate( opaqueImmediateObjects, camera, lights, fog, overrideMaterial );
-			renderObjectsImmediate( transparentImmediateObjects, camera, lights, fog, overrideMaterial );
-
 		} else {
 
 			// opaque pass (front-to-back order)
 
 			state.setBlending( THREE.NoBlending );
-
 			renderObjects( opaqueObjects, camera, lights, fog );
-			renderObjectsImmediate( opaqueImmediateObjects, camera, lights, fog );
 
 			// transparent pass (back-to-front order)
 
 			renderObjects( transparentObjects, camera, lights, fog );
-			renderObjectsImmediate( transparentImmediateObjects, camera, lights, fog );
 
 		}
 
@@ -1220,40 +1175,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-	function pushImmediateRenderItem( object ) {
-
-		var array, index;
-
-		// allocate the next position in the appropriate array
-
-		if ( object.material.transparent ) {
-
-			array = transparentImmediateObjects;
-			index = ++ transparentImmediateObjectsLastIndex;
-
-		} else {
-
-			array = opaqueImmediateObjects;
-			index = ++ opaqueImmediateObjectsLastIndex;
-
-		}
-
-		// recycle existing position or grow the array
-
-		if ( index < array.length ) {
-
-			array[ index ] = object;
-
-		} else {
-
-			// assert( index === array.length );
-			array.push( object );
-
-		}
-
-
-	}
-
 	function pushRenderItem( object, geometry, material, z, group ) {
 
 		var array, index;
@@ -1321,7 +1242,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		} else if ( object instanceof THREE.ImmediateRenderObject ) {
 
-			pushImmediateRenderItem( object );
+			if ( _this.sortObjects === true ) {
+
+				_vector3.setFromMatrixPosition( object.matrixWorld );
+				_vector3.applyProjection( _projScreenMatrix );
+
+			}
+
+			pushRenderItem( object, null, object.material, _vector3.z, null );
 
 		} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
 
@@ -1366,7 +1294,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					} else {
 
-						pushRenderItem( object, geometry, material, _vector3.z );
+						pushRenderItem( object, geometry, material, _vector3.z, null );
 
 					}
 
@@ -1400,36 +1328,25 @@ THREE.WebGLRenderer = function ( parameters ) {
 			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
 			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
 
-			_this.renderBufferDirect( camera, lights, fog, geometry, material, object, group );
-
-		}
-
-	}
-
-	function renderObjectsImmediate( renderList, camera, lights, fog, overrideMaterial ) {
-
-		var material = overrideMaterial;
+			if ( object instanceof THREE.ImmediateRenderObject ) {
 
-		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
+					setMaterial( material );
 
-			var object = renderList[ i ];
+					var program = setProgram( camera, lights, fog, material, object );
 
-			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
-			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
+					_currentGeometryProgram = '';
 
-			if ( overrideMaterial === undefined ) material = object.material;
+					object.render( function ( object ) {
 
-			setMaterial( material );
+						_this.renderBufferImmediate( object, program, material );
 
-			var program = setProgram( camera, lights, fog, material, object );
+					} );
 
-			_currentGeometryProgram = '';
-
-			object.render( function ( object ) {
+			} else {
 
-				_this.renderBufferImmediate( object, program, material );
+				_this.renderBufferDirect( camera, lights, fog, geometry, material, object, group );
 
-			} );
+			}
 
 		}
 
@@ -1442,15 +1359,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var parameters = programCache.getParameters( material, lights, fog, object );
 		var code = programCache.getProgramCode( material, parameters );
 
-
+		var program = materialProperties.program;
 		var programChange = true;
 
-		if ( ! materialProperties.program ) {
+		if ( program === undefined ) {
 
 			// new material
 			material.addEventListener( 'dispose', onMaterialDispose );
 
-		} else if ( materialProperties.program.code !== code ) {
+		} else if ( program.code !== code ) {
 
 			// changed glsl or parameters
 			releaseMaterialProgramReference( material );
@@ -1467,41 +1384,39 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		if ( parameters.shaderID ) {
+		if ( programChange ) {
 
-			var shader = THREE.ShaderLib[ parameters.shaderID ];
+			if ( parameters.shaderID ) {
 
-			materialProperties.__webglShader = {
-				name: material.type,
-				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
-				vertexShader: shader.vertexShader,
-				fragmentShader: shader.fragmentShader
-			};
+				var shader = THREE.ShaderLib[ parameters.shaderID ];
 
-		} else {
+				materialProperties.__webglShader = {
+					name: material.type,
+					uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
+					vertexShader: shader.vertexShader,
+					fragmentShader: shader.fragmentShader
+				};
 
-			materialProperties.__webglShader = {
-				name: material.type,
-				uniforms: material.uniforms,
-				vertexShader: material.vertexShader,
-				fragmentShader: material.fragmentShader
-			};
+			} else {
 
-		}
+				materialProperties.__webglShader = {
+					name: material.type,
+					uniforms: material.uniforms,
+					vertexShader: material.vertexShader,
+					fragmentShader: material.fragmentShader
+				};
 
-		material.__webglShader = materialProperties.__webglShader;
+			}
 
-		var program = programCache.getProgram( material, parameters, code );
+			material.__webglShader = materialProperties.__webglShader;
 
-		if ( programChange ) {
+			program = programCache.acquireProgram( material, parameters, code );
 
-			program.usedTimes ++;
+			materialProperties.program = program;
+			material.program = program;
 
 		}
 
-		materialProperties.program = program;
-		material.program = program;
-
 		var attributes = program.getAttributes();
 
 		if ( material.morphTargets ) {

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

@@ -0,0 +1,18 @@
+#if MAX_HEMI_LIGHTS > 0
+
+	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
+
+		vec3 lightDir = hemisphereLightDirection[ i ];
+
+		float dotProduct = dot( normal, lightDir );
+
+		float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
+
+		vec3 lightColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
+
+		totalAmbientLight += lightColor;
+
+	}
+
+#endif
+

+ 0 - 54
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl

@@ -1,31 +1,3 @@
-#ifndef FLAT_SHADED
-
-	vec3 normal = normalize( vNormal );
-
-	#ifdef DOUBLE_SIDED
-
-		normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );
-
-	#endif
-
-#else
-
-	vec3 fdx = dFdx( vViewPosition );
-	vec3 fdy = dFdy( vViewPosition );
-	vec3 normal = normalize( cross( fdx, fdy ) );
-
-#endif
-
-#ifdef USE_NORMALMAP
-
-	normal = perturbNormal2Arb( -vViewPosition, normal );
-
-#elif defined( USE_BUMPMAP )
-
-	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );
-
-#endif
-
 vec3 viewDir = normalize( vViewPosition );
 
 vec3 totalDiffuseLight = vec3( 0.0 );
@@ -126,32 +98,6 @@ vec3 totalSpecularLight = vec3( 0.0 );
 
 #endif
 
-#if MAX_HEMI_LIGHTS > 0
-
-	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
-
-		vec3 lightDir = hemisphereLightDirection[ i ];
-
-		// diffuse
-
-		float dotProduct = dot( normal, lightDir );
-
-		float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
-
-		vec3 lightColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
-
-		totalDiffuseLight += lightColor;
-
-		// specular (sky term only)
-
-		vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
-
-		totalSpecularLight += brdf * specularStrength * lightColor * max( dotProduct, 0.0 );
-
-	}
-
-#endif
-
 #ifdef METAL
 
 	outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) * specular + totalSpecularLight + totalEmissiveLight;

+ 28 - 0
src/renderers/shaders/ShaderChunk/normal_phong_fragment.glsl

@@ -0,0 +1,28 @@
+#ifndef FLAT_SHADED
+
+	vec3 normal = normalize( vNormal );
+
+	#ifdef DOUBLE_SIDED
+
+		normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );
+
+	#endif
+
+#else
+
+	vec3 fdx = dFdx( vViewPosition );
+	vec3 fdy = dFdy( vViewPosition );
+	vec3 normal = normalize( cross( fdx, fdy ) );
+
+#endif
+
+#ifdef USE_NORMALMAP
+
+	normal = perturbNormal2Arb( -vViewPosition, normal );
+
+#elif defined( USE_BUMPMAP )
+
+	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );
+
+#endif
+

+ 2 - 0
src/renderers/shaders/ShaderLib.js

@@ -366,7 +366,9 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
+				THREE.ShaderChunk[ "normal_phong_fragment" ],
 				THREE.ShaderChunk[ "lightmap_fragment" ],
+				THREE.ShaderChunk[ "hemilight_fragment" ],
 				THREE.ShaderChunk[ "aomap_fragment" ],
 				THREE.ShaderChunk[ "emissivemap_fragment" ],
 

+ 9 - 0
src/renderers/webgl/WebGLProgram.js

@@ -454,6 +454,15 @@ THREE.WebGLProgram = ( function () {
 
 		};
 
+		// free resource
+
+		this.destroy = function() {
+
+			gl.deleteProgram( program );
+			this.program = undefined;
+
+		};
+
 		// DEPRECATED
 
 		Object.defineProperties( this, {

+ 24 - 4
src/renderers/webgl/WebGLPrograms.js

@@ -160,7 +160,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 			flatShading: material.shading === THREE.FlatShading,
 
 			sizeAttenuation: material.sizeAttenuation,
-			logarithmicDepthBuffer: renderer.logarithmicDepthBuffer,
+			logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
 
 			skinning: material.skinning,
 			maxBones: maxBones,
@@ -230,7 +230,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 	};
 
-	this.getProgram = function ( material, parameters, code ) {
+	this.acquireProgram = function ( material, parameters, code ) {
 
 		var program;
 
@@ -242,6 +242,7 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 			if ( programInfo.code === code ) {
 
 				program = programInfo;
+				++ program.usedTimes;
 
 				break;
 
@@ -256,8 +257,27 @@ THREE.WebGLPrograms = function ( renderer, capabilities ) {
 
 		}
 
-		return program ;
+		return program;
 
-	}
+	};
+
+	this.releaseProgram = function( program ) {
+
+		if ( -- program.usedTimes === 0 ) {
+
+			// Remove from unordered set
+			var i = programs.indexOf( program );
+			programs[ i ] = programs[ programs.length - 1 ];
+			programs.pop();
+
+			// Free WebGL resources
+			program.destroy();
+
+		}
+
+	};
+
+	// Exposed for resource monitoring & error feedback via renderer.info:
+	this.programs = programs;
 
 };

+ 1 - 1
src/renderers/webgl/WebGLShadowMap.js

@@ -224,7 +224,7 @@ THREE.WebGLShadowMap = function ( _renderer, _lights, _objects ) {
 
 				} else {
 
-					_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, material ), object );
+					_renderer.renderBufferDirect( shadowCamera, _lights, null, geometry, getDepthMaterial( object, material ), object, null );
 
 				}
 

+ 2 - 0
utils/build/includes/common.json

@@ -114,6 +114,7 @@
 	"src/renderers/shaders/ShaderChunk/envmap_vertex.glsl",
 	"src/renderers/shaders/ShaderChunk/fog_fragment.glsl",
 	"src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl",
+	"src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl",
 	"src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl",
 	"src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl",
 	"src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl",
@@ -134,6 +135,7 @@
 	"src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl",
 	"src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl",
 	"src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl",
+	"src/renderers/shaders/ShaderChunk/normal_phong_fragment.glsl",
 	"src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl",
 	"src/renderers/shaders/ShaderChunk/project_vertex.glsl",
 	"src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl",

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