Browse Source

Merge pull request #6723 from fordacious/dev

Multiple Renders Fix
Ricardo Cabello 10 years ago
parent
commit
043268837f

+ 1 - 0
examples/index.html

@@ -313,6 +313,7 @@
 				"webgl_multiple_canvases_complex",
 				"webgl_multiple_canvases_complex",
 				"webgl_multiple_canvases_grid",
 				"webgl_multiple_canvases_grid",
 				"webgl_multiple_elements",
 				"webgl_multiple_elements",
+				"webgl_multiple_renderers",
 				"webgl_multiple_views",
 				"webgl_multiple_views",
 				"webgl_nearestneighbour",
 				"webgl_nearestneighbour",
 				"webgl_octree",
 				"webgl_octree",

+ 301 - 0
examples/webgl_multiple_renderers.html

@@ -0,0 +1,301 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - multiple Renderers - complex</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: #808080;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+
+				background-color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+
+			#container1, #container2, #container3 {
+				position: absolute;
+				border-style: solid;
+			}
+
+			#container1 {
+				width: 400px;
+				height: 200px;
+				left: 150px;
+			}
+
+			#container2 {
+				width: 400px;
+				height: 200px;
+				left: 150px;
+				top: 400px;
+			}
+
+			#container3 {
+				width: 300px;
+				height: 300px;
+				left: 75px;
+				top: 300px;
+  				box-shadow: 0px 0px 100px 0px #000;
+			}
+
+			a {
+
+				color: #0080ff;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<div id="container">
+			<div id="container1"></div>
+			<div id="container2"></div>
+			<div id="container3"></div>
+		</div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - multiple canvases - complex</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var apps = [];
+
+			var scene = createScene();
+
+			init();
+			animate();
+
+			function init() {
+
+				var container1 = document.getElementById( 'container1' );
+				var container2 = document.getElementById( 'container2' );
+				var container3 = document.getElementById( 'container3' );
+
+				var WIDTH = 800;
+				var HEIGHT = 600;
+
+				apps.push( new App( container1, WIDTH, HEIGHT ) );
+				apps.push( new App( container2, WIDTH, HEIGHT ) );
+				apps.push( new App( container3, WIDTH, HEIGHT ) );
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+			}
+
+			function animate() {
+
+				for ( var i = 0; i < apps.length; ++i ) {
+
+					apps[ i ].animate();
+
+				}
+
+				requestAnimationFrame( animate );
+
+			}
+
+			function onDocumentMouseMove (e) {
+
+				var container3 = document.getElementById( 'container3' );
+
+				container3.style.left = e.pageX - container3.clientWidth / 2 + "px"
+				container3.style.top = e.pageY - container3.clientHeight / 2 + "px"
+
+			}
+
+			function createScene () {
+
+				var mesh, group1, group2, group3, light;
+
+				scene = new THREE.Scene();
+
+				light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 0, 0, 1 ).normalize();
+				scene.add( light );
+
+				// shadow
+
+				var canvas = document.createElement( 'canvas' );
+				canvas.width = 128;
+				canvas.height = 128;
+
+				var context = canvas.getContext( '2d' );
+				var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
+				gradient.addColorStop( 0.1, 'rgba(210,210,210,1)' );
+				gradient.addColorStop( 1, 'rgba(255,255,255,1)' );
+
+				context.fillStyle = gradient;
+				context.fillRect( 0, 0, canvas.width, canvas.height );
+
+				var shadowTexture = new THREE.Texture( canvas );
+				shadowTexture.needsUpdate = true;
+
+				var shadowMaterial = new THREE.MeshBasicMaterial( { map: shadowTexture } );
+				var shadowGeo = new THREE.PlaneBufferGeometry( 300, 300, 1, 1 );
+
+				mesh = new THREE.Mesh( shadowGeo, shadowMaterial );
+				mesh.position.y = - 250;
+				mesh.rotation.x = - Math.PI / 2;
+				scene.add( mesh );
+
+				mesh = new THREE.Mesh( shadowGeo, shadowMaterial );
+				mesh.position.x = - 400;
+				mesh.position.y = - 250;
+				mesh.rotation.x = - Math.PI / 2;
+				scene.add( mesh );
+
+				mesh = new THREE.Mesh( shadowGeo, shadowMaterial );
+				mesh.position.x = 400;
+				mesh.position.y = - 250;
+				mesh.rotation.x = - Math.PI / 2;
+				scene.add( mesh );
+
+				var faceIndices = [ 'a', 'b', 'c' ];
+
+				var color, f1, f2, f3, p, vertexIndex,
+
+					radius = 200,
+
+					geometry1 = new THREE.IcosahedronGeometry( radius, 1 ),
+					geometry2 = new THREE.IcosahedronGeometry( radius, 1 ),
+					geometry3 = new THREE.IcosahedronGeometry( radius, 1 );
+
+				for ( var i = 0; i < geometry1.faces.length; i ++ ) {
+
+					f1 = geometry1.faces[ i ];
+					f2 = geometry2.faces[ i ];
+					f3 = geometry3.faces[ i ];
+
+					for( var j = 0; j < 3; j ++ ) {
+
+						vertexIndex = f1[ faceIndices[ j ] ];
+
+						p = geometry1.vertices[ vertexIndex ];
+
+						color = new THREE.Color( 0xffffff );
+						color.setHSL( ( p.y / radius + 1 ) / 2, 1.0, 0.5 );
+
+						f1.vertexColors[ j ] = color;
+
+						color = new THREE.Color( 0xffffff );
+						color.setHSL( 0.0, ( p.y / radius + 1 ) / 2, 0.5 );
+
+						f2.vertexColors[ j ] = color;
+
+						color = new THREE.Color( 0xffffff );
+						color.setHSL( 0.125 * vertexIndex / geometry1.vertices.length, 1.0, 0.5 );
+
+						f3.vertexColors[ j ] = color;
+
+					}
+
+				}
+
+				var materials = [
+
+					new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } ),
+					new THREE.MeshBasicMaterial( { color: 0x000000, shading: THREE.FlatShading, wireframe: true, transparent: true } )
+
+				];
+
+				group1 = THREE.SceneUtils.createMultiMaterialObject( geometry1, materials );
+				group1.position.x = -400;
+				group1.rotation.x = -1.87;
+				scene.add( group1 );
+
+				group2 = THREE.SceneUtils.createMultiMaterialObject( geometry2, materials );
+				group2.position.x = 400;
+				group2.rotation.x = 0;
+				scene.add( group2 );
+
+				group3 = THREE.SceneUtils.createMultiMaterialObject( geometry3, materials );
+				group3.position.x = 0;
+				group3.rotation.x = 0;
+				scene.add( group3 );
+
+				return scene;
+			}
+
+			function App( container, fullWidth, fullHeight ) {
+
+				var container, stats;
+
+				var camera, renderer;
+
+				var mouseX = 0, mouseY = 0;
+
+				var windowHalfX = window.innerWidth / 2;
+				var windowHalfY = window.innerHeight / 2;
+
+				init();
+
+				function init() {
+
+					camera = new THREE.PerspectiveCamera( 20, container.clientWidth / container.clientHeight, 1, 10000 );
+					camera.setViewOffset( fullWidth, fullHeight, container.offsetLeft, container.offsetTop, container.clientWidth, container.clientHeight );
+					camera.position.z = 1800;
+
+					renderer = new THREE.WebGLRenderer( { antialias: true } );
+					renderer.setClearColor( 0xffffff );
+					renderer.setPixelRatio( window.devicePixelRatio );
+					renderer.setSize( container.clientWidth, container.clientHeight );
+					container.appendChild( renderer.domElement );
+
+					stats = new Stats();
+					stats.domElement.style.position = 'absolute';
+					stats.domElement.style.top = '0px';
+					container.appendChild( stats.domElement );
+
+					document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+				}
+
+				function onDocumentMouseMove( event ) {
+
+					mouseX = ( event.clientX - windowHalfX );
+					mouseY = ( event.clientY - windowHalfY );
+
+				}
+
+				//
+
+				this.animate = function() {
+
+					render();
+					stats.update();
+
+				};
+
+				function render() {
+
+					camera.setViewOffset( fullWidth, fullHeight, container.offsetLeft, container.offsetTop, container.clientWidth, container.clientHeight );
+
+					camera.position.x += ( -mouseX - camera.position.x ) * 0.5;
+					camera.position.y += ( - mouseY - camera.position.y ) * 0.5;
+
+					camera.lookAt( scene.position );
+
+					renderer.render( scene, camera );
+
+				}
+			}
+
+		</script>
+
+	</body>
+</html>

+ 2 - 0
src/core/BufferAttribute.js

@@ -4,6 +4,8 @@
 
 
 THREE.BufferAttribute = function ( array, itemSize ) {
 THREE.BufferAttribute = function ( array, itemSize ) {
 
 
+	this.uuid = THREE.Math.generateUUID();
+
 	this.array = array;
 	this.array = array;
 	this.itemSize = itemSize;
 	this.itemSize = itemSize;
 
 

+ 2 - 0
src/core/InterleavedBuffer.js

@@ -4,6 +4,8 @@
 
 
 THREE.InterleavedBuffer = function ( array, stride, dynamic ) {
 THREE.InterleavedBuffer = function ( array, stride, dynamic ) {
 
 
+	this.uuid = THREE.Math.generateUUID();
+
 	this.array = array;
 	this.array = array;
 	this.stride = stride;
 	this.stride = stride;
 
 

+ 2 - 0
src/core/InterleavedBufferAttribute.js

@@ -4,6 +4,8 @@
 
 
 THREE.InterleavedBufferAttribute = function ( interleavedBuffer, itemSize, offset ) {
 THREE.InterleavedBufferAttribute = function ( interleavedBuffer, itemSize, offset ) {
 
 
+	this.uuid = THREE.Math.generateUUID();
+
 	this.data = interleavedBuffer;
 	this.data = interleavedBuffer;
 	this.itemSize = itemSize;
 	this.itemSize = itemSize;
 	this.offset = offset;
 	this.offset = offset;

+ 2 - 0
src/renderers/WebGLRenderTarget.js

@@ -5,6 +5,8 @@
 
 
 THREE.WebGLRenderTarget = function ( width, height, options ) {
 THREE.WebGLRenderTarget = function ( width, height, options ) {
 
 
+	this.uuid = THREE.Math.generateUUID();
+
 	this.width = width;
 	this.width = width;
 	this.height = height;
 	this.height = height;
 
 

+ 128 - 85
src/renderers/WebGLRenderer.js

@@ -32,6 +32,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 	_clearColor = new THREE.Color( 0x000000 ),
 	_clearColor = new THREE.Color( 0x000000 ),
 	_clearAlpha = 0;
 	_clearAlpha = 0;
 
 
+	var webGLProps = new THREE.WebGLProperties();
+
 	var lights = [];
 	var lights = [];
 
 
 	var opaqueObjects = [];
 	var opaqueObjects = [];
@@ -182,6 +184,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			setDefaultGLState();
 			setDefaultGLState();
 
 
 			objects.objects = {};
 			objects.objects = {};
+			objects.webGLProps.deleteAll();
+			webGLProps.deleteAll();
 
 
 		}, false);
 		}, false);
 
 
@@ -640,61 +644,60 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	var deallocateTexture = function ( texture ) {
 	var deallocateTexture = function ( texture ) {
 
 
-		if ( texture.image && texture.image.__webglTextureCube ) {
+		var textureWebGLProperties = webGLProps.get( texture );
 
 
-			// cube texture
+		if ( texture.image && textureWebGLProperties.__image__webglTextureCube ) {
 
 
-			_gl.deleteTexture( texture.image.__webglTextureCube );
+			// cube texture
 
 
-			delete texture.image.__webglTextureCube;
+			_gl.deleteTexture( textureWebGLProperties.__image__webglTextureCube );
 
 
 		} else {
 		} else {
 
 
 			// 2D texture
 			// 2D texture
 
 
-			if ( texture.__webglInit === undefined ) return;
-
-			_gl.deleteTexture( texture.__webglTexture );
+			if ( textureWebGLProperties.__webglInit === undefined ) return;
 
 
-			delete texture.__webglTexture;
-			delete texture.__webglInit;
+			_gl.deleteTexture( textureWebGLProperties.__webglTexture );
 
 
 		}
 		}
 
 
+		// remove all webgl properties
+		delete webGLProps.delete( texture );
+
 	};
 	};
 
 
 	var deallocateRenderTarget = function ( renderTarget ) {
 	var deallocateRenderTarget = function ( renderTarget ) {
 
 
-		if ( ! renderTarget || renderTarget.__webglTexture === undefined ) return;
+		var renderTargetWebGLProperties = webGLProps.get( renderTarget );
 
 
-		_gl.deleteTexture( renderTarget.__webglTexture );
+		if ( ! renderTarget || renderTargetWebGLProperties.__webglTexture === undefined ) return;
 
 
-		delete renderTarget.__webglTexture;
+		_gl.deleteTexture( renderTargetWebGLProperties.__webglTexture );
 
 
 		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 
 
 			for ( var i = 0; i < 6; i ++ ) {
 			for ( var i = 0; i < 6; i ++ ) {
 
 
-				_gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
-				_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
+				_gl.deleteFramebuffer( renderTargetWebGLProperties.__webglFramebuffer[ i ] );
+				_gl.deleteRenderbuffer( renderTargetWebGLProperties.__webglRenderbuffer[ i ] );
 
 
 			}
 			}
 
 
 		} else {
 		} else {
 
 
-			_gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
-			_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
+			_gl.deleteFramebuffer( renderTargetWebGLProperties.__webglFramebuffer );
+			_gl.deleteRenderbuffer( renderTargetWebGLProperties.__webglRenderbuffer );
 
 
 		}
 		}
 
 
-		delete renderTarget.__webglFramebuffer;
-		delete renderTarget.__webglRenderbuffer;
+		delete webGLProps.delete( renderTargetWebGLProperties );
 
 
 	};
 	};
 
 
 	var deallocateMaterial = function ( material ) {
 	var deallocateMaterial = function ( material ) {
 
 
-		var program = material.program.program;
+		var program = webGLProps.get( material ).program.program;
 
 
 		if ( program === undefined ) return;
 		if ( program === undefined ) return;
 
 
@@ -753,6 +756,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		}
 		}
 
 
+		delete webGLProps.delete( material );
+
 	};
 	};
 
 
 	// Buffer rendering
 	// Buffer rendering
@@ -761,16 +766,18 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		state.initAttributes();
 		state.initAttributes();
 
 
-		if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
-		if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
-		if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
-		if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
+		var objectWebGLProperties = webGLProps.get( object );
+
+		if ( object.hasPositions && ! objectWebGLProperties.__webglVertexBuffer ) objectWebGLProperties.__webglVertexBuffer = _gl.createBuffer();
+		if ( object.hasNormals && ! objectWebGLProperties.__webglNormalBuffer ) objectWebGLProperties.__webglNormalBuffer = _gl.createBuffer();
+		if ( object.hasUvs && ! objectWebGLProperties.__webglUvBuffer ) objectWebGLProperties.__webglUvBuffer = _gl.createBuffer();
+		if ( object.hasColors && ! objectWebGLProperties.__webglColorBuffer ) objectWebGLProperties.__webglColorBuffer = _gl.createBuffer();
 
 
 		var attributes = program.getAttributes();
 		var attributes = program.getAttributes();
 
 
 		if ( object.hasPositions ) {
 		if ( object.hasPositions ) {
 
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, objectWebGLProperties.__webglVertexBuffer );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 
 
 			state.enableAttribute( attributes.position );
 			state.enableAttribute( attributes.position );
@@ -780,7 +787,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( object.hasNormals ) {
 		if ( object.hasNormals ) {
 
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, objectWebGLProperties.__webglNormalBuffer );
 
 
 			if ( material instanceof THREE.MeshPhongMaterial === false && material.shading === THREE.FlatShading ) {
 			if ( material instanceof THREE.MeshPhongMaterial === false && material.shading === THREE.FlatShading ) {
 
 
@@ -835,7 +842,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( object.hasUvs && material.map ) {
 		if ( object.hasUvs && material.map ) {
 
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, objectWebGLProperties.__webglUvBuffer );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 
 
 			state.enableAttribute( attributes.uv );
 			state.enableAttribute( attributes.uv );
@@ -846,7 +853,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
 		if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
 
 
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
+			_gl.bindBuffer( _gl.ARRAY_BUFFER, objectWebGLProperties.__webglColorBuffer );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 
 
 			state.enableAttribute( attributes.color );
 			state.enableAttribute( attributes.color );
@@ -899,13 +906,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 					var size = geometryAttribute.itemSize;
 					var size = geometryAttribute.itemSize;
 					state.enableAttribute( programAttribute );
 					state.enableAttribute( programAttribute );
 
 
+					var buffer = objects.getAttributeBuffer(geometryAttribute);
+
 					if ( geometryAttribute instanceof THREE.InterleavedBufferAttribute ) {
 					if ( geometryAttribute instanceof THREE.InterleavedBufferAttribute ) {
 
 
 						var data = geometryAttribute.data;
 						var data = geometryAttribute.data;
 						var stride = data.stride;
 						var stride = data.stride;
 						var offset = geometryAttribute.offset;
 						var offset = geometryAttribute.offset;
 
 
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryAttribute.data.buffer );
+						_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
 						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
 						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
 
 
 						if ( data instanceof THREE.InstancedInterleavedBuffer ) {
 						if ( data instanceof THREE.InstancedInterleavedBuffer ) {
@@ -929,7 +938,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 					} else {
 					} else {
 
 
-						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryAttribute.buffer );
+						_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
 						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, 0, startIndex * size * 4 ); // 4 bytes per Float32
 						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, 0, startIndex * size * 4 ); // 4 bytes per Float32
 
 
 						if ( geometryAttribute instanceof THREE.InstancedBufferAttribute ) {
 						if ( geometryAttribute instanceof THREE.InstancedBufferAttribute ) {
@@ -1050,6 +1059,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			var type, size;
 			var type, size;
 
 
+			var indexBuffer = objects.getAttributeBuffer(index);
+
 			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
 			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
 
 
 				type = _gl.UNSIGNED_INT;
 				type = _gl.UNSIGNED_INT;
@@ -1069,7 +1080,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				if ( updateBuffers ) {
 				if ( updateBuffers ) {
 
 
 					setupVertexAttributes( material, program, geometry, 0 );
 					setupVertexAttributes( material, program, geometry, 0 );
-					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, indexBuffer );
 
 
 				}
 				}
 
 
@@ -1110,7 +1121,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					if ( updateBuffers ) {
 					if ( updateBuffers ) {
 
 
 						setupVertexAttributes( material, program, geometry, startIndex );
 						setupVertexAttributes( material, program, geometry, startIndex );
-						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, indexBuffer );
 
 
 					}
 					}
 
 
@@ -1254,6 +1265,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			var type, size;
 			var type, size;
 
 
+			var indexBuffer = objects.getAttributeBuffer(index);
+
 			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
 			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
 
 
 				type = _gl.UNSIGNED_INT;
 				type = _gl.UNSIGNED_INT;
@@ -1273,7 +1286,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				if ( updateBuffers ) {
 				if ( updateBuffers ) {
 
 
 					setupVertexAttributes( material, program, geometry, 0 );
 					setupVertexAttributes( material, program, geometry, 0 );
-					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, indexBuffer );
 
 
 				}
 				}
 
 
@@ -1297,7 +1310,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					if ( updateBuffers ) {
 					if ( updateBuffers ) {
 
 
 						setupVertexAttributes( material, program, geometry, startIndex );
 						setupVertexAttributes( material, program, geometry, startIndex );
-						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, indexBuffer );
 
 
 					}
 					}
 
 
@@ -1361,6 +1374,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			var type, size;
 			var type, size;
 
 
+			var indexBuffer = objects.getAttributeBuffer( index );
+
 			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
 			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
 
 
 				type = _gl.UNSIGNED_INT;
 				type = _gl.UNSIGNED_INT;
@@ -1380,7 +1395,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				if ( updateBuffers ) {
 				if ( updateBuffers ) {
 
 
 					setupVertexAttributes( material, program, geometry, 0 );
 					setupVertexAttributes( material, program, geometry, 0 );
-					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, indexBuffer );
 
 
 				}
 				}
 
 
@@ -1404,7 +1419,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					if ( updateBuffers ) {
 					if ( updateBuffers ) {
 
 
 						setupVertexAttributes( material, program, geometry, startIndex );
 						setupVertexAttributes( material, program, geometry, startIndex );
-						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
+						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, indexBuffer );
 
 
 					}
 					}
 
 
@@ -1684,6 +1699,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 						var material = object.material;
 						var material = object.material;
 
 
+						if ( webGLProps.get( material ) ) {
+
+							material.program = webGLProps.get( material ).program;
+
+						}
+
 						if ( material.transparent ) {
 						if ( material.transparent ) {
 
 
 							transparentObjects.push( webglObject );
 							transparentObjects.push( webglObject );
@@ -1809,6 +1830,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function initMaterial( material, lights, fog, object ) {
 	function initMaterial( material, lights, fog, object ) {
 
 
+		var materialWebGLProperties = webGLProps.get( material );
+
 		var shaderID = shaderIDs[ material.type ];
 		var shaderID = shaderIDs[ material.type ];
 
 
 		// heuristics to create shader parameters according to lights in the scene
 		// heuristics to create shader parameters according to lights in the scene
@@ -1909,12 +1932,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		var code = chunks.join();
 		var code = chunks.join();
 
 
-		if ( !material.program ) {
+		if ( !materialWebGLProperties.program ) {
 
 
 			// new material
 			// new material
 			material.addEventListener( 'dispose', onMaterialDispose );
 			material.addEventListener( 'dispose', onMaterialDispose );
 
 
-		} else if ( material.program.code !== code ) {
+		} else if ( materialWebGLProperties.program.code !== code ) {
 
 
 			// changed glsl or parameters
 			// changed glsl or parameters
 			deallocateMaterial( material );
 			deallocateMaterial( material );
@@ -1924,7 +1947,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 			// same glsl
 			// same glsl
 			return;
 			return;
 
 
-		} else if ( material.__webglShader.uniforms === material.uniforms ) {
+		} else if ( materialWebGLProperties.__webglShader.uniforms === material.uniforms ) {
 
 
 			// same uniforms (container object)
 			// same uniforms (container object)
 			return;
 			return;
@@ -1935,7 +1958,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			var shader = THREE.ShaderLib[ shaderID ];
 			var shader = THREE.ShaderLib[ shaderID ];
 
 
-			material.__webglShader = {
+			materialWebGLProperties.__webglShader = {
 				name: material.type,
 				name: material.type,
 				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
 				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
 				vertexShader: shader.vertexShader,
 				vertexShader: shader.vertexShader,
@@ -1944,7 +1967,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		} else {
 		} else {
 
 
-			material.__webglShader = {
+			materialWebGLProperties.__webglShader = {
 				name: material.type,
 				name: material.type,
 				uniforms: material.uniforms,
 				uniforms: material.uniforms,
 				vertexShader: material.vertexShader,
 				vertexShader: material.vertexShader,
@@ -1974,6 +1997,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( program === undefined ) {
 		if ( program === undefined ) {
 
 
+			material.__webglShader = materialWebGLProperties.__webglShader;
 			program = new THREE.WebGLProgram( _this, code, material, parameters );
 			program = new THREE.WebGLProgram( _this, code, material, parameters );
 			_programs.push( program );
 			_programs.push( program );
 
 
@@ -1981,7 +2005,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		}
 		}
 
 
-		material.program = program;
+		materialWebGLProperties.program = program;
 
 
 		var attributes = program.getAttributes();
 		var attributes = program.getAttributes();
 
 
@@ -2017,15 +2041,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		}
 		}
 
 
-		material.uniformsList = [];
+		materialWebGLProperties.uniformsList = [];
 
 
-		var uniformLocations = material.program.getUniforms();
-		for ( var u in material.__webglShader.uniforms ) {
+		var uniformLocations = materialWebGLProperties.program.getUniforms();
+		for ( var u in materialWebGLProperties.__webglShader.uniforms ) {
 
 
 			var location = uniformLocations[ u ];
 			var location = uniformLocations[ u ];
 
 
 			if ( location ) {
 			if ( location ) {
-				material.uniformsList.push( [ material.__webglShader.uniforms[ u ], location ] );
+				materialWebGLProperties.uniformsList.push( [ materialWebGLProperties.__webglShader.uniforms[ u ], location ] );
 			}
 			}
 
 
 		}
 		}
@@ -2065,7 +2089,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		_usedTextureUnits = 0;
 		_usedTextureUnits = 0;
 
 
-		if ( material.needsUpdate ) {
+		var materialWebGLProperties = webGLProps.get( material );
+
+		if ( material.needsUpdate || ! materialWebGLProperties.program ) {
 
 
 			initMaterial( material, lights, fog, object );
 			initMaterial( material, lights, fog, object );
 			material.needsUpdate = false;
 			material.needsUpdate = false;
@@ -2076,9 +2102,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var refreshMaterial = false;
 		var refreshMaterial = false;
 		var refreshLights = false;
 		var refreshLights = false;
 
 
-		var program = material.program,
+		var program = materialWebGLProperties.program,
 			p_uniforms = program.getUniforms(),
 			p_uniforms = program.getUniforms(),
-			m_uniforms = material.__webglShader.uniforms;
+			m_uniforms = materialWebGLProperties.__webglShader.uniforms;
 
 
 		if ( program.id !== _currentProgram ) {
 		if ( program.id !== _currentProgram ) {
 
 
@@ -2283,7 +2309,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			// load common uniforms
 			// load common uniforms
 
 
-			loadUniformsGeneric( material.uniformsList );
+			loadUniformsGeneric( materialWebGLProperties.uniformsList );
 
 
 		}
 		}
 
 
@@ -3194,10 +3220,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( extension && texture.type !== THREE.FloatType && texture.type !== THREE.HalfFloatType ) {
 		if ( extension && texture.type !== THREE.FloatType && texture.type !== THREE.HalfFloatType ) {
 
 
-			if ( texture.anisotropy > 1 || texture.__currentAnisotropy ) {
+			if ( texture.anisotropy > 1 || webGLProps.get( texture ).__currentAnisotropy ) {
 
 
 				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) );
 				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) );
-				texture.__currentAnisotropy = texture.anisotropy;
+				webGLProps.get( texture ).__currentAnisotropy = texture.anisotropy;
 
 
 			}
 			}
 
 
@@ -3207,20 +3233,24 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	this.uploadTexture = function ( texture, slot ) {
 	this.uploadTexture = function ( texture, slot ) {
 
 
-		if ( texture.__webglInit === undefined ) {
+		var textureWebGLProperties = webGLProps.get( texture );
+
+		if ( textureWebGLProperties.__webglInit === undefined ) {
+
+			textureWebGLProperties.__webglInit = true;
 
 
 			texture.__webglInit = true;
 			texture.__webglInit = true;
 
 
 			texture.addEventListener( 'dispose', onTextureDispose );
 			texture.addEventListener( 'dispose', onTextureDispose );
 
 
-			texture.__webglTexture = _gl.createTexture();
+			textureWebGLProperties.__webglTexture = _gl.createTexture();
 
 
 			_this.info.memory.textures ++;
 			_this.info.memory.textures ++;
 
 
 		}
 		}
 
 
 		state.activeTexture( _gl.TEXTURE0 + slot );
 		state.activeTexture( _gl.TEXTURE0 + slot );
-		state.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
+		state.bindTexture( _gl.TEXTURE_2D, textureWebGLProperties.__webglTexture );
 
 
 		_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
 		_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
 		_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
 		_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
@@ -3321,6 +3351,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	this.setTexture = function ( texture, slot ) {
 	this.setTexture = function ( texture, slot ) {
 
 
+		// if the image has been uploaded into a separate renderer, will need to reupload to this renderer
+		if ( ( texture.image && texture.image.complete !== false ) && texture.__webglInit === true && webGLProps.get( texture ).__webglInit === undefined ) {
+
+			texture.needsUpdate = true;
+
+		}
+
 		if ( texture.needsUpdate === true ) {
 		if ( texture.needsUpdate === true ) {
 
 
 			var image = texture.image;
 			var image = texture.image;
@@ -3345,7 +3382,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		}
 		}
 
 
 		state.activeTexture( _gl.TEXTURE0 + slot );
 		state.activeTexture( _gl.TEXTURE0 + slot );
-		state.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
+		state.bindTexture( _gl.TEXTURE_2D, webGLProps.get( texture ).__webglTexture );
 
 
 	};
 	};
 
 
@@ -3377,22 +3414,24 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function setCubeTexture ( texture, slot ) {
 	function setCubeTexture ( texture, slot ) {
 
 
+		var textureWebGLProperties = webGLProps.get( texture );
+
 		if ( texture.image.length === 6 ) {
 		if ( texture.image.length === 6 ) {
 
 
 			if ( texture.needsUpdate ) {
 			if ( texture.needsUpdate ) {
 
 
-				if ( ! texture.image.__webglTextureCube ) {
+				if ( ! textureWebGLProperties.__image__webglTextureCube ) {
 
 
 					texture.addEventListener( 'dispose', onTextureDispose );
 					texture.addEventListener( 'dispose', onTextureDispose );
 
 
-					texture.image.__webglTextureCube = _gl.createTexture();
+					textureWebGLProperties.__image__webglTextureCube = _gl.createTexture();
 
 
 					_this.info.memory.textures ++;
 					_this.info.memory.textures ++;
 
 
 				}
 				}
 
 
 				state.activeTexture( _gl.TEXTURE0 + slot );
 				state.activeTexture( _gl.TEXTURE0 + slot );
-				state.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
+				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureWebGLProperties.__image__webglTextureCube );
 
 
 				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
 				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
 
 
@@ -3481,7 +3520,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 			} else {
 			} else {
 
 
 				state.activeTexture( _gl.TEXTURE0 + slot );
 				state.activeTexture( _gl.TEXTURE0 + slot );
-				state.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
+				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureWebGLProperties.__image__webglTextureCube );
 
 
 			}
 			}
 
 
@@ -3492,7 +3531,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function setCubeTextureDynamic ( texture, slot ) {
 	function setCubeTextureDynamic ( texture, slot ) {
 
 
 		state.activeTexture( _gl.TEXTURE0 + slot );
 		state.activeTexture( _gl.TEXTURE0 + slot );
-		state.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
+		state.bindTexture( _gl.TEXTURE_CUBE_MAP, webGLProps.get( texture ).__webglTexture );
 
 
 	}
 	}
 
 
@@ -3501,7 +3540,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
 	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
 
 
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
 		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
+		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, webGLProps.get( renderTarget ).__webglTexture, 0 );
 
 
 	}
 	}
 
 
@@ -3537,14 +3576,16 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
 		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
 
 
-		if ( renderTarget && renderTarget.__webglFramebuffer === undefined ) {
+		if ( renderTarget && webGLProps.get( renderTarget ).__webglFramebuffer === undefined ) {
+
+			var renderTargetWebGLProperties = webGLProps.get( renderTarget );
 
 
 			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
 			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
 			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
 			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
 
 
 			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
 			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
 
 
-			renderTarget.__webglTexture = _gl.createTexture();
+			renderTargetWebGLProperties.__webglTexture = _gl.createTexture();
 
 
 			_this.info.memory.textures ++;
 			_this.info.memory.textures ++;
 
 
@@ -3556,22 +3597,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			if ( isCube ) {
 			if ( isCube ) {
 
 
-				renderTarget.__webglFramebuffer = [];
-				renderTarget.__webglRenderbuffer = [];
+				renderTargetWebGLProperties.__webglFramebuffer = [];
+				renderTargetWebGLProperties.__webglRenderbuffer = [];
 
 
-				state.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
+				state.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTargetWebGLProperties.__webglTexture );
 
 
 				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
 				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
 
 
 				for ( var i = 0; i < 6; i ++ ) {
 				for ( var i = 0; i < 6; i ++ ) {
 
 
-					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
-					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
+					renderTargetWebGLProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
+					renderTargetWebGLProperties.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
 
 
 					state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 					state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
 
-					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
-					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
+					setupFrameBuffer( renderTargetWebGLProperties.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
+					setupRenderBuffer( renderTargetWebGLProperties.__webglRenderbuffer[ i ], renderTarget );
 
 
 				}
 				}
 
 
@@ -3579,40 +3620,40 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			} else {
 			} else {
 
 
-				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
+				renderTargetWebGLProperties.__webglFramebuffer = _gl.createFramebuffer();
 
 
 				if ( renderTarget.shareDepthFrom ) {
 				if ( renderTarget.shareDepthFrom ) {
 
 
-					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
+					renderTargetWebGLProperties.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
 
 
 				} else {
 				} else {
 
 
-					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
+					renderTargetWebGLProperties.__webglRenderbuffer = _gl.createRenderbuffer();
 
 
 				}
 				}
 
 
-				state.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
+				state.bindTexture( _gl.TEXTURE_2D, renderTargetWebGLProperties.__webglTexture );
 				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
 				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
 
 
 				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
 
-				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
+				setupFrameBuffer( renderTargetWebGLProperties.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
 
 
 				if ( renderTarget.shareDepthFrom ) {
 				if ( renderTarget.shareDepthFrom ) {
 
 
 					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
 					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
 
 
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
+						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTargetWebGLProperties.__webglRenderbuffer );
 
 
 					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
 
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
+						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTargetWebGLProperties.__webglRenderbuffer );
 
 
 					}
 					}
 
 
 				} else {
 				} else {
 
 
-					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
+					setupRenderBuffer( renderTargetWebGLProperties.__webglRenderbuffer, renderTarget );
 
 
 				}
 				}
 
 
@@ -3641,13 +3682,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( renderTarget ) {
 		if ( renderTarget ) {
 
 
+			var renderTargetWebGLProperties = webGLProps.get( renderTarget );
+
 			if ( isCube ) {
 			if ( isCube ) {
 
 
-				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
+				framebuffer = renderTargetWebGLProperties.__webglFramebuffer[ renderTarget.activeCubeFace ];
 
 
 			} else {
 			} else {
 
 
-				framebuffer = renderTarget.__webglFramebuffer;
+				framebuffer = renderTargetWebGLProperties.__webglFramebuffer;
 
 
 			}
 			}
 
 
@@ -3692,7 +3735,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		}
 		}
 
 
-		if ( renderTarget.__webglFramebuffer ) {
+		if ( webGLProps.get( renderTarget ).__webglFramebuffer ) {
 
 
 			if ( renderTarget.format !== THREE.RGBAFormat ) {
 			if ( renderTarget.format !== THREE.RGBAFormat ) {
 
 
@@ -3703,9 +3746,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			var restore = false;
 			var restore = false;
 
 
-			if ( renderTarget.__webglFramebuffer !== _currentFramebuffer ) {
+			if ( webGLProps.get( renderTarget ).__webglFramebuffer !== _currentFramebuffer ) {
 
 
-				_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTarget.__webglFramebuffer );
+				_gl.bindFramebuffer( _gl.FRAMEBUFFER, webGLProps.get( renderTarget ).__webglFramebuffer );
 
 
 				restore = true;
 				restore = true;
 
 
@@ -3735,13 +3778,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 
 
-			state.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
+			state.bindTexture( _gl.TEXTURE_CUBE_MAP, webGLProps.get( renderTarget ).__webglTexture );
 			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 			state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 			state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 
 
 		} else {
 		} else {
 
 
-			state.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
+			state.bindTexture( _gl.TEXTURE_2D, webGLProps.get( renderTarget ).__webglTexture );
 			_gl.generateMipmap( _gl.TEXTURE_2D );
 			_gl.generateMipmap( _gl.TEXTURE_2D );
 			state.bindTexture( _gl.TEXTURE_2D, null );
 			state.bindTexture( _gl.TEXTURE_2D, null );
 
 

+ 27 - 10
src/renderers/webgl/WebGLObjects.js

@@ -7,6 +7,8 @@ THREE.WebGLObjects = function ( gl, info ) {
 	var objects = {};
 	var objects = {};
 	var objectsImmediate = [];
 	var objectsImmediate = [];
 
 
+	var webGLProps = new THREE.WebGLProperties();
+
 	var morphInfluences = new Float32Array( 8 );
 	var morphInfluences = new Float32Array( 8 );
 
 
 	var geometries = new THREE.WebGLGeometries( gl, info );
 	var geometries = new THREE.WebGLGeometries( gl, info );
@@ -40,11 +42,10 @@ THREE.WebGLObjects = function ( gl, info ) {
 
 
 		}
 		}
 
 
-		delete object.__webglInit;
 		delete object._modelViewMatrix;
 		delete object._modelViewMatrix;
 		delete object._normalMatrix;
 		delete object._normalMatrix;
 
 
-		delete object.__webglActive;
+		delete webGLProps.delete( object );
 
 
 	}
 	}
 
 
@@ -66,14 +67,17 @@ THREE.WebGLObjects = function ( gl, info ) {
 
 
 	this.objects = objects;
 	this.objects = objects;
 	this.objectsImmediate = objectsImmediate;
 	this.objectsImmediate = objectsImmediate;
+	this.webGLProps = webGLProps;
 
 
 	this.geometries = geometries;
 	this.geometries = geometries;
 
 
 	this.init = function ( object ) {
 	this.init = function ( object ) {
 
 
-		if ( object.__webglInit === undefined ) {
+		var objectWebglProperties = webGLProps.get( object );
+
+		if ( objectWebglProperties.__webglInit === undefined ) {
 
 
-			object.__webglInit = true;
+			objectWebglProperties.__webglInit = true;
 			object._modelViewMatrix = new THREE.Matrix4();
 			object._modelViewMatrix = new THREE.Matrix4();
 			object._normalMatrix = new THREE.Matrix3();
 			object._normalMatrix = new THREE.Matrix3();
 
 
@@ -81,9 +85,9 @@ THREE.WebGLObjects = function ( gl, info ) {
 
 
 		}
 		}
 
 
-		if ( object.__webglActive === undefined ) {
+		if ( objectWebglProperties.__webglActive === undefined ) {
 
 
-			object.__webglActive = true;
+			objectWebglProperties.__webglActive = true;
 
 
 			if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
 			if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.PointCloud ) {
 
 
@@ -188,10 +192,12 @@ THREE.WebGLObjects = function ( gl, info ) {
 
 
 			var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
 			var data = ( attribute instanceof THREE.InterleavedBufferAttribute ) ? attribute.data : attribute;
 
 
-			if ( data.buffer === undefined ) {
+			var attributeWebGLProperties = webGLProps.get( data );
+
+			if ( attributeWebGLProperties.__webglBuffer === undefined ) {
 
 
-				data.buffer = gl.createBuffer();
-				gl.bindBuffer( bufferType, data.buffer );
+				attributeWebGLProperties.__webglBuffer = gl.createBuffer();
+				gl.bindBuffer( bufferType, attributeWebGLProperties.__webglBuffer );
 
 
 				var usage = gl.STATIC_DRAW;
 				var usage = gl.STATIC_DRAW;
 
 
@@ -209,7 +215,7 @@ THREE.WebGLObjects = function ( gl, info ) {
 
 
 			} else if ( data.needsUpdate === true ) {
 			} else if ( data.needsUpdate === true ) {
 
 
-				gl.bindBuffer( bufferType, data.buffer );
+				gl.bindBuffer( bufferType, attributeWebGLProperties.__webglBuffer );
 
 
 				if ( data.updateRange === undefined || data.updateRange.count === -1 ) { // Not using update ranges
 				if ( data.updateRange === undefined || data.updateRange.count === -1 ) { // Not using update ranges
 
 
@@ -236,6 +242,17 @@ THREE.WebGLObjects = function ( gl, info ) {
 
 
 	};
 	};
 
 
+	// returns the webgl buffer for a specified attribute
+	this.getAttributeBuffer = function (attribute) {
+		if ( attribute instanceof THREE.InterleavedBufferAttribute ) {
+
+			return webGLProps.get( attribute.data ).__webglBuffer
+
+		}
+
+		return webGLProps.get( attribute ).__webglBuffer;
+	}
+
 	this.update = function ( renderList ) {
 	this.update = function ( renderList ) {
 
 
 		for ( var i = 0, ul = renderList.length; i < ul; i++ ) {
 		for ( var i = 0, ul = renderList.length; i < ul; i++ ) {

+ 38 - 0
src/renderers/webgl/WebGLProperties.js

@@ -0,0 +1,38 @@
+/**
+* @author fordacious / fordacious.github.io
+*/
+
+THREE.WebGLProperties = function () {
+
+	var properties = {};
+
+	this.deleteAll = function () {
+
+		properties = {};
+
+	}
+
+	this.delete = function ( object ) {
+
+		delete properties[ object.uuid ];
+
+	};
+
+	this.get = function ( object ) {
+
+		initObject( object );
+
+		return properties[ object.uuid ];
+
+	};
+
+	function initObject ( object ) {
+
+		if ( properties[ object.uuid ] === undefined ) {
+
+			properties[ object.uuid ] = {};
+		}
+
+	}
+
+};

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

@@ -160,6 +160,7 @@
 	"src/renderers/webgl/WebGLGeometries.js",
 	"src/renderers/webgl/WebGLGeometries.js",
 	"src/renderers/webgl/WebGLObjects.js",
 	"src/renderers/webgl/WebGLObjects.js",
 	"src/renderers/webgl/WebGLProgram.js",
 	"src/renderers/webgl/WebGLProgram.js",
+	"src/renderers/webgl/WebGLProperties.js",
 	"src/renderers/webgl/WebGLShader.js",
 	"src/renderers/webgl/WebGLShader.js",
 	"src/renderers/webgl/WebGLShadowMap.js",
 	"src/renderers/webgl/WebGLShadowMap.js",
 	"src/renderers/webgl/WebGLState.js",
 	"src/renderers/webgl/WebGLState.js",