Browse Source

Merge @zz85/buffer_attributes into dev

Mr.doob 12 years ago
parent
commit
a28e942faf

+ 253 - 0
examples/webgl_buffergeometry_custom_attributes_particles.html

@@ -0,0 +1,253 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - buffer geometry custom attributes [particles]</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				color: #ffffff;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+				font-weight: bold;
+
+				background-color: #000000;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				color: #fff;
+				background-color: rgba( 0, 0, 0, 0.75 );
+				position: relative;
+				top: 0px; width: 100%;
+				padding: 5px;
+				z-index:100;
+				width:33em;
+				margin:0 auto -2em;
+			}
+			a { color: #ff0000 }
+		</style>
+	</head>
+
+	<body>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - buffergeometry custom attributes example - particles</div>
+		<div id="container"></div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="../src/renderers/WebGLRenderer.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script type="x-shader/x-vertex" id="vertexshader">
+
+			uniform float amplitude;
+			attribute float size;
+			attribute vec3 customColor;
+
+			varying vec3 vColor;
+
+			void main() {
+
+				vColor = customColor;
+
+				vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
+
+				//gl_PointSize = size;
+				gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
+
+				gl_Position = projectionMatrix * mvPosition;
+
+			}
+
+		</script>
+
+		<script type="x-shader/x-fragment" id="fragmentshader">
+
+			uniform vec3 color;
+			uniform sampler2D texture;
+
+			varying vec3 vColor;
+
+			void main() {
+
+				gl_FragColor = vec4( color * vColor, 1.0 );
+				gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
+
+			}
+
+		</script>
+
+
+		<script>
+
+		if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+		var renderer, scene, camera, stats;
+
+		var sphere, uniforms, geometry;
+
+		var noise = [];
+		var values_size;
+		//500000
+		var particles = 100000;
+
+		var WIDTH = window.innerWidth;
+		var HEIGHT = window.innerHeight;
+
+		init();
+		animate();
+
+		function init() {
+
+			camera = new THREE.PerspectiveCamera( 40, WIDTH / HEIGHT, 1, 10000 );
+			camera.position.z = 300;
+
+			scene = new THREE.Scene();
+
+			var attributes = {
+
+				size: {	type: 'f', value: null },
+				customColor: { type: 'c', value: null }
+
+			};
+
+			uniforms = {
+
+				amplitude: { type: "f", value: 1.0 },
+				color:     { type: "c", value: new THREE.Color( 0xffffff ) },
+				texture:   { type: "t", value: THREE.ImageUtils.loadTexture( "textures/sprites/spark1.png" ) },
+
+			};
+
+			var shaderMaterial = new THREE.ShaderMaterial( {
+
+				uniforms: 		uniforms,
+				attributes:     attributes,
+				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
+				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
+
+				blending: 		THREE.AdditiveBlending,
+				depthTest: 		false,
+				transparent:	true
+
+			});
+
+
+			var radius = 200;
+
+			geometry = new THREE.BufferGeometry();
+			// geometry.dynamic = true;
+			geometry.attributes = {
+
+				position: {
+					itemSize: 3,
+					array: new Float32Array( particles * 3 ),
+					numItems: particles * 3
+				},
+				customColor: {
+					itemSize: 3,
+					array: new Float32Array( particles * 3 ),
+					numItems: particles * 3
+				},
+				size: {
+					itemSize: 1,
+					array: new Float32Array( particles ),
+					numItems: particles * 1,
+					dynamic: true
+				},
+
+			}
+
+
+			values_size = geometry.attributes.size.array;
+			var positions = geometry.attributes.position.array;
+			var values_color = geometry.attributes.customColor.array;
+
+			sphere = new THREE.ParticleSystem( geometry, shaderMaterial );
+
+			//sphere.sortParticles = true;
+
+			var color = new THREE.Color( 0xffaa00 );;
+
+			for( var v = 0; v < particles; v++ ) {
+
+				values_size[ v ] = 10;
+
+				positions[ v * 3 + 0 ] = (Math.random() * 2 - 1) * radius;
+				positions[ v * 3 + 1 ] = (Math.random() * 2 - 1) * radius;
+				positions[ v * 3 + 2 ] = (Math.random() * 2 - 1) * radius;
+
+				if ( positions[ v * 3 + 0 ] < 0 )
+					color.setHSL( 0.5 + 0.1 * ( v / particles ), 0.7, 0.1 );
+				else
+					color.setHSL( 0.0 + 0.1 * ( v / particles ), 0.9, 0.1 );
+
+				values_color[ v * 3 + 0 ] = color.r;
+				values_color[ v * 3 + 1 ] = color.g;
+				values_color[ v * 3 + 2 ] = color.b;
+
+			}
+
+			scene.add( sphere );
+
+			renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+			renderer.setSize( WIDTH, HEIGHT );
+
+			var container = document.getElementById( 'container' );
+			container.appendChild( renderer.domElement );
+
+			stats = new Stats();
+			stats.domElement.style.position = 'absolute';
+			stats.domElement.style.top = '0px';
+			container.appendChild( stats.domElement );
+
+			//
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+		}
+
+		function onWindowResize() {
+
+			camera.aspect = window.innerWidth / window.innerHeight;
+			camera.updateProjectionMatrix();
+
+			renderer.setSize( window.innerWidth, window.innerHeight );
+
+		}
+
+		function animate() {
+
+			requestAnimationFrame( animate );
+
+			render();
+			stats.update();
+
+		}
+
+		function render() {
+
+			var time = Date.now() * 0.005;
+
+			sphere.rotation.z = 0.01 * time;
+
+			for( var i = 0; i < particles; i++ ) {
+
+				values_size[ i ] = 14 + 13 * Math.sin( 0.1 * i + time );
+
+			}
+
+			geometry.attributes.size.needsUpdate = true;
+
+			renderer.render( scene, camera );
+
+		}
+
+
+	</script>
+
+</body>
+
+</html>

+ 154 - 351
src/renderers/WebGLRenderer.js

@@ -268,19 +268,19 @@ THREE.WebGLRenderer = function ( parameters ) {
 		return _glExtensionTextureFloat;
 
 	};
-	
+
 	this.supportsStandardDerivatives = function () {
 
 		return _glExtensionStandardDerivatives;
 
 	};
-	
+
 	this.supportsCompressedTextureS3TC = function () {
 
 		return _glExtensionCompressedTextureS3TC;
 
 	};
-	
+
 	this.getMaxAnisotropy  = function () {
 
 		return _maxAnisotropy;
@@ -3238,60 +3238,33 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		var attributes = geometry.attributes;
 
-		var index = attributes[ "index" ];
-		var position = attributes[ "position" ];
-		var normal = attributes[ "normal" ];
-		var uv = attributes[ "uv" ];
-		var color = attributes[ "color" ];
-		var tangent = attributes[ "tangent" ];
-
-		if ( geometry.elementsNeedUpdate && index !== undefined ) {
-
-			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
-			_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, index.array, hint );
-
-		}
-
-		if ( geometry.verticesNeedUpdate && position !== undefined ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, position.array, hint );
-
-		}
-
-		if ( geometry.normalsNeedUpdate && normal !== undefined ) {
+		var attributeName, attributeItem;
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, normal.array, hint );
+		for ( attributeName in attributes ) {
 
-		}
-
-		if ( geometry.uvsNeedUpdate && uv !== undefined ) {
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, uv.array, hint );
+			attributeItem = attributes[ attributeName ];
 
-		}
+			if ( attributeItem.needsUpdate ) {
 
-		if ( geometry.colorsNeedUpdate && color !== undefined ) {
+				if ( attributeName === 'index' ) {
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, color.array, hint );
+					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attributeItem.buffer );
+					_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, attributeItem.array, hint );
 
-		}
+				} else {
 
-		if ( geometry.tangentsNeedUpdate && tangent !== undefined ) {
+					_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+					_gl.bufferData( _gl.ARRAY_BUFFER, attributeItem.array, hint );
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
-			_gl.bufferData( _gl.ARRAY_BUFFER, tangent.array, hint );
+				}
 
-		}
+				attributeItem.needsUpdate = false;
 
-		if ( dispose ) {
+			}
 
-			for ( var i in geometry.attributes ) {
+			if ( dispose && ! attributeItem.dynamic ) {
 
-				delete geometry.attributes[ i ].array;
+				delete attributeItem.array;
 
 			}
 
@@ -3398,11 +3371,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( material.visible === false ) return;
 
-		var program, attributes, linewidth, primitives, a, attribute;
+		var program, programAttributes, linewidth, primitives, a, attribute, geometryAttributes;
+		var attributeItem, attributeName, attributePointer, attributeSize;
 
 		program = setProgram( camera, lights, fog, material, object );
 
-		attributes = program.attributes;
+		programAttributes = program.attributes;
+		geometryAttributes = geometry.attributes;
 
 		var updateBuffers = false,
 			wireframeBit = material.wireframe ? 1 : 0,
@@ -3425,7 +3400,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( object instanceof THREE.Mesh ) {
 
-			var index = geometry.attributes[ "index" ];
+			var index = geometryAttributes[ "index" ];
 
 			// indexed triangles
 
@@ -3445,68 +3420,21 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					if ( updateBuffers ) {
 
-						// vertices
-
-						var position = geometry.attributes[ "position" ];
-						var positionSize = position.itemSize;
+						for ( attributeName in geometryAttributes ) {
 
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
-						enableAttribute( attributes.position );
-						_gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, startIndex * positionSize * 4 ); // 4 bytes per Float32
+							if ( attributeName === 'index' ) continue;
 
-						// normals
+							attributePointer = programAttributes[ attributeName ];
+							attributeItem = geometryAttributes[ attributeName ];
+							attributeSize = attributeItem.itemSize;
 
-						var normal = geometry.attributes[ "normal" ];
+							if ( attributePointer >= 0 ) {
 
-						if ( attributes.normal >= 0 && normal ) {
+								_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+								enableAttribute( attributePointer );
+								_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
 
-							var normalSize = normal.itemSize;
-
-							_gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
-							enableAttribute( attributes.normal );
-							_gl.vertexAttribPointer( attributes.normal, normalSize, _gl.FLOAT, false, 0, startIndex * normalSize * 4 );
-
-						}
-
-						// uvs
-
-						var uv = geometry.attributes[ "uv" ];
-
-						if ( attributes.uv >= 0 && uv ) {
-
-							var uvSize = uv.itemSize;
-
-							_gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
-							enableAttribute( attributes.uv );
-							_gl.vertexAttribPointer( attributes.uv, uvSize, _gl.FLOAT, false, 0, startIndex * uvSize * 4 );
-
-						}
-
-						// colors
-
-						var color = geometry.attributes[ "color" ];
-
-						if ( attributes.color >= 0 && color ) {
-
-							var colorSize = color.itemSize;
-
-							_gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
-							enableAttribute( attributes.color );
-							_gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, startIndex * colorSize * 4 );
-
-						}
-
-						// tangents
-
-						var tangent = geometry.attributes[ "tangent" ];
-
-						if ( attributes.tangent >= 0 && tangent ) {
-
-							var tangentSize = tangent.itemSize;
-
-							_gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
-							enableAttribute( attributes.tangent );
-							_gl.vertexAttribPointer( attributes.tangent, tangentSize, _gl.FLOAT, false, 0, startIndex * tangentSize * 4 );
+							}
 
 						}
 
@@ -3532,73 +3460,28 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( updateBuffers ) {
 
-					// vertices
+					for ( attributeName in geometryAttributes ) {
 
-					var position = geometry.attributes[ "position" ];
-					var positionSize = position.itemSize;
+						if ( attributeName === 'index') continue;
 
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
-					enableAttribute( attributes.position );
-					_gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, 0 );
+						attributePointer = programAttributes[ attributeName ];
+						attributeItem = geometryAttributes[ attributeName ];
+						attributeSize = attributeItem.itemSize;
 
-					// normals
+						if ( attributePointer >= 0 ) {
 
-					var normal = geometry.attributes[ "normal" ];
+							_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+							enableAttribute( attributePointer );
+							_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
 
-					if ( attributes.normal >= 0 && normal ) {
-
-						var normalSize = normal.itemSize;
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
-						enableAttribute( attributes.normal );
-						_gl.vertexAttribPointer( attributes.normal, normalSize, _gl.FLOAT, false, 0, 0 );
-
-					}
-
-					// uvs
-
-					var uv = geometry.attributes[ "uv" ];
-
-					if ( attributes.uv >= 0 && uv ) {
-
-						var uvSize = uv.itemSize;
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
-						enableAttribute( attributes.uv );
-						_gl.vertexAttribPointer( attributes.uv, uvSize, _gl.FLOAT, false, 0, 0 );
-
-					}
-
-					// colors
-
-					var color = geometry.attributes[ "color" ];
-
-					if ( attributes.color >= 0 && color ) {
-
-						var colorSize = color.itemSize;
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
-						enableAttribute( attributes.color );
-						_gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, 0 );
-
-					}
-
-					// tangents
-
-					var tangent = geometry.attributes[ "tangent" ];
-
-					if ( attributes.tangent >= 0 && tangent ) {
-
-						var tangentSize = tangent.itemSize;
-
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
-						enableAttribute( attributes.tangent );
-						_gl.vertexAttribPointer( attributes.tangent, tangentSize, _gl.FLOAT, false, 0, 0 );
+						}
 
 					}
 
 				}
 
+				var position = geometry.attributes[ "position" ];
+
 				// render non-indexed triangles
 
 				_gl.drawArrays( _gl.TRIANGLES, 0, position.numItems / 3 );
@@ -3615,29 +3498,24 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( updateBuffers ) {
 
-				// vertices
-
-				var position = geometry.attributes[ "position" ];
-				var positionSize = position.itemSize;
-
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
-				enableAttribute( attributes.position );
-				_gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, 0 );
-
-				// colors
+				for ( attributeName in geometryAttributes ) {
 
-				var color = geometry.attributes[ "color" ];
+					attributePointer = programAttributes[ attributeName ];
+					attributeItem = geometryAttributes[ attributeName ];
+					attributeSize = attributeItem.itemSize;
 
-				if ( attributes.color >= 0 && color ) {
+					if ( attributePointer >= 0 ) {
 
-					var colorSize = color.itemSize;
+						_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+						enableAttribute( attributePointer );
+						_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
 
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
-					enableAttribute( attributes.color );
-					_gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, 0 );
+					}
 
 				}
 
+				var position = geometryAttributes[ "position" ];
+
 				// render particles
 
 				_gl.drawArrays( _gl.POINTS, 0, position.numItems / 3 );
@@ -3651,26 +3529,19 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( updateBuffers ) {
 
-				// vertices
+				for ( attributeName in geometryAttributes ) {
 
-				var position = geometry.attributes[ "position" ];
-				var positionSize = position.itemSize;
+					attributePointer = programAttributes[ attributeName ];
+					attributeItem = geometryAttributes[ attributeName ];
+					attributeSize = attributeItem.itemSize;
 
-				_gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
-				enableAttribute( attributes.position );
-				_gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, 0 );
+					if ( attributePointer >= 0 ) {
 
-				// colors
+						_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+						enableAttribute( attributePointer );
+						_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, 0 );
 
-				var color = geometry.attributes[ "color" ];
-
-				if ( attributes.color >= 0 && color ) {
-
-					var colorSize = color.itemSize;
-
-					_gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
-					enableAttribute( attributes.color );
-					_gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, 0 );
+					}
 
 				}
 
@@ -3678,6 +3549,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				setLineWidth( material.linewidth );
 
+				var position = geometryAttributes[ "position" ];
+
 				_gl.drawArrays( _gl.LINE_STRIP, 0, position.numItems / 3 );
 
 				_this.info.render.calls ++;
@@ -3685,7 +3558,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			}
 
-    }
+    	}
 
 	};
 
@@ -4077,7 +3950,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		} else {
 
-			return a.id - b.id;
+			return b.id - a.id;
 
 		}
 
@@ -4159,7 +4032,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 			webglObject = renderList[ i ];
 			object = webglObject.object;
 
-			webglObject.id = i;
 			webglObject.render = false;
 
 			if ( object.visible ) {
@@ -4187,6 +4059,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 						}
 
+						webglObject.id = object.id;
+
 					}
 
 				}
@@ -4633,54 +4507,53 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			}
 
-			if ( object instanceof THREE.Mesh ) {
+			geometry = object.geometry;
 
-				geometry = object.geometry;
-				material = object.material;
+			if ( geometry === undefined ) {
 
-				if ( geometry instanceof THREE.Geometry ) {
+				// fail silently for now
 
-					if ( geometry.geometryGroups === undefined ) {
+			} else if ( geometry instanceof THREE.BufferGeometry ) {
 
-						sortFacesByMaterial( geometry, material );
+				initDirectBuffers( geometry );
 
-					}
+			} else if ( object instanceof THREE.Mesh ) {
+
+				material = object.material;
 
-					// create separate VBOs per geometry chunk
+				if ( geometry.geometryGroups === undefined ) {
 
-					for ( g in geometry.geometryGroups ) {
+					sortFacesByMaterial( geometry, material );
 
-						geometryGroup = geometry.geometryGroups[ g ];
+				}
 
-						// initialise VBO on the first access
+				// create separate VBOs per geometry chunk
 
-						if ( ! geometryGroup.__webglVertexBuffer ) {
+				for ( g in geometry.geometryGroups ) {
 
-							createMeshBuffers( geometryGroup );
-							initMeshBuffers( geometryGroup, object );
+					geometryGroup = geometry.geometryGroups[ g ];
 
-							geometry.verticesNeedUpdate = true;
-							geometry.morphTargetsNeedUpdate = true;
-							geometry.elementsNeedUpdate = true;
-							geometry.uvsNeedUpdate = true;
-							geometry.normalsNeedUpdate = true;
-							geometry.tangentsNeedUpdate = true;
-							geometry.colorsNeedUpdate = true;
+					// initialise VBO on the first access
 
-						}
+					if ( ! geometryGroup.__webglVertexBuffer ) {
 
-					}
+						createMeshBuffers( geometryGroup );
+						initMeshBuffers( geometryGroup, object );
 
-				} else if ( geometry instanceof THREE.BufferGeometry ) {
+						geometry.verticesNeedUpdate = true;
+						geometry.morphTargetsNeedUpdate = true;
+						geometry.elementsNeedUpdate = true;
+						geometry.uvsNeedUpdate = true;
+						geometry.normalsNeedUpdate = true;
+						geometry.tangentsNeedUpdate = true;
+						geometry.colorsNeedUpdate = true;
 
-					initDirectBuffers( geometry );
+					}
 
 				}
 
 			} else if ( object instanceof THREE.Ribbon ) {
 
-				geometry = object.geometry;
-
 				if ( ! geometry.__webglVertexBuffer ) {
 
 					createRibbonBuffers( geometry );
@@ -4694,47 +4567,26 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			} else if ( object instanceof THREE.Line ) {
 
-				geometry = object.geometry;
-
 				if ( ! geometry.__webglVertexBuffer ) {
 
-					if ( geometry instanceof THREE.Geometry ) {
-
-						createLineBuffers( geometry );
-						initLineBuffers( geometry, object );
-
-						geometry.verticesNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
-						geometry.lineDistancesNeedUpdate = true;
-
-					} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-						initDirectBuffers( geometry );
+					createLineBuffers( geometry );
+					initLineBuffers( geometry, object );
 
-					}
+					geometry.verticesNeedUpdate = true;
+					geometry.colorsNeedUpdate = true;
+					geometry.lineDistancesNeedUpdate = true;
 
 				}
 
 			} else if ( object instanceof THREE.ParticleSystem ) {
 
-				geometry = object.geometry;
-
 				if ( ! geometry.__webglVertexBuffer ) {
 
-					if ( geometry instanceof THREE.Geometry ) {
-
-						createParticleBuffers( geometry );
-						initParticleBuffers( geometry, object );
-
-						geometry.verticesNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
-
-					} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-						initDirectBuffers( geometry );
-
-					}
+					createParticleBuffers( geometry );
+					initParticleBuffers( geometry, object );
 
+					geometry.verticesNeedUpdate = true;
+					geometry.colorsNeedUpdate = true;
 
 				}
 
@@ -4795,13 +4647,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		objlist.push(
 			{
-				id: null,
 				buffer: buffer,
 				object: object,
 				opaque: null,
-				transparent: null,
-				render: false,
-				z: 0
+				transparent: null
 			}
 		);
 
@@ -4826,66 +4675,49 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var geometry = object.geometry,
 			geometryGroup, customAttributesDirty, material;
 
-		if ( object instanceof THREE.Mesh ) {
-
-			if ( geometry instanceof THREE.BufferGeometry ) {
-
-				if ( geometry.verticesNeedUpdate || geometry.elementsNeedUpdate ||
-					 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
-					 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate ) {
+		if ( geometry instanceof THREE.BufferGeometry ) {
 
-					setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
+			setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
 
-				}
+		} else if ( object instanceof THREE.Mesh ) {
 
-				geometry.verticesNeedUpdate = false;
-				geometry.elementsNeedUpdate = false;
-				geometry.uvsNeedUpdate = false;
-				geometry.normalsNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-				geometry.tangentsNeedUpdate = false;
+			// check all geometry groups
 
-			} else {
+			for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
 
-				// check all geometry groups
+				geometryGroup = geometry.geometryGroupsList[ i ];
 
-				for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
+				material = getBufferMaterial( object, geometryGroup );
 
-					geometryGroup = geometry.geometryGroupsList[ i ];
+				if ( geometry.buffersNeedUpdate ) {
 
-					material = getBufferMaterial( object, geometryGroup );
-
-					if ( geometry.buffersNeedUpdate ) {
-
-						initMeshBuffers( geometryGroup, object );
-
-					}
+					initMeshBuffers( geometryGroup, object );
 
-					customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+				}
 
-					if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
-						 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
-						 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
+				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
 
-						setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
+				if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
+					 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
+					 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
 
-					}
+					setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
 
 				}
 
-				geometry.verticesNeedUpdate = false;
-				geometry.morphTargetsNeedUpdate = false;
-				geometry.elementsNeedUpdate = false;
-				geometry.uvsNeedUpdate = false;
-				geometry.normalsNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-				geometry.tangentsNeedUpdate = false;
+			}
 
-				geometry.buffersNeedUpdate = false;
+			geometry.verticesNeedUpdate = false;
+			geometry.morphTargetsNeedUpdate = false;
+			geometry.elementsNeedUpdate = false;
+			geometry.uvsNeedUpdate = false;
+			geometry.normalsNeedUpdate = false;
+			geometry.colorsNeedUpdate = false;
+			geometry.tangentsNeedUpdate = false;
 
-				material.attributes && clearCustomAttributes( material );
+			geometry.buffersNeedUpdate = false;
 
-			}
+			material.attributes && clearCustomAttributes( material );
 
 		} else if ( object instanceof THREE.Ribbon ) {
 
@@ -4907,68 +4739,39 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		} else if ( object instanceof THREE.Line ) {
 
-      if ( geometry instanceof THREE.BufferGeometry ) {
-
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
-
-					setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-
-			} else {
-
-        material = getBufferMaterial( object, geometry );
+			material = getBufferMaterial( object, geometry );
 
-        customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
 
-        if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) {
+			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) {
 
-          setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
+				setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
 
-        }
+			}
 
-        geometry.verticesNeedUpdate = false;
-        geometry.colorsNeedUpdate = false;
-        geometry.lineDistancesNeedUpdate = false;
+			geometry.verticesNeedUpdate = false;
+			geometry.colorsNeedUpdate = false;
+			geometry.lineDistancesNeedUpdate = false;
 
-        material.attributes && clearCustomAttributes( material );
+			material.attributes && clearCustomAttributes( material );
 
-      }
 
 		} else if ( object instanceof THREE.ParticleSystem ) {
 
-			if ( geometry instanceof THREE.BufferGeometry ) {
-
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
-
-					setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-
-			} else {
-
-				material = getBufferMaterial( object, geometry );
-
-				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
+			material = getBufferMaterial( object, geometry );
 
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
+			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
 
-					setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
+			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
 
-				}
+				setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
 
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
+			}
 
-				material.attributes && clearCustomAttributes( material );
+			geometry.verticesNeedUpdate = false;
+			geometry.colorsNeedUpdate = false;
 
-			}
+			material.attributes && clearCustomAttributes( material );
 
 		}
 
@@ -7476,17 +7279,17 @@ THREE.WebGLRenderer = function ( parameters ) {
 			console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
 
 		}
-		
+
 		if ( _gl.getShaderPrecisionFormat === undefined ) {
-			
-			_gl.getShaderPrecisionFormat = function() { 
-				
+
+			_gl.getShaderPrecisionFormat = function() {
+
 				return {
 					"rangeMin"  : 1,
 					"rangeMax"  : 1,
 					"precision" : 1
 				};
-				
+
 			}
 		}
 

+ 58 - 149
src/renderers/WebGLRenderer2.js

@@ -105,7 +105,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	_usedTextureUnits = 0,
 
-	// GL state 
+	// GL state
 
 	_viewportX = 0,
 	_viewportY = 0,
@@ -486,54 +486,31 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		var attributes = geometry.attributes;
 
-		var index = attributes[ "index" ];
-		var position = attributes[ "position" ];
-		var normal = attributes[ "normal" ];
-		var uv = attributes[ "uv" ];
-		var color = attributes[ "color" ];
-		var tangent = attributes[ "tangent" ];
+		var attributeName, attributeItem;
 
-		if ( geometry.elementsNeedUpdate && index !== undefined ) {
+		for ( attributeName in attributes ) {
 
-			renderer.setDynamicIndexBuffer(	index.buffer, index.array);
+			attributeItem = attributes[ attributeName ];
 
-		}
-
-		if ( geometry.verticesNeedUpdate && position !== undefined ) {
-
-			renderer.setDynamicArrayBuffer( position.buffer,  position.array);
-
-		}
-
-		if ( geometry.normalsNeedUpdate && normal !== undefined ) {
-
-			renderer.setDynamicArrayBuffer( normal.buffer,  normal.array);
-
-		}
+			if ( attributeItem.needsUpdate ) {
 
-		if ( geometry.uvsNeedUpdate && uv !== undefined ) {
+				if ( attributeName === 'index' ) {
 
-			renderer.setDynamicArrayBuffer( uv.buffer,  uv.array);
+					renderer.setDynamicIndexBuffer(	attributeItem.buffer, attributeItem.array );
 
-		}
-
-		if ( geometry.colorsNeedUpdate && color !== undefined ) {
-
-			renderer.setDynamicArrayBuffer( color.buffer,  color.array);
-
-		}
+				} else {
 
-		if ( geometry.tangentsNeedUpdate && tangent !== undefined ) {
+					renderer.setDynamicArrayBuffer( attributeItem.buffer,  attributeItem.array );
 
-			renderer.setDynamicArrayBuffer( tangent.buffer, tangent.array);
+				}
 
-		}
+				attributeItem.needsUpdate = false;
 
-		if ( dispose ) {
+			}
 
-			for ( var i in geometry.attributes ) {
+			if ( dispose && ! attributeItem.dynamic ) {
 
-				delete geometry.attributes[ i ].array;
+				delete attributeItem.array;
 
 			}
 
@@ -601,7 +578,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				}
 
 			}
-			
+
 			renderer.setDynamicArrayBuffer( object.__webglNormalBuffer, object.normalArray);
 			renderer.setFloatAttribute(program.attributes.normal, object.__webglNormalBuffer, 3, 0);
 
@@ -630,11 +607,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( material.visible === false ) return;
 
-		var program, attributes, linewidth, primitives, a, attribute;
+		var program, programAttributes, linewidth, primitives, a, attribute, geometryAttributes;
+		var attributeItem, attributeName, attributePointer, attributeSize;
 
 		program = setProgram( camera, lights, fog, material, object );
 
-		attributes = program.attributes;
+		programAttributes = program.attributes;
+		geometryAttributes = geometry.attributes;
 
 		var updateBuffers = false,
 			wireframeBit = material.wireframe ? 1 : 0,
@@ -657,7 +636,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( object instanceof THREE.Mesh ) {
 
-			var index = geometry.attributes[ "index" ];
+			var index = geometryAttributes[ "index" ];
 
 			// indexed triangles
 
@@ -677,60 +656,25 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					if ( updateBuffers ) {
 
-						// vertices
-
-						var position = geometry.attributes[ "position" ];
-						var positionSize = position.itemSize;
-						renderer.setFloatAttribute(attributes.position , position.buffer, positionSize, startIndex * positionSize * 4);
-
-						// normals
-
-						var normal = geometry.attributes[ "normal" ];
-
-						if ( attributes.normal >= 0 && normal ) {
-
-							var normalSize = normal.itemSize;
-							renderer.setFloatAttribute(attributes.normal , normal.buffer, normalSize, startIndex * normalSize * 4);
-
-						}
-
-						// uvs
-
-						var uv = geometry.attributes[ "uv" ];
-
-						if ( attributes.uv >= 0 && uv ) {
-
-							var uvSize = uv.itemSize;
-							renderer.setFloatAttribute(attributes.uv , uv.buffer, uvSize, startIndex * uvSize * 4);
-
-						}
-
-						// colors
-
-						var color = geometry.attributes[ "color" ];
-
-						if ( attributes.color >= 0 && color ) {
+						for ( attributeName in geometryAttributes ) {
 
-							var colorSize = color.itemSize;
-							renderer.setFloatAttribute(attributes.color , color.buffer, colorSize, startIndex * colorSize * 4);
+							if ( attributeName === 'index' ) continue;
 
-						}
-
-						// tangents
+							attributePointer = programAttributes[ attributeName ];
+							attributeItem = geometryAttributes[ attributeName ];
+							attributeSize = attributeItem.itemSize;
 
-						var tangent = geometry.attributes[ "tangent" ];
+							if ( attributePointer >= 0 ) {
 
-						if ( attributes.tangent >= 0 && tangent ) {
+								renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, startIndex * attributeSize * 4 );
 
-							var tangentSize = tangent.itemSize;
-							renderer.setFloatAttribute(attributes.tangent , tangent.buffer, tangentSize, startIndex * tangentSize * 4);
+							}
 
 						}
-
 					}
 
 					// render indexed triangles
-					
+
 					renderer.drawTriangleElements(index.buffer, offsets[ i ].count, offsets[ i ].start * 2);
 
 					_this.info.render.calls ++;
@@ -745,59 +689,26 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( updateBuffers ) {
 
-					// vertices
-
-					var position = geometry.attributes[ "position" ];
-					var positionSize = position.itemSize;
-					renderer.setFloatAttribute(attributes.position , position.buffer, positionSize, 0);
-
-					// normals
-
-					var normal = geometry.attributes[ "normal" ];
-
-					if ( attributes.normal >= 0 && normal ) {
-
-						var normalSize = normal.itemSize;
-						renderer.setFloatAttribute(attributes.normal , normal.buffer, normalSize, 0);
-
-					}
-
-					// uvs
-
-					var uv = geometry.attributes[ "uv" ];
-
-					if ( attributes.uv >= 0 && uv ) {
-
-						var uvSize = uv.itemSize;
-						renderer.setFloatAttribute(attributes.uv , uv.buffer, uvSize, 0);
-
-					}
-
-					// colors
+					for ( attributeName in geometryAttributes ) {
 
-					var color = geometry.attributes[ "color" ];
+						attributePointer = programAttributes[ attributeName ];
+						attributeItem = geometryAttributes[ attributeName ];
+						attributeSize = attributeItem.itemSize;
 
-					if ( attributes.color >= 0 && color ) {
+						if ( attributePointer >= 0 ) {
 
-						var colorSize = color.itemSize;
-						renderer.setFloatAttribute(attributes.color , color.buffer, colorSize, 0);
+							renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
 
-					}
-
-					// tangents
-
-					var tangent = geometry.attributes[ "tangent" ];
-
-					if ( attributes.tangent >= 0 && tangent ) {
-
-						var tangentSize = tangent.itemSize;
-						renderer.setFloatAttribute(attributes.tangent , tangent.buffer, tangentSize, 0);
+						}
 
 					}
 
 				}
 
+				var position = geometry.attributes[ "position" ];
+
 				// render non-indexed triangles
+
 				renderer.drawTriangles( position.numItems / 3)
 
 				_this.info.render.calls ++;
@@ -812,23 +723,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( updateBuffers ) {
 
-				// vertices
+				for ( attributeName in geometryAttributes ) {
 
-				var position = geometry.attributes[ "position" ];
-				var positionSize = position.itemSize;
-				renderer.setFloatAttribute(attributes.position , position.buffer, positionSize, 0);
-
-				// colors
+					attributePointer = programAttributes[ attributeName ];
+					attributeItem = geometryAttributes[ attributeName ];
+					attributeSize = attributeItem.itemSize;
 
-				var color = geometry.attributes[ "color" ];
+					if ( attributePointer >= 0 ) {
 
-				if ( attributes.color >= 0 && color ) {
+						renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
 
-					var colorSize = color.itemSize;
-					renderer.setFloatAttribute(attributes.color , color.buffer, colorSize, 0);
+					}
 
 				}
 
+				var position = geometryAttributes[ "position" ];
+
 				// render particles
 				renderer.drawPoints(position.numItems / 3);
 
@@ -841,23 +751,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( updateBuffers ) {
 
-				// vertices
+				for ( attributeName in geometryAttributes ) {
 
-				var position = geometry.attributes[ "position" ];
-				var positionSize = position.itemSize;
-				renderer.setFloatAttribute(attributes.position , position.buffer, positionSize, 0);
+					attributePointer = programAttributes[ attributeName ];
+					attributeItem = geometryAttributes[ attributeName ];
+					attributeSize = attributeItem.itemSize;
 
-				// colors
+					if ( attributePointer >= 0 ) {
 
-				var color = geometry.attributes[ "color" ];
+						renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
 
-				if ( attributes.color >= 0 && color ) {
-
-					var colorSize = color.itemSize;
-					renderer.setFloatAttribute(attributes.color , color.buffer, colorSize, 0);
+					}
 
 				}
 
+				var position = geometryAttributes[ "position" ];
+
 				// render lines
 				renderer.setLineWidth( material.linewidth );
 				renderer.drawLineStrip(position.numItems / 3);
@@ -3111,7 +3020,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				if ( ! light.visible ) continue;
 
 				_direction.getPositionFromMatrix( light.matrixWorld );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );					
+				_vector3.getPositionFromMatrix( light.target.matrixWorld );
 				_direction.sub( _vector3 );
 				_direction.normalize();