2
0
Эх сурвалжийг харах

Merge pull request #4986 from gero3/removeHackery

Remove hackery + fix visibility in webglrenderer
Mr.doob 11 жил өмнө
parent
commit
350eee2cbb

+ 1 - 1
editor/index.html

@@ -9,7 +9,7 @@
 		<link href="css/types.css" rel="stylesheet" />
 		<link id="theme" href="css/light.css" rel="stylesheet" />
 
-		<script src="../build/three.min.js"></script>
+		<script src="../build/three.js"></script>
 		<script src="../examples/js/libs/system.min.js"></script>
 
 		<script src="../examples/js/controls/EditorControls.js"></script>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 59 - 30
src/extras/renderers/plugins/DepthPassPlugin.js

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

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

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

+ 218 - 184
src/renderers/WebGLRenderer.js

@@ -28,6 +28,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	_clearColor = new THREE.Color( 0x000000 ),
 	_clearAlpha = 0;
+	
+	var opaqueObjects = [];
+	var transparentObjects = [];
+	var _sortObjects = true;
 
 	// public properties
 
@@ -3216,6 +3220,20 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	function reversePainterSortStable ( a, b ) {
+
+		if ( a.z !== b.z ) {
+
+			return a.z - b.z;
+
+		} else {
+
+			return a.id - b.id;
+
+		}
+
+	};
+
 	function numericalSort ( a, b ) {
 
 		return b[ 0 ] - a[ 0 ];
@@ -3285,52 +3303,17 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		// set matrices for regular objects (frustum culled)
 
-		renderList = scene.__webglObjects;
-
-		for ( i = 0, il = renderList.length; i < il; i ++ ) {
-
-			webglObject = renderList[ i ];
-			object = webglObject.object;
-
-			webglObject.id = i;
-			webglObject.render = false;
-
-			if ( object.visible ) {
-
-				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
-
-					setupMatrices( object, camera );
-
-					unrollBufferMaterial( webglObject );
-
-					webglObject.render = true;
-
-					if ( this.sortObjects === true ) {
-
-						if ( object.renderDepth !== null ) {
-
-							webglObject.z = object.renderDepth;
-
-						} else {
-
-							_vector3.setFromMatrixPosition( object.matrixWorld );
-							_vector3.applyProjection( _projScreenMatrix );
-
-							webglObject.z = _vector3.z;
-
-						}
-
-					}
-
-				}
-
-			}
-
-		}
+		
+		opaqueObjects.length = 0;
+		transparentObjects.length = 0;
+		_sortObjects = this.sortObjects;
+		
+		projectObject(scene,scene,camera);
 
 		if ( this.sortObjects ) {
 
-			renderList.sort( painterSortStable );
+			opaqueObjects.sort( painterSortStable );
+			transparentObjects.sort( reversePainterSortStable );
 
 		}
 
@@ -3362,7 +3345,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			this.setDepthWrite( material.depthWrite );
 			setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
 
-			renderObjects( scene.__webglObjects, false, '', camera, lights, fog, true, material );
+			renderObjects( opaqueObjects, camera, lights, fog, true, material );
+			renderObjects( transparentObjects, camera, lights, fog, true, material );
 			renderObjectsImmediate( scene.__webglObjectsImmediate, '', camera, lights, fog, false, material );
 
 		} else {
@@ -3373,12 +3357,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			this.setBlending( THREE.NoBlending );
 
-			renderObjects( scene.__webglObjects, true, 'opaque', camera, lights, fog, false, material );
+			renderObjects( opaqueObjects, camera, lights, fog, false, material );
 			renderObjectsImmediate( scene.__webglObjectsImmediate, 'opaque', camera, lights, fog, false, material );
 
 			// transparent pass (back-to-front order)
 
-			renderObjects( scene.__webglObjects, false, 'transparent', camera, lights, fog, true, material );
+			renderObjects( transparentObjects, camera, lights, fog, true, material );
 			renderObjectsImmediate( scene.__webglObjectsImmediate, 'transparent', camera, lights, fog, true, material );
 
 		}
@@ -3404,6 +3388,54 @@ THREE.WebGLRenderer = function ( parameters ) {
 		// _gl.finish();
 
 	};
+	
+	function projectObject(scene, object,camera){
+		
+		if ( object.visible ) {
+			
+			var webglObjects = scene.__webglObjects[object.id];
+			
+			if (webglObjects && (object.frustumCulled === false || _frustum.intersectsObject( object ) === true) ) {
+				
+				updateObject(scene, object);
+				
+				setupMatrices( object, camera );
+				
+				for (var i = 0, l = webglObjects.length; i < l; i++){
+					
+					var webglObject = webglObjects[i];
+					
+					unrollBufferMaterial( webglObject );
+					
+
+					webglObject.render = true;
+	
+					if ( _sortObjects === true ) {
+	
+						if ( object.renderDepth !== null ) {
+	
+							webglObject.z = object.renderDepth;
+	
+						} else {
+	
+							_vector3.setFromMatrixPosition( object.matrixWorld );
+							_vector3.applyProjection( _projScreenMatrix );
+	
+							webglObject.z = _vector3.z;
+	
+						}
+	
+					}
+				}
+			}
+			
+			for(var i = 0, l = object.children.length; i < l; i++) {
+				projectObject(scene, object.children[i],camera);
+			}
+				
+		}
+				
+	}
 
 	function renderPlugins( plugins, scene, camera ) {
 
@@ -3447,61 +3479,44 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-	function renderObjects( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
-
-		var webglObject, object, buffer, material, start, end, delta;
-
-		if ( reverse ) {
-
-			start = renderList.length - 1;
-			end = - 1;
-			delta = - 1;
-
-		} else {
+	function renderObjects( renderList, camera, lights, fog, useBlending, overrideMaterial ) {
 
-			start = 0;
-			end = renderList.length;
-			delta = 1;
-		}
+		var webglObject, object, buffer, material;
 
-		for ( var i = start; i !== end; i += delta ) {
+		for ( var i = renderList.length - 1; i !== - 1; i -- ) {
 
 			webglObject = renderList[ i ];
 
-			if ( webglObject.render ) {
-
-				object = webglObject.object;
-				buffer = webglObject.buffer;
+			object = webglObject.object;
+			buffer = webglObject.buffer;
 
-				if ( overrideMaterial ) {
+			if ( overrideMaterial ) {
 
-					material = overrideMaterial;
+				material = overrideMaterial;
 
-				} else {
-
-					material = webglObject[ materialType ];
+			} else {
 
-					if ( ! material ) continue;
+				material = webglObject.material;
 
-					if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
+				if ( ! material ) continue;
 
-					_this.setDepthTest( material.depthTest );
-					_this.setDepthWrite( material.depthWrite );
-					setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
+				if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
 
-				}
+				_this.setDepthTest( material.depthTest );
+				_this.setDepthWrite( material.depthWrite );
+				setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
 
-				_this.setMaterialFaces( material );
+			}
 
-				if ( buffer instanceof THREE.BufferGeometry ) {
+			_this.setMaterialFaces( material );
 
-					_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
+			if ( buffer instanceof THREE.BufferGeometry ) {
 
-				} else {
+				_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
 
-					_this.renderBuffer( camera, lights, fog, material, buffer, object );
+			} else {
 
-				}
+				_this.renderBuffer( camera, lights, fog, material, buffer, object );
 
 			}
 
@@ -3601,13 +3616,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( material.transparent ) {
 
-				globject.transparent = material;
-				globject.opaque = null;
+				globject.material = material; 
+				transparentObjects.push(globject);
 
 			} else {
 
-				globject.opaque = material;
-				globject.transparent = null;
+				globject.material = material; 
+				opaqueObjects.push(globject);
 
 			}
 
@@ -3617,13 +3632,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( material.transparent ) {
 
-					globject.transparent = material;
-					globject.opaque = null;
+					globject.material = material; 
+					transparentObjects.push(globject);
 
 				} else {
 
-					globject.opaque = material;
-					globject.transparent = null;
+					globject.material = material; 
+					opaqueObjects.push(globject);
 
 				}
 
@@ -3639,7 +3654,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( ! scene.__webglObjects ) {
 
-			scene.__webglObjects = [];
+			scene.__webglObjects = {};
 			scene.__webglObjectsImmediate = [];
 			scene.__webglSprites = [];
 			scene.__webglFlares = [];
@@ -3660,37 +3675,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		// update must be called after objects adding / removal
-
-		for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
-
-			var object = scene.__webglObjects[ o ].object;
-
-			// TODO: Remove this hack (WebGLRenderer refactoring)
-
-			if ( object.__webglInit === undefined ) {
-
-				if ( object.__webglActive !== undefined ) {
-
-					removeObject( object, scene );
-
-				}
-
-				addObject( object, scene );
-
-			}
-
-			updateObject( object );
-
-		}
-
 	};
 
 	// Objects adding
 
 	function addObject( object, scene ) {
 
-		var g, geometry, material, geometryGroup;
+		var g, geometry, geometryGroup;
 
 		if ( object.__webglInit === undefined ) {
 
@@ -3699,80 +3690,55 @@ THREE.WebGLRenderer = function ( parameters ) {
 			object._modelViewMatrix = new THREE.Matrix4();
 			object._normalMatrix = new THREE.Matrix3();
 
-			geometry = object.geometry;
-
-			if ( geometry === undefined ) {
-
-				// ImmediateRenderObject
-
-			} else if ( geometry.__webglInit === undefined ) {
-
-				geometry.__webglInit = true;
-				geometry.addEventListener( 'dispose', onGeometryDispose );
-
-				if ( geometry instanceof THREE.BufferGeometry ) {
-
-					initDirectBuffers( geometry );
-
-				} else if ( object instanceof THREE.Mesh ) {
-
-					material = object.material;
-
-					if ( geometry.geometryGroups === undefined ) {
-
-						geometry.makeGroups( material instanceof THREE.MeshFaceMaterial, _glExtensionElementIndexUint ? 4294967296 : 65535  );
-
-					}
-
-					// create separate VBOs per geometry chunk
+		}
+		
+		geometry = object.geometry;
+		
+		if ( geometry === undefined ) {
 
-					for ( var i = 0,l = geometry.geometryGroupsList.length; i<l;i++ ) {
-	
-						geometryGroup = geometry.geometryGroupsList[ i ];
+			// ImmediateRenderObject
 
-						// initialise VBO on the first access
+		} else if ( geometry.__webglInit === undefined ) {
 
-						if ( ! geometryGroup.__webglVertexBuffer ) {
+			geometry.__webglInit = true;
+			geometry.addEventListener( 'dispose', onGeometryDispose );
 
-							createMeshBuffers( geometryGroup );
-							initMeshBuffers( geometryGroup, object );
+			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.Mesh ) {
+				
+				if ( object.__webglActive !== undefined ) {
 
-					}
+					removeObject( object, scene );
 
-				} else if ( object instanceof THREE.Line ) {
+				}
+				
+				initGeometryGroups(scene, object, geometry);
 
-					if ( ! geometry.__webglVertexBuffer ) {
+			} else if ( object instanceof THREE.Line ) {
 
-						createLineBuffers( geometry );
-						initLineBuffers( geometry, object );
+				if ( ! geometry.__webglVertexBuffer ) {
 
-						geometry.verticesNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
-						geometry.lineDistancesNeedUpdate = true;
+					createLineBuffers( geometry );
+					initLineBuffers( geometry, object );
 
-					}
+					geometry.verticesNeedUpdate = true;
+					geometry.colorsNeedUpdate = true;
+					geometry.lineDistancesNeedUpdate = true;
 
-				} else if ( object instanceof THREE.PointCloud ) {
+				}
 
-					if ( ! geometry.__webglVertexBuffer ) {
+			} else if ( object instanceof THREE.PointCloud ) {
 
-						createParticleBuffers( geometry );
-						initParticleBuffers( geometry, object );
+				if ( ! geometry.__webglVertexBuffer ) {
 
-						geometry.verticesNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
+					createParticleBuffers( geometry );
+					initParticleBuffers( geometry, object );
 
-					}
+					geometry.verticesNeedUpdate = true;
+					geometry.colorsNeedUpdate = true;
 
 				}
 
@@ -3780,7 +3746,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		if ( object.__webglActive === undefined ) {
+		if ( object.__webglActive === undefined) {
 
 			if ( object instanceof THREE.Mesh ) {
 
@@ -3795,11 +3761,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 					for ( var i = 0,l = geometry.geometryGroupsList.length; i<l;i++ ) {
 	
 						geometryGroup = geometry.geometryGroupsList[ i ];
-
 						addBuffer( scene.__webglObjects, geometryGroup, object );
-
+						
 					}
-
 				}
 
 			} else if ( object instanceof THREE.Line ||
@@ -3827,16 +3791,65 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 
 	};
+	
+	function initGeometryGroups(scene,object,geometry) {
+		
+		var g, geometryGroup, material,addBuffers = false;
+		material = object.material;
 
-	function addBuffer( objlist, buffer, object ) {
+		if ( geometry.geometryGroups === undefined ) {
+			
+			delete scene.__webglObjects[object.id];
+			geometry.makeGroups( material instanceof THREE.MeshFaceMaterial, _glExtensionElementIndexUint ? 4294967296 : 65535  );
+			
+		}
 
-		objlist.push(
+		// create separate VBOs per geometry chunk
+
+		for ( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
+
+			geometryGroup = geometry.geometryGroupsList[ i ];
+
+			// initialise VBO on the first access
+
+			if ( ! geometryGroup.__webglVertexBuffer ) {
+
+				createMeshBuffers( geometryGroup );
+				initMeshBuffers( geometryGroup, object );
+
+				geometry.verticesNeedUpdate = true;
+				geometry.morphTargetsNeedUpdate = true;
+				geometry.elementsNeedUpdate = true;
+				geometry.uvsNeedUpdate = true;
+				geometry.normalsNeedUpdate = true;
+				geometry.tangentsNeedUpdate = true;
+				geometry.colorsNeedUpdate = true;
+				
+				addBuffers = true;
+				
+			} else {
+				
+				addBuffers = false;
+				
+			}
+			
+			if ( addBuffers || object.__webglActive === undefined ) {
+				addBuffer( scene.__webglObjects, geometryGroup, object );
+			}
+
+		}
+		object.__webglActive = true;
+	}
+	
+	function addBuffer( objlist, buffer, object ) {
+		var id = object.id;
+		objlist[id] = objlist[id] || [];
+		objlist[id].push(
 			{
 				id: null,
 				buffer: buffer,
 				object: object,
-				opaque: null,
-				transparent: null,
+				material: null,
 				z: 0
 			}
 		);
@@ -3859,7 +3872,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	// Objects updates
 
-	function updateObject( object ) {
+	function updateObject(scene, object ) {
 
 		var geometry = object.geometry,
 			geometryGroup, customAttributesDirty, material;
@@ -3871,6 +3884,19 @@ THREE.WebGLRenderer = function ( parameters ) {
 		} else if ( object instanceof THREE.Mesh ) {
 
 			// check all geometry groups
+			if ( geometry.buffersNeedUpdate ) {
+				
+				if ( geometry instanceof THREE.BufferGeometry ) {
+
+					initDirectBuffers( geometry );
+
+				} else if ( object instanceof THREE.Mesh ) {
+				
+					initGeometryGroups(scene, object,geometry);
+					
+				}
+				
+			}
 
 			for ( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
 
@@ -3980,7 +4006,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 			 object instanceof THREE.PointCloud ||
 			 object instanceof THREE.Line ) {
 
-			removeInstances( scene.__webglObjects, object );
+			removeInstancesWebglObjects( scene.__webglObjects, object );
 
 		} else if ( object instanceof THREE.Sprite ) {
 
@@ -3999,6 +4025,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 		delete object.__webglActive;
 
 	};
+	
+	
+
+	function removeInstancesWebglObjects( objlist, object ) {
+
+		delete objlist[object]; 
+
+	};
 
 	function removeInstances( objlist, object ) {