Przeglądaj źródła

Updated builds.

Mr.doob 11 lat temu
rodzic
commit
f6312e0ad7
3 zmienionych plików z 966 dodań i 960 usunięć
  1. 768 754
      build/three.js
  2. 197 205
      build/three.min.js
  3. 1 1
      src/renderers/webgl/WebGLProgram.js

+ 768 - 754
build/three.js

@@ -20339,7 +20339,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 	var _this = this,
 
 	_programs = [],
-	_programs_counter = 0,
 
 	// internal state cache
 
@@ -24317,6 +24316,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		parameters = {
 
+			precision: _precision,
+			supportsVertexTextures: _supportsVertexTextures,
+
 			map: !!material.map,
 			envMap: !!material.envMap,
 			lightMap: !!material.lightMap,
@@ -24360,7 +24362,66 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		};
 
-		material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, material.defines, parameters, material.index0AttributeName );
+		// Generate code
+
+		var chunks = [];
+
+		if ( shaderID ) {
+
+			chunks.push( shaderID );
+
+		} else {
+
+			chunks.push( material.fragmentShader );
+			chunks.push( material.vertexShader );
+
+		}
+
+		for ( var d in material.defines ) {
+
+			chunks.push( d );
+			chunks.push( material.defines[ d ] );
+
+		}
+
+		for ( var p in parameters ) {
+
+			chunks.push( p );
+			chunks.push( parameters[ p ] );
+
+		}
+
+		var code = chunks.join();
+
+		var program;
+
+		// Check if code has been already compiled
+
+		for ( var p = 0, pl = _programs.length; p < pl; p ++ ) {
+
+			var programInfo = _programs[ p ];
+
+			if ( programInfo.code === code ) {
+
+				program = programInfo;
+				program.usedTimes ++;
+
+				break;
+
+			}
+
+		}
+
+		if ( program === undefined ) {
+
+			program = new THREE.WebGLProgram( this, code, material, parameters );
+			_programs.push( program );
+
+			_this.info.memory.programs = _programs.length;
+
+		}
+
+		material.program = program;
 
 		var attributes = material.program.attributes;
 
@@ -24451,10 +24512,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 			p_uniforms = program.uniforms,
 			m_uniforms = material.uniforms;
 
-		if ( program !== _currentProgram ) {
+		if ( program.id !== _currentProgram ) {
 
-			_gl.useProgram( program );
-			_currentProgram = program;
+			_gl.useProgram( program.program );
+			_currentProgram = program.id;
 
 			refreshMaterial = true;
 
@@ -25590,1238 +25651,1191 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-	// Defines
+	// Textures
 
-	function generateDefines ( defines ) {
+	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
 
-		var value, chunk, chunks = [];
+		if ( isImagePowerOfTwo ) {
 
-		for ( var d in defines ) {
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
 
-			value = defines[ d ];
-			if ( value === false ) continue;
+			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
+			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
 
-			chunk = "#define " + d + " " + value;
-			chunks.push( chunk );
+		} else {
 
-		}
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
+			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
 
-		return chunks.join( "\n" );
+			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
+			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
 
-	};
+		}
 
-	// Shaders
+		if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
 
-	function buildProgram( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters, index0AttributeName ) {
+			if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
 
-		var p, pl, d, program, code;
-		var chunks = [];
+				_gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
+				texture.__oldAnisotropy = texture.anisotropy;
 
-		// Generate code
+			}
 
-		if ( shaderID ) {
+		}
 
-			chunks.push( shaderID );
+	};
 
-		} else {
+	this.setTexture = function ( texture, slot ) {
 
-			chunks.push( fragmentShader );
-			chunks.push( vertexShader );
+		if ( texture.needsUpdate ) {
 
-		}
+			if ( ! texture.__webglInit ) {
 
-		for ( d in defines ) {
+				texture.__webglInit = true;
 
-			chunks.push( d );
-			chunks.push( defines[ d ] );
+				texture.addEventListener( 'dispose', onTextureDispose );
 
-		}
+				texture.__webglTexture = _gl.createTexture();
 
-		for ( p in parameters ) {
+				_this.info.memory.textures ++;
 
-			chunks.push( p );
-			chunks.push( parameters[ p ] );
+			}
 
-		}
+			_gl.activeTexture( _gl.TEXTURE0 + slot );
+			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
 
-		code = chunks.join();
+			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
+			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
+			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
 
-		// Check if code has been already compiled
+			var image = texture.image,
+			isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
+			glFormat = paramThreeToGL( texture.format ),
+			glType = paramThreeToGL( texture.type );
 
-		for ( p = 0, pl = _programs.length; p < pl; p ++ ) {
+			setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
 
-			var programInfo = _programs[ p ];
+			var mipmap, mipmaps = texture.mipmaps;
 
-			if ( programInfo.code === code ) {
+			if ( texture instanceof THREE.DataTexture ) {
 
-				// console.log( "Code already compiled." /*: \n\n" + code*/ );
+				// use manually created mipmaps if available
+				// if there are no manual mipmaps
+				// set 0 level mipmap and then use GL to generate other mipmap levels
 
-				programInfo.usedTimes ++;
+				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
 
-				return programInfo.program;
+					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
-			}
+						mipmap = mipmaps[ i ];
+						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
 
-		}
+					}
 
-		var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
+					texture.generateMipmaps = false;
 
-		if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
+				} else {
 
-			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
+					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
 
-		} else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
+				}
 
-			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
+			} else if ( texture instanceof THREE.CompressedTexture ) {
 
-		}
+				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
-		// console.log( "building new program " );
+					mipmap = mipmaps[ i ];
+					if ( texture.format!==THREE.RGBAFormat ) {
+						_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+					} else {
+						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+					}
 
-		//
+				}
 
-		var customDefines = generateDefines( defines );
+			} else { // regular Texture (image, video, canvas)
 
-		//
+				// use manually created mipmaps if available
+				// if there are no manual mipmaps
+				// set 0 level mipmap and then use GL to generate other mipmap levels
 
-		program = _gl.createProgram();
+				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
 
-		var prefix_vertex = [
+					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
 
-			"precision " + _precision + " float;",
-			"precision " + _precision + " int;",
+						mipmap = mipmaps[ i ];
+						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
 
-			customDefines,
+					}
 
-			_supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
+					texture.generateMipmaps = false;
 
-			_this.gammaInput ? "#define GAMMA_INPUT" : "",
-			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
+				} else {
 
-			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
-			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
-			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
-			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
+					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
 
-			"#define MAX_SHADOWS " + parameters.maxShadows,
+				}
 
-			"#define MAX_BONES " + parameters.maxBones,
+			}
 
-			parameters.map ? "#define USE_MAP" : "",
-			parameters.envMap ? "#define USE_ENVMAP" : "",
-			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
-			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
-			parameters.normalMap ? "#define USE_NORMALMAP" : "",
-			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
-			parameters.vertexColors ? "#define USE_COLOR" : "",
+			if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
 
-			parameters.skinning ? "#define USE_SKINNING" : "",
-			parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
+			texture.needsUpdate = false;
 
-			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
-			parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
-			parameters.wrapAround ? "#define WRAP_AROUND" : "",
-			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
-			parameters.flipSided ? "#define FLIP_SIDED" : "",
+			if ( texture.onUpdate ) texture.onUpdate();
 
-			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
-			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
-			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
-			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
+		} else {
 
-			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
+			_gl.activeTexture( _gl.TEXTURE0 + slot );
+			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
 
-			"uniform mat4 modelMatrix;",
-			"uniform mat4 modelViewMatrix;",
-			"uniform mat4 projectionMatrix;",
-			"uniform mat4 viewMatrix;",
-			"uniform mat3 normalMatrix;",
-			"uniform vec3 cameraPosition;",
+		}
 
-			"attribute vec3 position;",
-			"attribute vec3 normal;",
-			"attribute vec2 uv;",
-			"attribute vec2 uv2;",
+	};
 
-			"#ifdef USE_COLOR",
+	function clampToMaxSize ( image, maxSize ) {
 
-			"	attribute vec3 color;",
+		if ( image.width <= maxSize && image.height <= maxSize ) {
 
-			"#endif",
+			return image;
 
-			"#ifdef USE_MORPHTARGETS",
+		}
 
-			"	attribute vec3 morphTarget0;",
-			"	attribute vec3 morphTarget1;",
-			"	attribute vec3 morphTarget2;",
-			"	attribute vec3 morphTarget3;",
+		// Warning: Scaling through the canvas will only work with images that use
+		// premultiplied alpha.
 
-			"	#ifdef USE_MORPHNORMALS",
+		var maxDimension = Math.max( image.width, image.height );
+		var newWidth = Math.floor( image.width * maxSize / maxDimension );
+		var newHeight = Math.floor( image.height * maxSize / maxDimension );
 
-			"		attribute vec3 morphNormal0;",
-			"		attribute vec3 morphNormal1;",
-			"		attribute vec3 morphNormal2;",
-			"		attribute vec3 morphNormal3;",
+		var canvas = document.createElement( 'canvas' );
+		canvas.width = newWidth;
+		canvas.height = newHeight;
 
-			"	#else",
+		var ctx = canvas.getContext( "2d" );
+		ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
 
-			"		attribute vec3 morphTarget4;",
-			"		attribute vec3 morphTarget5;",
-			"		attribute vec3 morphTarget6;",
-			"		attribute vec3 morphTarget7;",
+		return canvas;
 
-			"	#endif",
+	}
 
-			"#endif",
+	function setCubeTexture ( texture, slot ) {
 
-			"#ifdef USE_SKINNING",
+		if ( texture.image.length === 6 ) {
 
-			"	attribute vec4 skinIndex;",
-			"	attribute vec4 skinWeight;",
+			if ( texture.needsUpdate ) {
 
-			"#endif",
+				if ( ! texture.image.__webglTextureCube ) {
 
-			""
+					texture.addEventListener( 'dispose', onTextureDispose );
 
-		].join("\n");
+					texture.image.__webglTextureCube = _gl.createTexture();
 
-		var prefix_fragment = [
+					_this.info.memory.textures ++;
 
-			"precision " + _precision + " float;",
-			"precision " + _precision + " int;",
+				}
 
-			( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
+				_gl.activeTexture( _gl.TEXTURE0 + slot );
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
 
-			customDefines,
-
-			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
-			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
-			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
-			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
+				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
 
-			"#define MAX_SHADOWS " + parameters.maxShadows,
+				var isCompressed = texture instanceof THREE.CompressedTexture;
 
-			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
+				var cubeImage = [];
 
-			_this.gammaInput ? "#define GAMMA_INPUT" : "",
-			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
+				for ( var i = 0; i < 6; i ++ ) {
 
-			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
-			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
+					if ( _this.autoScaleCubemaps && ! isCompressed ) {
 
-			parameters.map ? "#define USE_MAP" : "",
-			parameters.envMap ? "#define USE_ENVMAP" : "",
-			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
-			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
-			parameters.normalMap ? "#define USE_NORMALMAP" : "",
-			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
-			parameters.vertexColors ? "#define USE_COLOR" : "",
+						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
 
-			parameters.metal ? "#define METAL" : "",
-			parameters.wrapAround ? "#define WRAP_AROUND" : "",
-			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
-			parameters.flipSided ? "#define FLIP_SIDED" : "",
+					} else {
 
-			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
-			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
-			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
-			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
+						cubeImage[ i ] = texture.image[ i ];
 
-			"uniform mat4 viewMatrix;",
-			"uniform vec3 cameraPosition;",
-			""
+					}
 
-		].join( '\n' );
+				}
 
-		var glVertexShader = new THREE.WebGLShader( _gl, _gl.VERTEX_SHADER, prefix_vertex + vertexShader );
-		var glFragmentShader = new THREE.WebGLShader( _gl, _gl.FRAGMENT_SHADER, prefix_fragment + fragmentShader );
+				var image = cubeImage[ 0 ],
+				isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
+				glFormat = paramThreeToGL( texture.format ),
+				glType = paramThreeToGL( texture.type );
 
-		_gl.attachShader( program, glVertexShader );
-		_gl.attachShader( program, glFragmentShader );
+				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
 
-		// Force a particular attribute to index 0.
-		// because potentially expensive emulation is done by browser if attribute 0 is disabled.
-		// And, color, for example is often automatically bound to index 0 so disabling it
-		if ( index0AttributeName !== undefined ) {
+				for ( var i = 0; i < 6; i ++ ) {
 
-			_gl.bindAttribLocation( program, 0, index0AttributeName );
+					if( !isCompressed ) {
 
-		}
+						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
 
-		_gl.linkProgram( program );
+					} else {
+						
+						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
 
-		if ( _gl.getProgramParameter( program, _gl.LINK_STATUS ) === false ) {
+						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
 
-			console.error( 'Could not initialise shader' );
-			console.error( 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) );
-			console.error( 'gl.getError()', _gl.getError() );
+							mipmap = mipmaps[ j ];
+							if ( texture.format!==THREE.RGBAFormat ) {
 
-		}
+								_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
 
-		if ( _gl.getProgramInfoLog( program ) !== '' ) {
+							} else {
+								_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
+							}
 
-			console.error( 'gl.getProgramInfoLog()', _gl.getProgramInfoLog( program ) );
+						}
+					}
+				}
 
-		}
+				if ( texture.generateMipmaps && isImagePowerOfTwo ) {
 
-		program.vertexShader = _gl.getShaderSource( glVertexShader );
-		program.fragmentShader = _gl.getShaderSource( glFragmentShader );
+					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 
-		// clean up
+				}
 
-		_gl.deleteShader( glVertexShader );
-		_gl.deleteShader( glFragmentShader );
+				texture.needsUpdate = false;
 
-		// console.log( prefix_fragment + fragmentShader );
-		// console.log( prefix_vertex + vertexShader );
+				if ( texture.onUpdate ) texture.onUpdate();
 
-		program.uniforms = {};
-		program.attributes = {};
+			} else {
 
-		var identifiers, u, a, i;
+				_gl.activeTexture( _gl.TEXTURE0 + slot );
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
 
-		// cache uniform locations
+			}
 
-		identifiers = [
+		}
 
-			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
-			'morphTargetInfluences'
+	};
 
-		];
+	function setCubeTextureDynamic ( texture, slot ) {
 
-		if ( parameters.useVertexTexture ) {
+		_gl.activeTexture( _gl.TEXTURE0 + slot );
+		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
 
-			identifiers.push( 'boneTexture' );
-			identifiers.push( 'boneTextureWidth' );
-			identifiers.push( 'boneTextureHeight' );
+	};
 
-		} else {
+	// Render targets
 
-			identifiers.push( 'boneGlobalMatrices' );
+	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
 
-		}
+		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
+		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
 
-		for ( u in uniforms ) {
+	};
 
-			identifiers.push( u );
+	function setupRenderBuffer ( renderbuffer, renderTarget  ) {
 
-		}
+		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
 
-		cacheUniformLocations( program, identifiers );
+		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
 
-		// cache attributes locations
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
+			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
 
-		identifiers = [
+		/* For some reason this is not working. Defaulting to RGBA4.
+		} else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
-			"position", "normal", "uv", "uv2", "tangent", "color",
-			"skinIndex", "skinWeight", "lineDistance"
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
+			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
+		*/
+		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
-		];
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
+			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
 
-		for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
+		} else {
 
-			identifiers.push( "morphTarget" + i );
+			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
 
 		}
 
-		for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
+	};
 
-			identifiers.push( "morphNormal" + i );
+	this.setRenderTarget = function ( renderTarget ) {
 
-		}
+		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
 
-		for ( a in attributes ) {
+		if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
 
-			identifiers.push( a );
+			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
+			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
 
-		}
+			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
 
-		cacheAttributeLocations( program, identifiers );
+			renderTarget.__webglTexture = _gl.createTexture();
 
-		program.id = _programs_counter ++;
+			_this.info.memory.textures ++;
 
-		_programs.push( { program: program, code: code, usedTimes: 1 } );
+			// Setup texture, create render and frame buffers
 
-		_this.info.memory.programs = _programs.length;
+			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height ),
+				glFormat = paramThreeToGL( renderTarget.format ),
+				glType = paramThreeToGL( renderTarget.type );
 
-		return program;
+			if ( isCube ) {
 
-	};
+				renderTarget.__webglFramebuffer = [];
+				renderTarget.__webglRenderbuffer = [];
 
-	// Shader parameters cache
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
+				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
 
-	function cacheUniformLocations ( program, identifiers ) {
+				for ( var i = 0; i < 6; i ++ ) {
 
-		var i, l, id;
+					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
+					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
 
-		for( i = 0, l = identifiers.length; i < l; i ++ ) {
+					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
-			id = identifiers[ i ];
-			program.uniforms[ id ] = _gl.getUniformLocation( program, id );
+					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
+					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
 
-		}
+				}
 
-	};
+				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
 
-	function cacheAttributeLocations ( program, identifiers ) {
+			} else {
 
-		var i, l, id;
+				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
 
-		for( i = 0, l = identifiers.length; i < l; i ++ ) {
+				if ( renderTarget.shareDepthFrom ) {
 
-			id = identifiers[ i ];
-			program.attributes[ id ] = _gl.getAttribLocation( program, id );
+					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
 
-		}
+				} else {
 
-	};
+					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
 
+				}
 
+				_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
+				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
 
-	// Textures
+				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
 
-	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
+				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
 
-		if ( isImagePowerOfTwo ) {
+				if ( renderTarget.shareDepthFrom ) {
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
+					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
+						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
 
-		} else {
+					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
+						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
 
-			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
+					}
 
-		}
+				} else {
 
-		if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
+					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
 
-			if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
+				}
 
-				_gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
-				texture.__oldAnisotropy = texture.anisotropy;
+				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
 
 			}
 
-		}
+			// Release everything
 
-	};
+			if ( isCube ) {
 
-	this.setTexture = function ( texture, slot ) {
+				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 
-		if ( texture.needsUpdate ) {
+			} else {
 
-			if ( ! texture.__webglInit ) {
+				_gl.bindTexture( _gl.TEXTURE_2D, null );
 
-				texture.__webglInit = true;
+			}
 
-				texture.addEventListener( 'dispose', onTextureDispose );
+			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
+			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
 
-				texture.__webglTexture = _gl.createTexture();
+		}
 
-				_this.info.memory.textures ++;
+		var framebuffer, width, height, vx, vy;
 
-			}
+		if ( renderTarget ) {
 
-			_gl.activeTexture( _gl.TEXTURE0 + slot );
-			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
+			if ( isCube ) {
 
-			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
-			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
-			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
+				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
 
-			var image = texture.image,
-			isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
-			glFormat = paramThreeToGL( texture.format ),
-			glType = paramThreeToGL( texture.type );
+			} else {
 
-			setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
+				framebuffer = renderTarget.__webglFramebuffer;
 
-			var mipmap, mipmaps = texture.mipmaps;
+			}
 
-			if ( texture instanceof THREE.DataTexture ) {
+			width = renderTarget.width;
+			height = renderTarget.height;
 
-				// use manually created mipmaps if available
-				// if there are no manual mipmaps
-				// set 0 level mipmap and then use GL to generate other mipmap levels
-
-				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
-
-					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
-
-						mipmap = mipmaps[ i ];
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
-
-					}
-
-					texture.generateMipmaps = false;
-
-				} else {
+			vx = 0;
+			vy = 0;
 
-					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
+		} else {
 
-				}
+			framebuffer = null;
 
-			} else if ( texture instanceof THREE.CompressedTexture ) {
+			width = _viewportWidth;
+			height = _viewportHeight;
 
-				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
+			vx = _viewportX;
+			vy = _viewportY;
 
-					mipmap = mipmaps[ i ];
-					if ( texture.format!==THREE.RGBAFormat ) {
-						_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
-					} else {
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
-					}
+		}
 
-				}
+		if ( framebuffer !== _currentFramebuffer ) {
 
-			} else { // regular Texture (image, video, canvas)
+			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
+			_gl.viewport( vx, vy, width, height );
 
-				// use manually created mipmaps if available
-				// if there are no manual mipmaps
-				// set 0 level mipmap and then use GL to generate other mipmap levels
+			_currentFramebuffer = framebuffer;
 
-				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
+		}
 
-					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
+		_currentWidth = width;
+		_currentHeight = height;
 
-						mipmap = mipmaps[ i ];
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
+	};
 
-					}
+	function updateRenderTargetMipmap ( renderTarget ) {
 
-					texture.generateMipmaps = false;
+		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
 
-				} else {
+			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
+			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 
-					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
+		} else {
 
-				}
+			_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
+			_gl.generateMipmap( _gl.TEXTURE_2D );
+			_gl.bindTexture( _gl.TEXTURE_2D, null );
 
-			}
+		}
 
-			if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
+	};
 
-			texture.needsUpdate = false;
+	// Fallback filters for non-power-of-2 textures
 
-			if ( texture.onUpdate ) texture.onUpdate();
+	function filterFallback ( f ) {
 
-		} else {
+		if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
 
-			_gl.activeTexture( _gl.TEXTURE0 + slot );
-			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
+			return _gl.NEAREST;
 
 		}
 
+		return _gl.LINEAR;
+
 	};
 
-	function clampToMaxSize ( image, maxSize ) {
+	// Map three.js constants to WebGL constants
 
-		if ( image.width <= maxSize && image.height <= maxSize ) {
+	function paramThreeToGL ( p ) {
 
-			return image;
+		if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
+		if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
+		if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
 
-		}
+		if ( p === THREE.NearestFilter ) return _gl.NEAREST;
+		if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
+		if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
 
-		// Warning: Scaling through the canvas will only work with images that use
-		// premultiplied alpha.
+		if ( p === THREE.LinearFilter ) return _gl.LINEAR;
+		if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
+		if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
 
-		var maxDimension = Math.max( image.width, image.height );
-		var newWidth = Math.floor( image.width * maxSize / maxDimension );
-		var newHeight = Math.floor( image.height * maxSize / maxDimension );
+		if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
+		if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
+		if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
+		if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
 
-		var canvas = document.createElement( 'canvas' );
-		canvas.width = newWidth;
-		canvas.height = newHeight;
+		if ( p === THREE.ByteType ) return _gl.BYTE;
+		if ( p === THREE.ShortType ) return _gl.SHORT;
+		if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
+		if ( p === THREE.IntType ) return _gl.INT;
+		if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
+		if ( p === THREE.FloatType ) return _gl.FLOAT;
 
-		var ctx = canvas.getContext( "2d" );
-		ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
+		if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
+		if ( p === THREE.RGBFormat ) return _gl.RGB;
+		if ( p === THREE.RGBAFormat ) return _gl.RGBA;
+		if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
+		if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
 
-		return canvas;
+		if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
+		if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
+		if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
 
-	}
+		if ( p === THREE.ZeroFactor ) return _gl.ZERO;
+		if ( p === THREE.OneFactor ) return _gl.ONE;
+		if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
+		if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
+		if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
+		if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
+		if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
+		if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
 
-	function setCubeTexture ( texture, slot ) {
+		if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
+		if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
+		if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
 
-		if ( texture.image.length === 6 ) {
+		if ( _glExtensionCompressedTextureS3TC !== undefined ) {
 
-			if ( texture.needsUpdate ) {
+			if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
+			if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+			if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
+			if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
 
-				if ( ! texture.image.__webglTextureCube ) {
+		}
 
-					texture.addEventListener( 'dispose', onTextureDispose );
+		return 0;
 
-					texture.image.__webglTextureCube = _gl.createTexture();
+	};
 
-					_this.info.memory.textures ++;
+	// Allocations
 
-				}
+	function allocateBones ( object ) {
 
-				_gl.activeTexture( _gl.TEXTURE0 + slot );
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
+		if ( _supportsBoneTextures && object && object.useVertexTexture ) {
 
-				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
+			return 1024;
 
-				var isCompressed = texture instanceof THREE.CompressedTexture;
+		} else {
 
-				var cubeImage = [];
+			// default for when object is not specified
+			// ( for example when prebuilding shader
+			//   to be used with multiple objects )
+			//
+			// 	- leave some extra space for other uniforms
+			//  - limit here is ANGLE's 254 max uniform vectors
+			//    (up to 54 should be safe)
 
-				for ( var i = 0; i < 6; i ++ ) {
+			var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
+			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
 
-					if ( _this.autoScaleCubemaps && ! isCompressed ) {
+			var maxBones = nVertexMatrices;
 
-						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
+			if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
 
-					} else {
+				maxBones = Math.min( object.bones.length, maxBones );
 
-						cubeImage[ i ] = texture.image[ i ];
+				if ( maxBones < object.bones.length ) {
 
-					}
+					console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
 
 				}
 
-				var image = cubeImage[ 0 ],
-				isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
-				glFormat = paramThreeToGL( texture.format ),
-				glType = paramThreeToGL( texture.type );
+			}
 
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
+			return maxBones;
 
-				for ( var i = 0; i < 6; i ++ ) {
+		}
 
-					if( !isCompressed ) {
+	};
 
-						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
+	function allocateLights( lights ) {
 
-					} else {
-						
-						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
+		var dirLights = 0;
+		var pointLights = 0;
+		var spotLights = 0;
+		var hemiLights = 0;
 
-						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
+		for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
 
-							mipmap = mipmaps[ j ];
-							if ( texture.format!==THREE.RGBAFormat ) {
+			var light = lights[ l ];
 
-								_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
+			if ( light.onlyShadow || light.visible === false ) continue;
 
-							} else {
-								_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
-							}
+			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
+			if ( light instanceof THREE.PointLight ) pointLights ++;
+			if ( light instanceof THREE.SpotLight ) spotLights ++;
+			if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
 
-						}
-					}
-				}
+		}
 
-				if ( texture.generateMipmaps && isImagePowerOfTwo ) {
+		return { 'directional' : dirLights, 'point' : pointLights, 'spot': spotLights, 'hemi': hemiLights };
 
-					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+	};
 
-				}
+	function allocateShadows( lights ) {
 
-				texture.needsUpdate = false;
+		var maxShadows = 0;
 
-				if ( texture.onUpdate ) texture.onUpdate();
+		for ( var l = 0, ll = lights.length; l < ll; l++ ) {
 
-			} else {
+			var light = lights[ l ];
 
-				_gl.activeTexture( _gl.TEXTURE0 + slot );
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
+			if ( ! light.castShadow ) continue;
 
-			}
+			if ( light instanceof THREE.SpotLight ) maxShadows ++;
+			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
 
 		}
 
+		return maxShadows;
+
 	};
 
-	function setCubeTextureDynamic ( texture, slot ) {
+	// Initialization
 
-		_gl.activeTexture( _gl.TEXTURE0 + slot );
-		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
+	function initGL() {
 
-	};
+		try {
 
-	// Render targets
+			var attributes = {
+				alpha: _alpha,
+				depth: _depth,
+				stencil: _stencil,
+				antialias: _antialias,
+				premultipliedAlpha: _premultipliedAlpha,
+				preserveDrawingBuffer: _preserveDrawingBuffer
+			};
 
-	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
+			_gl = _context || _canvas.getContext( 'webgl', attributes ) || _canvas.getContext( 'experimental-webgl', attributes );
 
-		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
+			if ( _gl === null ) {
 
-	};
+				throw 'Error creating WebGL context.';
 
-	function setupRenderBuffer ( renderbuffer, renderTarget  ) {
+			}
 
-		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
+		} catch ( error ) {
 
-		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
+			console.error( error );
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
+		}
 
-		/* For some reason this is not working. Defaulting to RGBA4.
-		} else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
+		_glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
+		_glExtensionTextureFloatLinear = _gl.getExtension( 'OES_texture_float_linear' );
+		_glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
-		*/
-		} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
+		_glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) || _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
+		_glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || _gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || _gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
 
-		} else {
+		_glExtensionElementIndexUint = _gl.getExtension( 'OES_element_index_uint' );
+		
+		
+		if ( _glExtensionTextureFloat === null ) {
 
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
+			console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
 
 		}
 
-	};
+		if ( _glExtensionStandardDerivatives === null ) {
 
-	this.setRenderTarget = function ( renderTarget ) {
+			console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
 
-		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
+		}
 
-		if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
+		if ( _glExtensionTextureFilterAnisotropic === null ) {
 
-			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
-			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
+			console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
 
-			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
+		}
 
-			renderTarget.__webglTexture = _gl.createTexture();
+		if ( _glExtensionCompressedTextureS3TC === null ) {
 
-			_this.info.memory.textures ++;
+			console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
 
-			// Setup texture, create render and frame buffers
+		}
 
-			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height ),
-				glFormat = paramThreeToGL( renderTarget.format ),
-				glType = paramThreeToGL( renderTarget.type );
+		if ( _glExtensionElementIndexUint === null ) {
 
-			if ( isCube ) {
+			console.log( 'THREE.WebGLRenderer: elementindex as unsigned integer not supported.' );
 
-				renderTarget.__webglFramebuffer = [];
-				renderTarget.__webglRenderbuffer = [];
+		}
 
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
+		if ( _gl.getShaderPrecisionFormat === undefined ) {
 
-				for ( var i = 0; i < 6; i ++ ) {
+			_gl.getShaderPrecisionFormat = function() {
 
-					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
-					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
+				return {
+					"rangeMin"  : 1,
+					"rangeMax"  : 1,
+					"precision" : 1
+				};
 
-					_gl.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 );
+	};
 
-				}
+	function setDefaultGLState () {
 
-				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
+		_gl.clearColor( 0, 0, 0, 1 );
+		_gl.clearDepth( 1 );
+		_gl.clearStencil( 0 );
 
-			} else {
+		_gl.enable( _gl.DEPTH_TEST );
+		_gl.depthFunc( _gl.LEQUAL );
 
-				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
+		_gl.frontFace( _gl.CCW );
+		_gl.cullFace( _gl.BACK );
+		_gl.enable( _gl.CULL_FACE );
 
-				if ( renderTarget.shareDepthFrom ) {
+		_gl.enable( _gl.BLEND );
+		_gl.blendEquation( _gl.FUNC_ADD );
+		_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
 
-					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
+		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
+		
+		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
 
-				} else {
+	};
 
-					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
+	// default plugins (order is important)
 
-				}
+	this.shadowMapPlugin = new THREE.ShadowMapPlugin();
+	this.addPrePlugin( this.shadowMapPlugin );
 
-				_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
+	this.addPostPlugin( new THREE.SpritePlugin() );
+	this.addPostPlugin( new THREE.LensFlarePlugin() );
 
-				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
+};
 
-				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
+/**
+ * @author szimek / https://github.com/szimek/
+ * @author alteredq / http://alteredqualia.com/
+ */
 
-				if ( renderTarget.shareDepthFrom ) {
+THREE.WebGLRenderTarget = function ( width, height, options ) {
 
-					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
+	this.width = width;
+	this.height = height;
 
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
+	options = options || {};
 
-					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
+	this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping;
+	this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping;
 
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
+	this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter;
+	this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter;
 
-					}
+	this.anisotropy = options.anisotropy !== undefined ? options.anisotropy : 1;
 
-				} else {
+	this.offset = new THREE.Vector2( 0, 0 );
+	this.repeat = new THREE.Vector2( 1, 1 );
 
-					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
+	this.format = options.format !== undefined ? options.format : THREE.RGBAFormat;
+	this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType;
 
-				}
+	this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
+	this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
 
-				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
+	this.generateMipmaps = true;
 
-			}
+	this.shareDepthFrom = null;
 
-			// Release everything
+};
 
-			if ( isCube ) {
+THREE.WebGLRenderTarget.prototype = {
 
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
+	constructor: THREE.WebGLRenderTarget,
 
-			} else {
+	clone: function () {
 
-				_gl.bindTexture( _gl.TEXTURE_2D, null );
+		var tmp = new THREE.WebGLRenderTarget( this.width, this.height );
 
-			}
+		tmp.wrapS = this.wrapS;
+		tmp.wrapT = this.wrapT;
 
-			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
-			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
+		tmp.magFilter = this.magFilter;
+		tmp.minFilter = this.minFilter;
 
-		}
+		tmp.anisotropy = this.anisotropy;
 
-		var framebuffer, width, height, vx, vy;
+		tmp.offset.copy( this.offset );
+		tmp.repeat.copy( this.repeat );
 
-		if ( renderTarget ) {
+		tmp.format = this.format;
+		tmp.type = this.type;
 
-			if ( isCube ) {
+		tmp.depthBuffer = this.depthBuffer;
+		tmp.stencilBuffer = this.stencilBuffer;
 
-				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
+		tmp.generateMipmaps = this.generateMipmaps;
 
-			} else {
+		tmp.shareDepthFrom = this.shareDepthFrom;
 
-				framebuffer = renderTarget.__webglFramebuffer;
+		return tmp;
 
-			}
+	},
 
-			width = renderTarget.width;
-			height = renderTarget.height;
+	dispose: function () {
 
-			vx = 0;
-			vy = 0;
+		this.dispatchEvent( { type: 'dispose' } );
 
-		} else {
+	}
 
-			framebuffer = null;
+};
 
-			width = _viewportWidth;
-			height = _viewportHeight;
+THREE.EventDispatcher.prototype.apply( THREE.WebGLRenderTarget.prototype );
 
-			vx = _viewportX;
-			vy = _viewportY;
+/**
+ * @author alteredq / http://alteredqualia.com
+ */
 
-		}
+THREE.WebGLRenderTargetCube = function ( width, height, options ) {
 
-		if ( framebuffer !== _currentFramebuffer ) {
+	THREE.WebGLRenderTarget.call( this, width, height, options );
 
-			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-			_gl.viewport( vx, vy, width, height );
+	this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
 
-			_currentFramebuffer = framebuffer;
+};
 
-		}
+THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype );
 
-		_currentWidth = width;
-		_currentHeight = height;
+THREE.WebGLProgram = ( function () {
 
-	};
+	var programIdCount = 0;
 
-	function updateRenderTargetMipmap ( renderTarget ) {
+	var generateDefines = function ( defines ) {
 
-		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
+		var value, chunk, chunks = [];
 
-			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
-			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
-			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
+		for ( var d in defines ) {
 
-		} else {
+			value = defines[ d ];
+			if ( value === false ) continue;
 
-			_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
-			_gl.generateMipmap( _gl.TEXTURE_2D );
-			_gl.bindTexture( _gl.TEXTURE_2D, null );
+			chunk = "#define " + d + " " + value;
+			chunks.push( chunk );
 
 		}
 
+		return chunks.join( "\n" );
+
 	};
 
-	// Fallback filters for non-power-of-2 textures
+	var cacheUniformLocations = function ( gl, program, identifiers ) {
 
-	function filterFallback ( f ) {
+		var uniforms = {};
 
-		if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
+		for ( var i = 0, l = identifiers.length; i < l; i ++ ) {
 
-			return _gl.NEAREST;
+			var id = identifiers[ i ];
+			uniforms[ id ] = gl.getUniformLocation( program, id );
 
 		}
 
-		return _gl.LINEAR;
+		return uniforms;
 
 	};
 
-	// Map three.js constants to WebGL constants
+	var cacheAttributeLocations = function ( gl, program, identifiers ) {
 
-	function paramThreeToGL ( p ) {
+		var attributes = {};
 
-		if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
-		if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
-		if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
+		for ( var i = 0, l = identifiers.length; i < l; i ++ ) {
 
-		if ( p === THREE.NearestFilter ) return _gl.NEAREST;
-		if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
-		if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
+			var id = identifiers[ i ];
+			attributes[ id ] = gl.getAttribLocation( program, id );
 
-		if ( p === THREE.LinearFilter ) return _gl.LINEAR;
-		if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
-		if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
+		}
 
-		if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
-		if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
-		if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
-		if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
-
-		if ( p === THREE.ByteType ) return _gl.BYTE;
-		if ( p === THREE.ShortType ) return _gl.SHORT;
-		if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
-		if ( p === THREE.IntType ) return _gl.INT;
-		if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
-		if ( p === THREE.FloatType ) return _gl.FLOAT;
-
-		if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
-		if ( p === THREE.RGBFormat ) return _gl.RGB;
-		if ( p === THREE.RGBAFormat ) return _gl.RGBA;
-		if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
-		if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
-
-		if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
-		if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
-		if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
-
-		if ( p === THREE.ZeroFactor ) return _gl.ZERO;
-		if ( p === THREE.OneFactor ) return _gl.ONE;
-		if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
-		if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
-		if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
-		if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
-		if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
-		if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
-
-		if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
-		if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
-		if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
-
-		if ( _glExtensionCompressedTextureS3TC !== undefined ) {
-
-			if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
-
-		}
-
-		return 0;
+		return attributes;
 
 	};
 
-	// Allocations
+	return function ( renderer, code, material, parameters ) {
 
-	function allocateBones ( object ) {
+		var _this = renderer;
+		var _gl = _this.context;
 
-		if ( _supportsBoneTextures && object && object.useVertexTexture ) {
+		var fragmentShader = material.fragmentShader;
+		var vertexShader = material.vertexShader;
+		var uniforms = material.uniforms;
+		var attributes = material.attributes;
+		var defines = material.defines;
+		var index0AttributeName = material.index0AttributeName;
 
-			return 1024;
+		var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
 
-		} else {
+		if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
 
-			// default for when object is not specified
-			// ( for example when prebuilding shader
-			//   to be used with multiple objects )
-			//
-			// 	- leave some extra space for other uniforms
-			//  - limit here is ANGLE's 254 max uniform vectors
-			//    (up to 54 should be safe)
+			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
 
-			var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
-			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
+		} else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
 
-			var maxBones = nVertexMatrices;
+			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
 
-			if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
+		}
 
-				maxBones = Math.min( object.bones.length, maxBones );
+		// console.log( "building new program " );
 
-				if ( maxBones < object.bones.length ) {
+		//
 
-					console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
+		var customDefines = generateDefines( defines );
 
-				}
+		//
 
-			}
+		var program = _gl.createProgram();
 
-			return maxBones;
+		var prefix_vertex = [
 
-		}
+			"precision " + parameters.precision + " float;",
+			"precision " + parameters.precision + " int;",
 
-	};
+			customDefines,
 
-	function allocateLights( lights ) {
+			parameters.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
 
-		var dirLights = 0;
-		var pointLights = 0;
-		var spotLights = 0;
-		var hemiLights = 0;
+			_this.gammaInput ? "#define GAMMA_INPUT" : "",
+			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
 
-		for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
+			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
+			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
+			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
+			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
 
-			var light = lights[ l ];
+			"#define MAX_SHADOWS " + parameters.maxShadows,
 
-			if ( light.onlyShadow || light.visible === false ) continue;
+			"#define MAX_BONES " + parameters.maxBones,
 
-			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
-			if ( light instanceof THREE.PointLight ) pointLights ++;
-			if ( light instanceof THREE.SpotLight ) spotLights ++;
-			if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
+			parameters.map ? "#define USE_MAP" : "",
+			parameters.envMap ? "#define USE_ENVMAP" : "",
+			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
+			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
+			parameters.normalMap ? "#define USE_NORMALMAP" : "",
+			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
+			parameters.vertexColors ? "#define USE_COLOR" : "",
 
-		}
+			parameters.skinning ? "#define USE_SKINNING" : "",
+			parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
 
-		return { 'directional' : dirLights, 'point' : pointLights, 'spot': spotLights, 'hemi': hemiLights };
+			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
+			parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
+			parameters.wrapAround ? "#define WRAP_AROUND" : "",
+			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
+			parameters.flipSided ? "#define FLIP_SIDED" : "",
 
-	};
+			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
+			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
+			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
+			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
 
-	function allocateShadows( lights ) {
+			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
 
-		var maxShadows = 0;
+			"uniform mat4 modelMatrix;",
+			"uniform mat4 modelViewMatrix;",
+			"uniform mat4 projectionMatrix;",
+			"uniform mat4 viewMatrix;",
+			"uniform mat3 normalMatrix;",
+			"uniform vec3 cameraPosition;",
 
-		for ( var l = 0, ll = lights.length; l < ll; l++ ) {
+			"attribute vec3 position;",
+			"attribute vec3 normal;",
+			"attribute vec2 uv;",
+			"attribute vec2 uv2;",
 
-			var light = lights[ l ];
+			"#ifdef USE_COLOR",
 
-			if ( ! light.castShadow ) continue;
+			"	attribute vec3 color;",
 
-			if ( light instanceof THREE.SpotLight ) maxShadows ++;
-			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
+			"#endif",
 
-		}
+			"#ifdef USE_MORPHTARGETS",
 
-		return maxShadows;
+			"	attribute vec3 morphTarget0;",
+			"	attribute vec3 morphTarget1;",
+			"	attribute vec3 morphTarget2;",
+			"	attribute vec3 morphTarget3;",
 
-	};
+			"	#ifdef USE_MORPHNORMALS",
 
-	// Initialization
+			"		attribute vec3 morphNormal0;",
+			"		attribute vec3 morphNormal1;",
+			"		attribute vec3 morphNormal2;",
+			"		attribute vec3 morphNormal3;",
 
-	function initGL() {
+			"	#else",
 
-		try {
+			"		attribute vec3 morphTarget4;",
+			"		attribute vec3 morphTarget5;",
+			"		attribute vec3 morphTarget6;",
+			"		attribute vec3 morphTarget7;",
 
-			var attributes = {
-				alpha: _alpha,
-				depth: _depth,
-				stencil: _stencil,
-				antialias: _antialias,
-				premultipliedAlpha: _premultipliedAlpha,
-				preserveDrawingBuffer: _preserveDrawingBuffer
-			};
+			"	#endif",
 
-			_gl = _context || _canvas.getContext( 'webgl', attributes ) || _canvas.getContext( 'experimental-webgl', attributes );
+			"#endif",
 
-			if ( _gl === null ) {
+			"#ifdef USE_SKINNING",
 
-				throw 'Error creating WebGL context.';
+			"	attribute vec4 skinIndex;",
+			"	attribute vec4 skinWeight;",
 
-			}
+			"#endif",
 
-		} catch ( error ) {
+			""
 
-			console.error( error );
+		].join( '\n' );
 
-		}
+		var prefix_fragment = [
 
-		_glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
-		_glExtensionTextureFloatLinear = _gl.getExtension( 'OES_texture_float_linear' );
-		_glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
+			"precision " + parameters.precision + " float;",
+			"precision " + parameters.precision + " int;",
 
-		_glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) || _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
+			( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
 
-		_glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || _gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || _gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
+			customDefines,
 
-		_glExtensionElementIndexUint = _gl.getExtension( 'OES_element_index_uint' );
-		
-		
-		if ( _glExtensionTextureFloat === null ) {
+			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
+			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
+			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
+			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
 
-			console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
+			"#define MAX_SHADOWS " + parameters.maxShadows,
 
-		}
+			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
 
-		if ( _glExtensionStandardDerivatives === null ) {
+			_this.gammaInput ? "#define GAMMA_INPUT" : "",
+			_this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
 
-			console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
+			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
+			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
 
-		}
+			parameters.map ? "#define USE_MAP" : "",
+			parameters.envMap ? "#define USE_ENVMAP" : "",
+			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
+			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
+			parameters.normalMap ? "#define USE_NORMALMAP" : "",
+			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
+			parameters.vertexColors ? "#define USE_COLOR" : "",
 
-		if ( _glExtensionTextureFilterAnisotropic === null ) {
+			parameters.metal ? "#define METAL" : "",
+			parameters.wrapAround ? "#define WRAP_AROUND" : "",
+			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
+			parameters.flipSided ? "#define FLIP_SIDED" : "",
 
-			console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
+			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
+			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
+			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
+			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
 
-		}
+			"uniform mat4 viewMatrix;",
+			"uniform vec3 cameraPosition;",
+			""
 
-		if ( _glExtensionCompressedTextureS3TC === null ) {
+		].join( '\n' );
 
-			console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
+		var glVertexShader = new THREE.WebGLShader( _gl, _gl.VERTEX_SHADER, prefix_vertex + vertexShader );
+		var glFragmentShader = new THREE.WebGLShader( _gl, _gl.FRAGMENT_SHADER, prefix_fragment + fragmentShader );
 
-		}
+		_gl.attachShader( program, glVertexShader );
+		_gl.attachShader( program, glFragmentShader );
 
-		if ( _glExtensionElementIndexUint === null ) {
+		// Force a particular attribute to index 0.
+		// because potentially expensive emulation is done by browser if attribute 0 is disabled.
+		// And, color, for example is often automatically bound to index 0 so disabling it
+		if ( index0AttributeName !== undefined ) {
 
-			console.log( 'THREE.WebGLRenderer: elementindex as unsigned integer not supported.' );
+			_gl.bindAttribLocation( program, 0, index0AttributeName );
 
 		}
 
-		if ( _gl.getShaderPrecisionFormat === undefined ) {
+		_gl.linkProgram( program );
 
-			_gl.getShaderPrecisionFormat = function() {
+		if ( _gl.getProgramParameter( program, _gl.LINK_STATUS ) === false ) {
 
-				return {
-					"rangeMin"  : 1,
-					"rangeMax"  : 1,
-					"precision" : 1
-				};
+			console.error( 'Could not initialise shader' );
+			console.error( 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) );
+			console.error( 'gl.getError()', _gl.getError() );
 
-			}
 		}
 
-	};
-
-	function setDefaultGLState () {
-
-		_gl.clearColor( 0, 0, 0, 1 );
-		_gl.clearDepth( 1 );
-		_gl.clearStencil( 0 );
-
-		_gl.enable( _gl.DEPTH_TEST );
-		_gl.depthFunc( _gl.LEQUAL );
-
-		_gl.frontFace( _gl.CCW );
-		_gl.cullFace( _gl.BACK );
-		_gl.enable( _gl.CULL_FACE );
-
-		_gl.enable( _gl.BLEND );
-		_gl.blendEquation( _gl.FUNC_ADD );
-		_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
-
-		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
-		
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
-
-	};
-
-	// default plugins (order is important)
-
-	this.shadowMapPlugin = new THREE.ShadowMapPlugin();
-	this.addPrePlugin( this.shadowMapPlugin );
-
-	this.addPostPlugin( new THREE.SpritePlugin() );
-	this.addPostPlugin( new THREE.LensFlarePlugin() );
-
-};
-
-/**
- * @author szimek / https://github.com/szimek/
- * @author alteredq / http://alteredqualia.com/
- */
-
-THREE.WebGLRenderTarget = function ( width, height, options ) {
-
-	this.width = width;
-	this.height = height;
+		if ( _gl.getProgramInfoLog( program ) !== '' ) {
 
-	options = options || {};
+			console.error( 'gl.getProgramInfoLog()', _gl.getProgramInfoLog( program ) );
 
-	this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping;
-	this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping;
+		}
 
-	this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter;
-	this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter;
+		// cache uniform locations
 
-	this.anisotropy = options.anisotropy !== undefined ? options.anisotropy : 1;
+		var identifiers = [
 
-	this.offset = new THREE.Vector2( 0, 0 );
-	this.repeat = new THREE.Vector2( 1, 1 );
+			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
+			'morphTargetInfluences'
 
-	this.format = options.format !== undefined ? options.format : THREE.RGBAFormat;
-	this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType;
+		];
 
-	this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
-	this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
+		if ( parameters.useVertexTexture ) {
 
-	this.generateMipmaps = true;
+			identifiers.push( 'boneTexture' );
+			identifiers.push( 'boneTextureWidth' );
+			identifiers.push( 'boneTextureHeight' );
 
-	this.shareDepthFrom = null;
+		} else {
 
-};
+			identifiers.push( 'boneGlobalMatrices' );
 
-THREE.WebGLRenderTarget.prototype = {
+		}
 
-	constructor: THREE.WebGLRenderTarget,
+		for ( var u in uniforms ) {
 
-	clone: function () {
+			identifiers.push( u );
 
-		var tmp = new THREE.WebGLRenderTarget( this.width, this.height );
+		}
 
-		tmp.wrapS = this.wrapS;
-		tmp.wrapT = this.wrapT;
+		this.uniforms = cacheUniformLocations( _gl, program, identifiers );
 
-		tmp.magFilter = this.magFilter;
-		tmp.minFilter = this.minFilter;
+		// cache attributes locations
 
-		tmp.anisotropy = this.anisotropy;
+		identifiers = [
 
-		tmp.offset.copy( this.offset );
-		tmp.repeat.copy( this.repeat );
+			"position", "normal", "uv", "uv2", "tangent", "color",
+			"skinIndex", "skinWeight", "lineDistance"
 
-		tmp.format = this.format;
-		tmp.type = this.type;
+		];
 
-		tmp.depthBuffer = this.depthBuffer;
-		tmp.stencilBuffer = this.stencilBuffer;
+		for ( var i = 0; i < parameters.maxMorphTargets; i ++ ) {
 
-		tmp.generateMipmaps = this.generateMipmaps;
+			identifiers.push( "morphTarget" + i );
 
-		tmp.shareDepthFrom = this.shareDepthFrom;
+		}
 
-		return tmp;
+		for ( var i = 0; i < parameters.maxMorphNormals; i ++ ) {
 
-	},
+			identifiers.push( "morphNormal" + i );
 
-	dispose: function () {
+		}
 
-		this.dispatchEvent( { type: 'dispose' } );
+		for ( var a in attributes ) {
 
-	}
+			identifiers.push( a );
 
-};
+		}
 
-THREE.EventDispatcher.prototype.apply( THREE.WebGLRenderTarget.prototype );
+		this.attributes = cacheAttributeLocations( _gl, program, identifiers );
 
-/**
- * @author alteredq / http://alteredqualia.com
- */
+		//
 
-THREE.WebGLRenderTargetCube = function ( width, height, options ) {
+		this.id = programIdCount ++;
+		this.code = code;
+		this.usedTimes = 1;
+		this.program = program;
+		this.vertexShader = glVertexShader; // _gl.getShaderSource( glVertexShader );
+		this.fragmentShader = _gl.getShaderSource( glFragmentShader );
 
-	THREE.WebGLRenderTarget.call( this, width, height, options );
+		// clean up
 
-	this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
+		_gl.deleteShader( glVertexShader );
+		_gl.deleteShader( glFragmentShader );
 
-};
+		return this;
 
-THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype );
+	};
 
+} )();
 THREE.WebGLShader = ( function () {
 
 	var addLineNumbers = function ( string ) {

Plik diff jest za duży
+ 197 - 205
build/three.min.js


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

@@ -293,7 +293,7 @@ THREE.WebGLProgram = ( function () {
 
 		// cache attributes locations
 
-		var identifiers = [
+		identifiers = [
 
 			"position", "normal", "uv", "uv2", "tangent", "color",
 			"skinIndex", "skinWeight", "lineDistance"

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików