WebGLRenderer.js 92.6 KB
Newer Older
M
Mr.doob 已提交
1 2 3 4 5 6 7 8 9
/**
 * @author supereggbert / http://www.paulbrunt.co.uk/
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 * @author szimek / https://github.com/szimek/
 */

THREE.WebGLRenderer = function ( parameters ) {

10
	console.log( 'THREE.WebGLRenderer', THREE.REVISION );
M
Mr.doob 已提交
11 12 13 14

	parameters = parameters || {};

	var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
15
	_context = parameters.context !== undefined ? parameters.context : null,
M
Mr.doob 已提交
16

M
Mr.doob 已提交
17 18
	_width = _canvas.width,
	_height = _canvas.height,
19

20 21
	pixelRatio = 1,

M
Mr.doob 已提交
22 23
	_precision = parameters.precision !== undefined ? parameters.precision : 'highp',

24
	_alpha = parameters.alpha !== undefined ? parameters.alpha : false,
25
	_depth = parameters.depth !== undefined ? parameters.depth : true,
M
Mr.doob 已提交
26
	_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
27 28
	_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
	_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
M
Mr.doob 已提交
29
	_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
30
	_logarithmicDepthBuffer = parameters.logarithmicDepthBuffer !== undefined ? parameters.logarithmicDepthBuffer : false,
M
Mr.doob 已提交
31

32 33
	_clearColor = new THREE.Color( 0x000000 ),
	_clearAlpha = 0;
M
Mr.doob 已提交
34

M
Mr.doob 已提交
35
	var lights = [];
M
Mr.doob 已提交
36

O
OpenShift guest 已提交
37
	var opaqueObjects = [];
38
	var transparentObjects = [];
39

M
Mr.doob 已提交
40 41 42
	var sprites = [];
	var lensFlares = [];

M
Mr.doob 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
	// public properties

	this.domElement = _canvas;
	this.context = null;

	// clearing

	this.autoClear = true;
	this.autoClearColor = true;
	this.autoClearDepth = true;
	this.autoClearStencil = true;

	// scene graph

	this.sortObjects = true;

	// physically based shading

61
	this.gammaFactor = 2.0;	// for backwards compatibility
M
Mr.doob 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	this.gammaInput = false;
	this.gammaOutput = false;

	// morphs

	this.maxMorphTargets = 8;
	this.maxMorphNormals = 4;

	// flags

	this.autoScaleCubemaps = true;

	// info

	this.info = {

		memory: {

			programs: 0,
			geometries: 0,
			textures: 0

		},

		render: {

			calls: 0,
			vertices: 0,
			faces: 0,
			points: 0

		}

	};

	// internal properties

	var _this = this,

	_programs = [],

	// internal state cache

	_currentProgram = null,
	_currentFramebuffer = null,
107
	_currentMaterialId = - 1,
108
	_currentGeometryProgram = '',
M
Mr.doob 已提交
109 110 111 112 113 114
	_currentCamera = null,

	_usedTextureUnits = 0,

	_viewportX = 0,
	_viewportY = 0,
115 116
	_viewportWidth = _canvas.width,
	_viewportHeight = _canvas.height,
M
Mr.doob 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	_currentWidth = 0,
	_currentHeight = 0,

	// frustum

	_frustum = new THREE.Frustum(),

	 // camera matrices cache

	_projScreenMatrix = new THREE.Matrix4(),

	_vector3 = new THREE.Vector3(),

	// light arrays cache

	_direction = new THREE.Vector3(),

	_lightsNeedUpdate = true,

	_lights = {

		ambient: [ 0, 0, 0 ],
G
gero3 已提交
139
		directional: { length: 0, colors:[], positions: [] },
M
Mr.doob 已提交
140 141
		point: { length: 0, colors: [], positions: [], distances: [], decays: [] },
		spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [], decays: [] },
G
gero3 已提交
142
		hemi: { length: 0, skyColors: [], groundColors: [], positions: [] }
M
Mr.doob 已提交
143 144 145 146 147 148 149

	};

	// initialize

	var _gl;

M
Mr.doob 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
	try {

		var attributes = {
			alpha: _alpha,
			depth: _depth,
			stencil: _stencil,
			antialias: _antialias,
			premultipliedAlpha: _premultipliedAlpha,
			preserveDrawingBuffer: _preserveDrawingBuffer
		};

		_gl = _context || _canvas.getContext( 'webgl', attributes ) || _canvas.getContext( 'experimental-webgl', attributes );

		if ( _gl === null ) {

165 166 167 168 169 170 171 172 173
			if ( _canvas.getContext( 'webgl') !== null ) {

				throw 'Error creating WebGL context with your selected attributes.';

			} else {

				throw 'Error creating WebGL context.';

			}
M
Mr.doob 已提交
174 175 176

		}

177 178 179 180 181 182 183
		_canvas.addEventListener( 'webglcontextlost', function ( event ) {

			event.preventDefault();

			resetGLState();
			setDefaultGLState();

M
Mr.doob 已提交
184
			objects.objects = {};
185 186 187

		}, false);

M
Mr.doob 已提交
188 189
	} catch ( error ) {

190
		console.error( 'THREE.WebGLRenderer: ' + error );
M
Mr.doob 已提交
191 192 193

	}

M
Mr.doob 已提交
194 195
	var state = new THREE.WebGLState( _gl, paramThreeToGL );

M
Mr.doob 已提交
196 197 198 199 200 201 202 203 204 205 206
	if ( _gl.getShaderPrecisionFormat === undefined ) {

		_gl.getShaderPrecisionFormat = function () {

			return {
				'rangeMin': 1,
				'rangeMax': 1,
				'precision': 1
			};

		}
207

M
Mr.doob 已提交
208
	}
M
Mr.doob 已提交
209

210
	var extensions = new THREE.WebGLExtensions( _gl );
M
Mr.doob 已提交
211
	var objects = new THREE.WebGLObjects( _gl, this.info );
212

213 214
	extensions.get( 'OES_texture_float' );
	extensions.get( 'OES_texture_float_linear' );
215 216
	extensions.get( 'OES_texture_half_float' );
	extensions.get( 'OES_texture_half_float_linear' );
217
	extensions.get( 'OES_standard_derivatives' );
B
Ben Adams 已提交
218
	extensions.get( 'ANGLE_instanced_arrays' );
219

220 221
	if ( extensions.get( 'OES_element_index_uint' ) ) {

222
		THREE.BufferGeometry.MaxIndex = 4294967296;
223 224 225

	}

M
Mr.doob 已提交
226 227
	if ( _logarithmicDepthBuffer ) {

228
		extensions.get( 'EXT_frag_depth' );
M
Mr.doob 已提交
229 230 231 232 233

	}

	//

234
	var glClearColor = function ( r, g, b, a ) {
235 236 237

		if ( _premultipliedAlpha === true ) {

238
			r *= a; g *= a; b *= a;
239 240 241

		}

242 243
		_gl.clearColor( r, g, b, a );

244 245
	};

246
	var setDefaultGLState = function () {
M
Mr.doob 已提交
247

M
Mr.doob 已提交
248
		state.init();
M
Mr.doob 已提交
249 250 251

		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );

252
		glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
M
Mr.doob 已提交
253

254 255 256 257 258 259 260
	};

	var resetGLState = function () {

		_currentProgram = null;
		_currentCamera = null;

261
		_currentGeometryProgram = '';
262 263 264 265
		_currentMaterialId = - 1;

		_lightsNeedUpdate = true;

M
Mr.doob 已提交
266 267
		state.reset();

268
	};
M
Mr.doob 已提交
269 270 271 272

	setDefaultGLState();

	this.context = _gl;
273
	this.extensions = extensions;
M
Mr.doob 已提交
274
	this.state = state;
M
Mr.doob 已提交
275

M
Mr.doob 已提交
276 277
	// shadow map

M
Mr.doob 已提交
278
	var shadowMap = new THREE.WebGLShadowMap( this, lights, objects );
M
Mr.doob 已提交
279

280
	this.shadowMap = shadowMap;
M
Mr.doob 已提交
281

M
Mr.doob 已提交
282 283 284 285 286 287 288
	// GPU capabilities

	var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
	var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
	var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
	var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );

289 290
	var _supportsVertexTextures = _maxVertexTextures > 0;
	var _supportsBoneTextures = _supportsVertexTextures && extensions.get( 'OES_texture_float' );
B
Ben Adams 已提交
291
	var _supportsInstancedArrays = extensions.get( 'ANGLE_instanced_arrays' );
M
Mr.doob 已提交
292

293
	//
294

295 296
	var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
	var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
297

298 299
	var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
	var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
300

301
	var getCompressedTextureFormats = ( function () {
302

303
		var array;
304

305
		return function () {
306

307
			if ( array !== undefined ) {
308

309
				return array;
M
Mr.doob 已提交
310

311
			}
M
Mr.doob 已提交
312

313
			array = [];
M
Mr.doob 已提交
314

315 316 317 318
			if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) || extensions.get( 'WEBGL_compressed_texture_s3tc' ) ) {

				var formats = _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS );

G
gero3 已提交
319
				for ( var i = 0; i < formats.length; i ++ ) {
320 321 322 323 324 325

					array.push( formats[ i ] );

				}

			}
326

327 328 329 330 331
			return array;

		};

	} )();
M
Mr.doob 已提交
332 333 334 335 336 337

	// clamp precision to maximum available

	var highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
	var mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;

338
	if ( _precision === 'highp' && ! highpAvailable ) {
M
Mr.doob 已提交
339 340 341

		if ( mediumpAvailable ) {

342
			_precision = 'mediump';
343
			console.warn( 'THREE.WebGLRenderer: highp not supported, using mediump.' );
M
Mr.doob 已提交
344 345 346

		} else {

347
			_precision = 'lowp';
348
			console.warn( 'THREE.WebGLRenderer: highp and mediump not supported, using lowp.' );
M
Mr.doob 已提交
349 350 351 352 353

		}

	}

354
	if ( _precision === 'mediump' && ! mediumpAvailable ) {
M
Mr.doob 已提交
355

356
		_precision = 'lowp';
357
		console.warn( 'THREE.WebGLRenderer: mediump not supported, using lowp.' );
M
Mr.doob 已提交
358 359 360

	}

M
Mr.doob 已提交
361 362 363 364 365
	// Plugins

	var spritePlugin = new THREE.SpritePlugin( this, sprites );
	var lensFlarePlugin = new THREE.LensFlarePlugin( this, lensFlares );

M
Mr.doob 已提交
366 367 368 369 370 371 372 373
	// API

	this.getContext = function () {

		return _gl;

	};

374 375 376 377 378 379
	this.forceContextLoss = function () {

		extensions.get( 'WEBGL_lose_context' ).loseContext();

	};

M
Mr.doob 已提交
380 381 382 383 384 385
	this.supportsVertexTextures = function () {

		return _supportsVertexTextures;

	};

B
Ben Adams 已提交
386 387
	this.supportsInstancedArrays = function () {

M
Mr.doob 已提交
388
		return _supportsInstancedArrays;
B
Ben Adams 已提交
389 390 391

	};

M
Mr.doob 已提交
392 393
	this.supportsFloatTextures = function () {

394
		return extensions.get( 'OES_texture_float' );
M
Mr.doob 已提交
395 396

	};
397

398 399 400 401 402 403
	this.supportsHalfFloatTextures = function () {

		return extensions.get( 'OES_texture_half_float' );

	};

M
Mr.doob 已提交
404 405
	this.supportsStandardDerivatives = function () {

406
		return extensions.get( 'OES_standard_derivatives' );
M
Mr.doob 已提交
407 408

	};
409

M
Mr.doob 已提交
410 411
	this.supportsCompressedTextureS3TC = function () {

412
		return extensions.get( 'WEBGL_compressed_texture_s3tc' );
M
Mr.doob 已提交
413 414

	};
415

P
Pierre Lepers 已提交
416 417
	this.supportsCompressedTexturePVRTC = function () {

418
		return extensions.get( 'WEBGL_compressed_texture_pvrtc' );
P
Pierre Lepers 已提交
419 420 421

	};

422 423
	this.supportsBlendMinMax = function () {

424
		return extensions.get( 'EXT_blend_minmax' );
425 426 427

	};

428
	this.getMaxAnisotropy = ( function () {
M
Mr.doob 已提交
429

430
		var value;
M
Mr.doob 已提交
431

432 433
		return function () {

M
Mr.doob 已提交
434
			if ( value !== undefined ) return value;
435

M
Mr.doob 已提交
436
			var extension = extensions.get( 'EXT_texture_filter_anisotropic' );
437

M
Mr.doob 已提交
438
			if ( extension !== null ) {
439

M
Mr.doob 已提交
440
				value = _gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
441

M
Mr.doob 已提交
442 443 444 445 446
			} else {

				value = 0;

			}
447 448 449 450 451 452

			return value;

		}

	} )();
M
Mr.doob 已提交
453 454 455 456 457 458 459

	this.getPrecision = function () {

		return _precision;

	};

460 461 462 463 464 465 466 467
	this.getPixelRatio = function () {

		return pixelRatio;

	};

	this.setPixelRatio = function ( value ) {

468
		if ( value !== undefined ) pixelRatio = value;
469 470 471

	};

472 473 474 475 476 477 478 479 480
	this.getSize = function () {

		return {
			width: _width,
			height: _height
		};

	};

481
	this.setSize = function ( width, height, updateStyle ) {
M
Mr.doob 已提交
482

483 484 485
		_width = width;
		_height = height;

486 487
		_canvas.width = width * pixelRatio;
		_canvas.height = height * pixelRatio;
488

489
		if ( updateStyle !== false ) {
490

G
gero3 已提交
491 492
			_canvas.style.width = width + 'px';
			_canvas.style.height = height + 'px';
493

G
gero3 已提交
494
		}
M
Mr.doob 已提交
495

496
		this.setViewport( 0, 0, width, height );
M
Mr.doob 已提交
497 498 499 500 501

	};

	this.setViewport = function ( x, y, width, height ) {

502 503
		_viewportX = x * pixelRatio;
		_viewportY = y * pixelRatio;
M
Mr.doob 已提交
504

505 506
		_viewportWidth = width * pixelRatio;
		_viewportHeight = height * pixelRatio;
M
Mr.doob 已提交
507 508 509 510 511 512 513

		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );

	};

	this.setScissor = function ( x, y, width, height ) {

514
		_gl.scissor(
515 516 517 518
			x * pixelRatio,
			y * pixelRatio,
			width * pixelRatio,
			height * pixelRatio
519
		);
M
Mr.doob 已提交
520 521 522 523 524 525 526 527 528 529 530

	};

	this.enableScissorTest = function ( enable ) {

		enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );

	};

	// Clearing

M
Mr.doob 已提交
531
	this.getClearColor = function () {
M
Mr.doob 已提交
532

M
Mr.doob 已提交
533
		return _clearColor;
M
Mr.doob 已提交
534 535 536

	};

M
Mr.doob 已提交
537
	this.setClearColor = function ( color, alpha ) {
M
Mr.doob 已提交
538

M
Mr.doob 已提交
539
		_clearColor.set( color );
540

M
Mr.doob 已提交
541
		_clearAlpha = alpha !== undefined ? alpha : 1;
M
Mr.doob 已提交
542

543
		glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
M
Mr.doob 已提交
544 545 546

	};

M
Mr.doob 已提交
547
	this.getClearAlpha = function () {
M
Mr.doob 已提交
548

M
Mr.doob 已提交
549
		return _clearAlpha;
M
Mr.doob 已提交
550 551 552

	};

M
Mr.doob 已提交
553
	this.setClearAlpha = function ( alpha ) {
M
Mr.doob 已提交
554

M
Mr.doob 已提交
555
		_clearAlpha = alpha;
M
Mr.doob 已提交
556

557
		glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
M
Mr.doob 已提交
558 559 560 561 562 563 564 565 566 567 568 569

	};

	this.clear = function ( color, depth, stencil ) {

		var bits = 0;

		if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
		if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
		if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;

		_gl.clear( bits );
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587

	};

	this.clearColor = function () {

		_gl.clear( _gl.COLOR_BUFFER_BIT );

	};

	this.clearDepth = function () {

		_gl.clear( _gl.DEPTH_BUFFER_BIT );

	};

	this.clearStencil = function () {

		_gl.clear( _gl.STENCIL_BUFFER_BIT );
M
Mr.doob 已提交
588 589 590 591 592 593 594 595 596 597

	};

	this.clearTarget = function ( renderTarget, color, depth, stencil ) {

		this.setRenderTarget( renderTarget );
		this.clear( color, depth, stencil );

	};

M
Mr.doob 已提交
598 599
	// Reset

600
	this.resetGLState = resetGLState;
M
Mr.doob 已提交
601

M
Mr.doob 已提交
602
	// Events
M
Mr.doob 已提交
603

M
Mr.doob 已提交
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
	var onTextureDispose = function ( event ) {

		var texture = event.target;

		texture.removeEventListener( 'dispose', onTextureDispose );

		deallocateTexture( texture );

		_this.info.memory.textures --;


	};

	var onRenderTargetDispose = function ( event ) {

		var renderTarget = event.target;

		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );

		deallocateRenderTarget( renderTarget );

		_this.info.memory.textures --;

	};

	var onMaterialDispose = function ( event ) {

		var material = event.target;

		material.removeEventListener( 'dispose', onMaterialDispose );

		deallocateMaterial( material );

	};

	// Buffer deallocation

	var deallocateTexture = function ( texture ) {

		if ( texture.image && texture.image.__webglTextureCube ) {

			// cube texture

			_gl.deleteTexture( texture.image.__webglTextureCube );

M
Mr.doob 已提交
649 650
			delete texture.image.__webglTextureCube;

651 652 653 654 655 656 657 658 659 660 661
		} else {

			// 2D texture

			if ( texture.__webglInit === undefined ) return;

			_gl.deleteTexture( texture.__webglTexture );

			delete texture.__webglTexture;
			delete texture.__webglInit;

M
Mr.doob 已提交
662 663 664 665 666 667
		}

	};

	var deallocateRenderTarget = function ( renderTarget ) {

M
Mr.doob 已提交
668
		if ( ! renderTarget || renderTarget.__webglTexture === undefined ) return;
M
Mr.doob 已提交
669 670 671

		_gl.deleteTexture( renderTarget.__webglTexture );

M
Mr.doob 已提交
672 673
		delete renderTarget.__webglTexture;

M
Mr.doob 已提交
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {

			for ( var i = 0; i < 6; i ++ ) {

				_gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
				_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );

			}

		} else {

			_gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
			_gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );

		}

M
Mr.doob 已提交
690 691 692
		delete renderTarget.__webglFramebuffer;
		delete renderTarget.__webglRenderbuffer;

M
Mr.doob 已提交
693 694 695 696
	};

	var deallocateMaterial = function ( material ) {

697
		var program = material.program.program;
M
Mr.doob 已提交
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761

		if ( program === undefined ) return;

		material.program = undefined;

		// only deallocate GL program if this was the last use of shared program
		// assumed there is only single copy of any program in the _programs list
		// (that's how it's constructed)

		var i, il, programInfo;
		var deleteProgram = false;

		for ( i = 0, il = _programs.length; i < il; i ++ ) {

			programInfo = _programs[ i ];

			if ( programInfo.program === program ) {

				programInfo.usedTimes --;

				if ( programInfo.usedTimes === 0 ) {

					deleteProgram = true;

				}

				break;

			}

		}

		if ( deleteProgram === true ) {

			// avoid using array.splice, this is costlier than creating new array from scratch

			var newPrograms = [];

			for ( i = 0, il = _programs.length; i < il; i ++ ) {

				programInfo = _programs[ i ];

				if ( programInfo.program !== program ) {

					newPrograms.push( programInfo );

				}

			}

			_programs = newPrograms;

			_gl.deleteProgram( program );

			_this.info.memory.programs --;

		}

	};

	// Buffer rendering

	this.renderBufferImmediate = function ( object, program, material ) {

762
		state.initAttributes();
763

M
Mr.doob 已提交
764 765 766 767 768
		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();

769
		var attributes = program.getAttributes();
770

M
Mr.doob 已提交
771 772 773 774
		if ( object.hasPositions ) {

			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
775

776 777
			state.enableAttribute( attributes.position );
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
778 779 780 781 782 783 784

		}

		if ( object.hasNormals ) {

			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );

M
Mr.doob 已提交
785
			if ( material instanceof THREE.MeshPhongMaterial === false && material.shading === THREE.FlatShading ) {
M
Mr.doob 已提交
786 787 788 789 790 791

				var nx, ny, nz,
					nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
					normalArray,
					i, il = object.count * 3;

792
				for ( i = 0; i < il; i += 9 ) {
M
Mr.doob 已提交
793 794 795

					normalArray = object.normalArray;

M
Mr.doob 已提交
796 797 798
					nax = normalArray[ i ];
					nay = normalArray[ i + 1 ];
					naz = normalArray[ i + 2 ];
M
Mr.doob 已提交
799

M
Mr.doob 已提交
800 801 802
					nbx = normalArray[ i + 3 ];
					nby = normalArray[ i + 4 ];
					nbz = normalArray[ i + 5 ];
M
Mr.doob 已提交
803

M
Mr.doob 已提交
804 805 806
					ncx = normalArray[ i + 6 ];
					ncy = normalArray[ i + 7 ];
					ncz = normalArray[ i + 8 ];
M
Mr.doob 已提交
807 808 809 810 811

					nx = ( nax + nbx + ncx ) / 3;
					ny = ( nay + nby + ncy ) / 3;
					nz = ( naz + nbz + ncz ) / 3;

M
Mr.doob 已提交
812
					normalArray[ i     ] = nx;
M
Mr.doob 已提交
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
					normalArray[ i + 1 ] = ny;
					normalArray[ i + 2 ] = nz;

					normalArray[ i + 3 ] = nx;
					normalArray[ i + 4 ] = ny;
					normalArray[ i + 5 ] = nz;

					normalArray[ i + 6 ] = nx;
					normalArray[ i + 7 ] = ny;
					normalArray[ i + 8 ] = nz;

				}

			}

			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
829

830
			state.enableAttribute( attributes.normal );
831

832
			_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
833 834 835 836 837 838 839

		}

		if ( object.hasUvs && material.map ) {

			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
840

841
			state.enableAttribute( attributes.uv );
842

843
			_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
844 845 846 847 848 849 850

		}

		if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {

			_gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
851

852
			state.enableAttribute( attributes.color );
853

854
			_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
855 856 857

		}

858
		state.disableUnusedAttributes();
859

M
Mr.doob 已提交
860 861 862 863 864 865
		_gl.drawArrays( _gl.TRIANGLES, 0, object.count );

		object.count = 0;

	};

866
	function setupVertexAttributes( material, program, geometry, startIndex ) {
M
Mr.doob 已提交
867

M
Mr.doob 已提交
868
		var extension;
B
Ben Adams 已提交
869

M
Mr.doob 已提交
870
		if ( geometry instanceof THREE.InstancedBufferGeometry ) {
B
Ben Adams 已提交
871

M
Mr.doob 已提交
872
			extension = extensions.get( 'ANGLE_instanced_arrays' );
B
Ben Adams 已提交
873

M
Mr.doob 已提交
874
			if ( extension === null ) {
B
Ben Adams 已提交
875

876
				console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
M
Mr.doob 已提交
877
				return;
B
Ben Adams 已提交
878

M
Mr.doob 已提交
879 880 881
			}

		}
B
Ben Adams 已提交
882

883
		var geometryAttributes = geometry.attributes;
884

885
		var programAttributes = program.getAttributes();
886

887
		var materialDefaultAttributeValues = material.defaultAttributeValues;
888

889
		for ( var name in programAttributes ) {
890

891
			var programAttribute = programAttributes[ name ];
M
Mr.doob 已提交
892

M
Mr.doob 已提交
893
			if ( programAttribute >= 0 ) {
M
Mr.doob 已提交
894

895
				var geometryAttribute = geometryAttributes[ name ];
896

M
Mr.doob 已提交
897
				if ( geometryAttribute !== undefined ) {
M
Mr.doob 已提交
898

M
Mr.doob 已提交
899
					var size = geometryAttribute.itemSize;
B
Ben Adams 已提交
900
					state.enableAttribute( programAttribute );
M
Mr.doob 已提交
901

B
Ben Adams 已提交
902
					if ( geometryAttribute instanceof THREE.InterleavedBufferAttribute ) {
903

M
Mr.doob 已提交
904 905 906 907 908 909
						var data = geometryAttribute.data;
						var stride = data.stride;
						var offset = geometryAttribute.offset;

						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryAttribute.data.buffer );
						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
910

M
Mr.doob 已提交
911
						if ( data instanceof THREE.InstancedInterleavedBuffer ) {
M
Mr.doob 已提交
912

M
Mr.doob 已提交
913
							if ( extension === null ) {
B
Ben Adams 已提交
914

915
								console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferAttribute but hardware does not support extension ANGLE_instanced_arrays.' );
M
Mr.doob 已提交
916
								return;
B
Ben Adams 已提交
917

M
Mr.doob 已提交
918
							}
B
Ben Adams 已提交
919

M
Mr.doob 已提交
920
							extension.vertexAttribDivisorANGLE( programAttribute, data.meshPerAttribute );
B
Ben Adams 已提交
921

M
Mr.doob 已提交
922
							if ( geometry.maxInstancedCount === undefined ) {
923

M
Mr.doob 已提交
924
								geometry.maxInstancedCount = data.meshPerAttribute * ( data.array.length / data.stride );
B
Ben Adams 已提交
925

M
Mr.doob 已提交
926
							}
B
Ben Adams 已提交
927

M
Mr.doob 已提交
928
						}
B
Ben Adams 已提交
929

B
Ben Adams 已提交
930 931
					} else {

M
Mr.doob 已提交
932 933
						_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryAttribute.buffer );
						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, 0, startIndex * size * 4 ); // 4 bytes per Float32
B
Ben Adams 已提交
934

M
Mr.doob 已提交
935
						if ( geometryAttribute instanceof THREE.InstancedBufferAttribute ) {
B
Ben Adams 已提交
936

M
Mr.doob 已提交
937
							if ( extension === null ) {
B
Ben Adams 已提交
938

939
								console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferAttribute but hardware does not support extension ANGLE_instanced_arrays.' );
M
Mr.doob 已提交
940
								return;
B
Ben Adams 已提交
941

M
Mr.doob 已提交
942
							}
B
Ben Adams 已提交
943

M
Mr.doob 已提交
944
							extension.vertexAttribDivisorANGLE( programAttribute, geometryAttribute.meshPerAttribute );
B
Ben Adams 已提交
945

M
Mr.doob 已提交
946
							if ( geometry.maxInstancedCount === undefined ) {
B
Ben Adams 已提交
947

M
Mr.doob 已提交
948
								geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * ( geometryAttribute.array.length / geometryAttribute.itemSize );
B
Ben Adams 已提交
949

M
Mr.doob 已提交
950
							}
B
Ben Adams 已提交
951

M
Mr.doob 已提交
952
						}
B
Ben Adams 已提交
953 954

					}
M
Mr.doob 已提交
955

956 957
				} else if ( materialDefaultAttributeValues !== undefined ) {

T
tschw 已提交
958
					var value = materialDefaultAttributeValues[ name ];
959
					if ( value !== undefined ) {
M
Mr.doob 已提交
960

961
						switch ( value.length ) {
M
Mr.doob 已提交
962

963 964 965
							case 2:
								_gl.vertexAttrib2fv( programAttribute, value );
								break;
M
Mr.doob 已提交
966

967 968 969
							case 3:
								_gl.vertexAttrib3fv( programAttribute, value );
								break;
M
Mr.doob 已提交
970

971 972 973
							case 4:
								_gl.vertexAttrib4fv( programAttribute, value );
								break;
974

975 976
							default:
								_gl.vertexAttrib1fv( programAttribute, value );
977 978

						}
M
Mr.doob 已提交
979 980 981 982 983 984 985 986

					}

				}

			}

		}
987

988
		state.disableUnusedAttributes();
989

M
Mr.doob 已提交
990 991
	}

M
Mr.doob 已提交
992
	this.renderBufferDirect = function ( camera, lights, fog, material, object ) {
M
Mr.doob 已提交
993

994 995
		if ( material.visible === false ) return;

M
Mr.doob 已提交
996 997
		setMaterial( material );

M
Mr.doob 已提交
998
		var geometry = objects.geometries.get( object );
M
Mr.doob 已提交
999
		var program = setProgram( camera, lights, fog, material, object );
M
Mr.doob 已提交
1000 1001 1002

		var updateBuffers = false,
			wireframeBit = material.wireframe ? 1 : 0,
M
Mr.doob 已提交
1003
			geometryProgram = geometry.id + '_' + program.id + '_' + wireframeBit;
M
Mr.doob 已提交
1004

1005
		if ( geometryProgram !== _currentGeometryProgram ) {
M
Mr.doob 已提交
1006

1007
			_currentGeometryProgram = geometryProgram;
M
Mr.doob 已提交
1008 1009 1010 1011 1012 1013
			updateBuffers = true;

		}

		if ( updateBuffers ) {

1014
			state.initAttributes();
M
Mr.doob 已提交
1015 1016 1017 1018 1019

		}

		if ( object instanceof THREE.Mesh ) {

1020
			renderMesh( material, geometry, object, program, updateBuffers );
1021

1022
		} else if ( object instanceof THREE.Line ) {
1023

1024
			renderLine( material, geometry, object, program, updateBuffers );
1025

M
Mr.doob 已提交
1026 1027 1028 1029
		} else if ( object instanceof THREE.PointCloud ) {

			renderPointCloud( material, geometry, object, program, updateBuffers );

1030
		}
1031

1032
	};
1033

M
Mr.doob 已提交
1034
	function renderMesh( material, geometry, object, program, updateBuffers ) {
1035

1036
		var mode = material.wireframe === true ? _gl.LINES : _gl.TRIANGLES;
1037

1038
		var index = geometry.attributes.index;
1039

1040
		if ( index ) {
M
Mr.doob 已提交
1041

1042
			// indexed triangles
1043

1044
			var type, size;
1045

1046
			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
1047

1048 1049
				type = _gl.UNSIGNED_INT;
				size = 4;
1050

1051
			} else {
B
Ben Adams 已提交
1052

1053 1054
				type = _gl.UNSIGNED_SHORT;
				size = 2;
B
Ben Adams 已提交
1055

1056
			}
1057

1058
			var offsets = geometry.offsets;
B
Ben Adams 已提交
1059

1060
			if ( offsets.length === 0 ) {
1061

1062
				if ( updateBuffers ) {
B
Ben Adams 已提交
1063

1064 1065 1066 1067 1068 1069
					setupVertexAttributes( material, program, geometry, 0 );
					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );

				}

				if ( geometry instanceof THREE.InstancedBufferGeometry && geometry.maxInstancedCount > 0 ) {
B
Ben Adams 已提交
1070

1071 1072 1073 1074
					var extension = extensions.get( 'ANGLE_instanced_arrays' );

					if ( extension === null ) {

1075
						console.error( 'THREE.WebGLRenderer.renderMesh: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
1076
						return;
B
Ben Adams 已提交
1077 1078

					}
1079

1080
					extension.drawElementsInstancedANGLE( mode, index.array.length, type, 0, geometry.maxInstancedCount ); // Draw the instanced meshes
1081

1082
				} else {
M
Mr.doob 已提交
1083

1084
					_gl.drawElements( mode, index.array.length, type, 0 );
M
Mr.doob 已提交
1085

1086 1087 1088 1089
				}
				_this.info.render.calls ++;
				_this.info.render.vertices += index.array.length; // not really true, here vertices can be shared
				_this.info.render.faces += index.array.length / 3;
M
Mr.doob 已提交
1090

1091
			} else {
M
Mr.doob 已提交
1092

1093 1094 1095
				// if there is more than 1 chunk
				// must set attribute pointers to use new offsets for each chunk
				// even if geometry and materials didn't change
M
Mr.doob 已提交
1096

1097
				updateBuffers = true;
1098

1099
				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
M
Mr.doob 已提交
1100

1101
					var startIndex = offsets[ i ].index;
M
Mr.doob 已提交
1102

1103
					if ( updateBuffers ) {
M
Mr.doob 已提交
1104

1105 1106
						setupVertexAttributes( material, program, geometry, startIndex );
						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
B
Ben Adams 已提交
1107

1108
					}
B
Ben Adams 已提交
1109

1110
					// render indexed triangles
B
Ben Adams 已提交
1111

1112
					if ( geometry instanceof THREE.InstancedBufferGeometry && offsets[i].instances > 0 ) {
B
Ben Adams 已提交
1113

1114
						var extension = extensions.get( 'ANGLE_instanced_arrays' );
B
Ben Adams 已提交
1115

1116
						if ( extension === null ) {
B
Ben Adams 已提交
1117

1118
							console.error( 'THREE.WebGLRenderer.renderMesh: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
1119
							return;
M
Mr.doob 已提交
1120

B
Ben Adams 已提交
1121
						}
M
Mr.doob 已提交
1122

1123 1124 1125 1126 1127
						extension.drawElementsInstancedANGLE( mode, offsets[i].count, type, offsets[i].start * size, offsets[i].count, type, offsets[i].instances ); // Draw the instanced meshes

					} else {

						_gl.drawElements( mode, offsets[ i ].count, type, offsets[ i ].start * size );
M
Mr.doob 已提交
1128

1129
					}
M
Mr.doob 已提交
1130

1131 1132 1133 1134
					_this.info.render.calls ++;
					_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
					_this.info.render.faces += offsets[ i ].count / 3;

M
Mr.doob 已提交
1135 1136
				}

1137
			}
M
Mr.doob 已提交
1138

1139
		} else {
1140

1141
			// non-indexed triangles
1142

1143 1144 1145
			var offsets = geometry.offsets;

			if ( offsets.length === 0 ) {
M
Mr.doob 已提交
1146

1147
				if ( updateBuffers ) {
M
Mr.doob 已提交
1148

1149
					setupVertexAttributes( material, program, geometry, 0 );
M
Mr.doob 已提交
1150

1151
				}
1152

M
Mr.doob 已提交
1153
				var position = geometry.attributes.position;
M
Mr.doob 已提交
1154

1155
				// render non-indexed triangles
B
Ben Adams 已提交
1156

1157
				if ( geometry instanceof THREE.InstancedBufferGeometry && geometry.maxInstancedCount > 0 ) {
B
Ben Adams 已提交
1158

1159
					var extension = extensions.get( 'ANGLE_instanced_arrays' );
B
Ben Adams 已提交
1160

1161
					if ( extension === null ) {
M
Mr.doob 已提交
1162

1163
						console.error( 'THREE.WebGLRenderer.renderMesh: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
1164
						return;
M
Mr.doob 已提交
1165

1166 1167 1168 1169 1170
					}

					if ( position instanceof THREE.InterleavedBufferAttribute ) {

						extension.drawArraysInstancedANGLE( mode, 0, position.data.array.length / position.data.stride, geometry.maxInstancedCount ); // Draw the instanced meshes
B
Ben Adams 已提交
1171

1172 1173 1174
					} else {

						extension.drawArraysInstancedANGLE( mode, 0, position.array.length / position.itemSize, geometry.maxInstancedCount ); // Draw the instanced meshes
B
Ben Adams 已提交
1175

1176
					}
B
Ben Adams 已提交
1177

1178
				} else {
B
Ben Adams 已提交
1179

1180 1181 1182 1183 1184 1185 1186 1187 1188
					if ( position instanceof THREE.InterleavedBufferAttribute ) {

						_gl.drawArrays( mode, 0, position.data.array.length / position.data.stride );

					} else {

						_gl.drawArrays( mode, 0, position.array.length / position.itemSize );

					}
B
Ben Adams 已提交
1189

1190
				}
B
Ben Adams 已提交
1191

1192 1193 1194 1195
				_this.info.render.calls++;
				_this.info.render.vertices += position.array.length / position.itemSize;
				_this.info.render.faces += position.array.length / ( 3 * position.itemSize );

1196
			} else {
B
Ben Adams 已提交
1197

1198 1199 1200
				// if there is more than 1 chunk
				// must set attribute pointers to use new offsets for each chunk
				// even if geometry and materials didn't change
B
Ben Adams 已提交
1201

B
Ben Adams 已提交
1202
				if ( updateBuffers ) {
M
Mr.doob 已提交
1203

B
Ben Adams 已提交
1204
					setupVertexAttributes( material, program, geometry, 0 );
1205

B
Ben Adams 已提交
1206
				}
M
Mr.doob 已提交
1207

B
Ben Adams 已提交
1208
				for ( var i = 0, il = offsets.length; i < il; i++ ) {
M
Mr.doob 已提交
1209

1210 1211 1212 1213
					// render non-indexed triangles

					if ( geometry instanceof THREE.InstancedBufferGeometry ) {

1214
						console.error( 'THREE.WebGLRenderer.renderMesh: cannot use drawCalls with THREE.InstancedBufferGeometry.' );
1215 1216 1217 1218
						return;

					} else {

B
Ben Adams 已提交
1219
						_gl.drawArrays( mode, offsets[ i ].start, offsets[ i ].count );
1220 1221 1222 1223

					}

					_this.info.render.calls++;
B
Ben Adams 已提交
1224 1225
					_this.info.render.vertices += offsets[ i ].count;
					_this.info.render.faces += ( offsets[ i ].count  ) / 3;
1226 1227 1228

				}
			}
1229
		}
1230

M
Mr.doob 已提交
1231
	}
M
Mr.doob 已提交
1232

M
Mr.doob 已提交
1233
	function renderLine( material, geometry, object, program, updateBuffers ) {
M
Mr.doob 已提交
1234

1235
		var mode = object instanceof THREE.LineSegments ? _gl.LINES : _gl.LINE_STRIP;
M
Mr.doob 已提交
1236 1237 1238 1239 1240

		// In case user is not using Line*Material by mistake
		var lineWidth = material.linewidth !== undefined ? material.linewidth : 1;

		state.setLineWidth( lineWidth * pixelRatio );
1241

1242
		var index = geometry.attributes.index;
M
mschuetz 已提交
1243

1244
		if ( index ) {
M
mschuetz 已提交
1245

M
Mr.doob 已提交
1246
			// indexed lines
M
mschuetz 已提交
1247

1248
			var type, size;
M
mschuetz 已提交
1249

1250
			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
M
Mr.doob 已提交
1251

1252 1253
				type = _gl.UNSIGNED_INT;
				size = 4;
M
mschuetz 已提交
1254

1255
			} else {
M
mschuetz 已提交
1256

1257 1258
				type = _gl.UNSIGNED_SHORT;
				size = 2;
M
mschuetz 已提交
1259

1260
			}
M
mschuetz 已提交
1261

1262
			var offsets = geometry.offsets;
M
mschuetz 已提交
1263

1264
			if ( offsets.length === 0 ) {
M
mschuetz 已提交
1265

1266
				if ( updateBuffers ) {
M
mschuetz 已提交
1267

1268 1269
					setupVertexAttributes( material, program, geometry, 0 );
					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
M
mschuetz 已提交
1270

1271
				}
M
mschuetz 已提交
1272

M
Mr.doob 已提交
1273
				_gl.drawElements( mode, index.array.length, type, 0 ); // 2 bytes per Uint16Array
1274 1275

				_this.info.render.calls ++;
M
Mr.doob 已提交
1276
				_this.info.render.vertices += index.array.length; // not really true, here vertices can be shared
M
mschuetz 已提交
1277

1278
			} else {
M
mschuetz 已提交
1279

1280 1281 1282
				// if there is more than 1 chunk
				// must set attribute pointers to use new offsets for each chunk
				// even if geometry and materials didn't change
M
mschuetz 已提交
1283

1284
				if ( offsets.length > 1 ) updateBuffers = true;
M
mschuetz 已提交
1285

1286
				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
M
mschuetz 已提交
1287

1288
					var startIndex = offsets[ i ].index;
M
mschuetz 已提交
1289

1290
					if ( updateBuffers ) {
M
mschuetz 已提交
1291

1292 1293
						setupVertexAttributes( material, program, geometry, startIndex );
						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
M
mschuetz 已提交
1294

1295
					}
M
mschuetz 已提交
1296

M
Mr.doob 已提交
1297
					// render indexed lines
M
mschuetz 已提交
1298

M
Mr.doob 已提交
1299
					_gl.drawElements( mode, offsets[ i ].count, type, offsets[ i ].start * size ); // 2 bytes per Uint16Array
M
mschuetz 已提交
1300

1301
					_this.info.render.calls ++;
M
Mr.doob 已提交
1302
					_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
M
mschuetz 已提交
1303

M
mschuetz 已提交
1304
				}
M
mschuetz 已提交
1305

1306
			}
M
Mr.doob 已提交
1307

1308
		} else {
M
mschuetz 已提交
1309

M
Mr.doob 已提交
1310
			// non-indexed lines
M
mschuetz 已提交
1311

1312
			if ( updateBuffers ) {
M
mschuetz 已提交
1313

1314
				setupVertexAttributes( material, program, geometry, 0 );
M
mschuetz 已提交
1315

1316
			}
M
mschuetz 已提交
1317

1318 1319
			var position = geometry.attributes.position;
			var offsets = geometry.offsets;
M
mschuetz 已提交
1320

1321
			if ( offsets.length === 0 ) {
1322

1323
				_gl.drawArrays( mode, 0, position.array.length / 3 );
1324

1325
				_this.info.render.calls ++;
M
Mr.doob 已提交
1326
				_this.info.render.vertices += position.array.length / 3;
1327

1328
			} else {
1329

1330
				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
1331

1332
					_gl.drawArrays( mode, offsets[ i ].index, offsets[ i ].count );
1333

1334
					_this.info.render.calls ++;
M
Mr.doob 已提交
1335
					_this.info.render.vertices += offsets[ i ].count;
1336 1337

				}
M
Mr.doob 已提交
1338

M
mschuetz 已提交
1339
			}
M
Mr.doob 已提交
1340

1341
		}
M
Mr.doob 已提交
1342

M
Mr.doob 已提交
1343
	}
1344

M
Mr.doob 已提交
1345
	function renderPointCloud( material, geometry, object, program, updateBuffers ) {
M
Mr.doob 已提交
1346

M
Mr.doob 已提交
1347
		var mode = _gl.POINTS;
1348

1349
		var index = geometry.attributes.index;
M
Mr.doob 已提交
1350

1351
		if ( index ) {
M
Mr.doob 已提交
1352

M
Mr.doob 已提交
1353
			// indexed points
1354

1355
			var type, size;
1356

M
Mr.doob 已提交
1357
			if ( index.array instanceof Uint32Array && extensions.get( 'OES_element_index_uint' ) ) {
1358

1359 1360
				type = _gl.UNSIGNED_INT;
				size = 4;
1361

1362
			} else {
1363

1364 1365
				type = _gl.UNSIGNED_SHORT;
				size = 2;
M
Mr.doob 已提交
1366

1367
			}
M
Mr.doob 已提交
1368

1369
			var offsets = geometry.offsets;
M
Mr.doob 已提交
1370

1371
			if ( offsets.length === 0 ) {
M
Mr.doob 已提交
1372

1373
				if ( updateBuffers ) {
M
Mr.doob 已提交
1374

1375 1376
					setupVertexAttributes( material, program, geometry, 0 );
					_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
1377

1378
				}
1379

M
Mr.doob 已提交
1380
				_gl.drawElements( mode, index.array.length, type, 0);
1381

1382
				_this.info.render.calls ++;
M
Mr.doob 已提交
1383
				_this.info.render.points += index.array.length;
M
Mr.doob 已提交
1384

1385
			} else {
1386

1387 1388 1389
				// if there is more than 1 chunk
				// must set attribute pointers to use new offsets for each chunk
				// even if geometry and materials didn't change
1390

1391
				if ( offsets.length > 1 ) updateBuffers = true;
1392

1393
				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
M
Mr.doob 已提交
1394

1395
					var startIndex = offsets[ i ].index;
1396

1397
					if ( updateBuffers ) {
1398

1399 1400
						setupVertexAttributes( material, program, geometry, startIndex );
						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
1401

1402
					}
1403

M
Mr.doob 已提交
1404
					// render indexed points
1405

M
Mr.doob 已提交
1406
					_gl.drawElements( mode, offsets[ i ].count, type, offsets[ i ].start * size );
1407

1408
					_this.info.render.calls ++;
M
Mr.doob 已提交
1409
					_this.info.render.points += offsets[ i ].count;
1410 1411 1412

				}

1413
			}
1414

1415
		} else {
M
Mr.doob 已提交
1416

M
Mr.doob 已提交
1417
			// non-indexed points
1418

1419
			if ( updateBuffers ) {
1420

1421
				setupVertexAttributes( material, program, geometry, 0 );
1422

1423
			}
1424

1425 1426
			var position = geometry.attributes.position;
			var offsets = geometry.offsets;
1427

1428
			if ( offsets.length === 0 ) {
1429

1430
				_gl.drawArrays( mode, 0, position.array.length / 3 );
1431

1432
				_this.info.render.calls ++;
M
Mr.doob 已提交
1433
				_this.info.render.points += position.array.length / 3;
1434

1435
			} else {
1436

1437
				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
1438

1439
					_gl.drawArrays( mode, offsets[ i ].index, offsets[ i ].count );
1440

1441
					_this.info.render.calls ++;
M
Mr.doob 已提交
1442
					_this.info.render.points += offsets[ i ].count;
1443 1444

				}
M
Mr.doob 已提交
1445

1446
			}
M
Mr.doob 已提交
1447

1448
		}
M
Mr.doob 已提交
1449

M
Mr.doob 已提交
1450
	}
M
Mr.doob 已提交
1451 1452 1453 1454 1455

	// Sorting

	function painterSortStable ( a, b ) {

U
unconed 已提交
1456
		if ( a.object.renderOrder !== b.object.renderOrder ) {
1457

U
unconed 已提交
1458
			return a.object.renderOrder - b.object.renderOrder;
1459

1460
		} else if ( a.object.material.id !== b.object.material.id ) {
M
Mr.doob 已提交
1461

1462
			return a.object.material.id - b.object.material.id;
1463 1464

		} else if ( a.z !== b.z ) {
M
Mr.doob 已提交
1465

M
Mr.doob 已提交
1466
			return a.z - b.z;
M
Mr.doob 已提交
1467 1468 1469

		} else {

1470
			return a.id - b.id;
M
Mr.doob 已提交
1471 1472 1473

		}

1474
	}
M
Mr.doob 已提交
1475

1476 1477
	function reversePainterSortStable ( a, b ) {

U
unconed 已提交
1478
		if ( a.object.renderOrder !== b.object.renderOrder ) {
1479

U
unconed 已提交
1480
			return a.object.renderOrder - b.object.renderOrder;
1481 1482

		} if ( a.z !== b.z ) {
1483

M
Mr.doob 已提交
1484
			return b.z - a.z;
1485 1486 1487 1488 1489 1490 1491

		} else {

			return a.id - b.id;

		}

1492
	}
1493

M
Mr.doob 已提交
1494 1495 1496 1497 1498 1499
	// Rendering

	this.render = function ( scene, camera, renderTarget, forceClear ) {

		if ( camera instanceof THREE.Camera === false ) {

1500
			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
M
Mr.doob 已提交
1501 1502 1503 1504
			return;

		}

M
Mr.doob 已提交
1505
		var fog = scene.fog;
M
Mr.doob 已提交
1506 1507 1508

		// reset caching for this frame

1509
		_currentGeometryProgram = '';
1510
		_currentMaterialId = - 1;
1511
		_currentCamera = null;
M
Mr.doob 已提交
1512 1513 1514 1515
		_lightsNeedUpdate = true;

		// update scene graph

1516
		if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
M
Mr.doob 已提交
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526

		// update camera matrices and frustum

		if ( camera.parent === undefined ) camera.updateMatrixWorld();

		camera.matrixWorldInverse.getInverse( camera.matrixWorld );

		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
		_frustum.setFromMatrix( _projScreenMatrix );

M
Mr.doob 已提交
1527
		lights.length = 0;
1528 1529
		opaqueObjects.length = 0;
		transparentObjects.length = 0;
M
Mr.doob 已提交
1530

M
Mr.doob 已提交
1531 1532 1533
		sprites.length = 0;
		lensFlares.length = 0;

1534
		projectObject( scene );
M
Mr.doob 已提交
1535

M
Mr.doob 已提交
1536
		if ( _this.sortObjects === true ) {
1537 1538 1539

			opaqueObjects.sort( painterSortStable );
			transparentObjects.sort( reversePainterSortStable );
M
Mr.doob 已提交
1540

1541 1542
		}

B
Ben Adams 已提交
1543 1544
		objects.update( opaqueObjects );
		objects.update( transparentObjects );
M
Mr.doob 已提交
1545

M
Mr.doob 已提交
1546
		//
M
Mr.doob 已提交
1547

1548
		shadowMap.render( scene, camera );
M
Mr.doob 已提交
1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566

		//

		_this.info.render.calls = 0;
		_this.info.render.vertices = 0;
		_this.info.render.faces = 0;
		_this.info.render.points = 0;

		this.setRenderTarget( renderTarget );

		if ( this.autoClear || forceClear ) {

			this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );

		}

		// set matrices for immediate objects

M
Mr.doob 已提交
1567
		for ( var i = 0, il = objects.objectsImmediate.length; i < il; i ++ ) {
M
Mr.doob 已提交
1568

M
Mr.doob 已提交
1569
			var webglObject = objects.objectsImmediate[ i ];
M
Mr.doob 已提交
1570
			var object = webglObject.object;
M
Mr.doob 已提交
1571

1572
			if ( object.visible === true ) {
M
Mr.doob 已提交
1573 1574 1575

				setupMatrices( object, camera );

1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588
				var material = object.material;

				if ( material.transparent ) {

					webglObject.transparent = material;
					webglObject.opaque = null;

				} else {

					webglObject.opaque = material;
					webglObject.transparent = null;

				}
M
Mr.doob 已提交
1589 1590 1591 1592 1593 1594 1595

			}

		}

		if ( scene.overrideMaterial ) {

1596
			var overrideMaterial = scene.overrideMaterial;
M
Mr.doob 已提交
1597

1598 1599
			renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial );
			renderObjects( transparentObjects, camera, lights, fog, overrideMaterial );
M
Mr.doob 已提交
1600
			renderObjectsImmediate( objects.objectsImmediate, '', camera, lights, fog, overrideMaterial );
M
Mr.doob 已提交
1601 1602 1603 1604 1605

		} else {

			// opaque pass (front-to-back order)

M
Mr.doob 已提交
1606
			state.setBlending( THREE.NoBlending );
M
Mr.doob 已提交
1607

1608
			renderObjects( opaqueObjects, camera, lights, fog, null );
M
Mr.doob 已提交
1609
			renderObjectsImmediate( objects.objectsImmediate, 'opaque', camera, lights, fog, null );
M
Mr.doob 已提交
1610 1611 1612

			// transparent pass (back-to-front order)

1613
			renderObjects( transparentObjects, camera, lights, fog, null );
M
Mr.doob 已提交
1614
			renderObjectsImmediate( objects.objectsImmediate, 'transparent', camera, lights, fog, null );
M
Mr.doob 已提交
1615 1616 1617 1618 1619

		}

		// custom render plugins (post pass)

M
Mr.doob 已提交
1620 1621
		spritePlugin.render( scene, camera );
		lensFlarePlugin.render( scene, camera, _currentWidth, _currentHeight );
M
Mr.doob 已提交
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632

		// Generate mipmap if we're using any kind of mipmap filtering

		if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {

			updateRenderTargetMipmap( renderTarget );

		}

		// Ensure depth buffer writing is enabled so it can be cleared on next render

M
Mr.doob 已提交
1633 1634
		state.setDepthTest( true );
		state.setDepthWrite( true );
1635
		state.setColorWrite( true );
M
Mr.doob 已提交
1636 1637 1638 1639

		// _gl.finish();

	};
M
Mr.doob 已提交
1640

1641
	function projectObject( object ) {
M
Mr.doob 已提交
1642

1643
		if ( object.visible === true ) {
M
Mr.doob 已提交
1644

1645
			if ( object instanceof THREE.Scene || object instanceof THREE.Group ) {
M
Mr.doob 已提交
1646

1647
				// skip
M
Mr.doob 已提交
1648

1649
			} else {
M
Mr.doob 已提交
1650

1651 1652
				// update Skeleton objects
				if ( object instanceof THREE.SkinnedMesh ) {
B
Ben Adams 已提交
1653

1654
					object.skeleton.update();
B
Ben Adams 已提交
1655

1656
				}
B
Ben Adams 已提交
1657

1658
				objects.init( object );
M
Mr.doob 已提交
1659

1660
				if ( object instanceof THREE.Light ) {
M
Mr.doob 已提交
1661

1662
					lights.push( object );
M
Mr.doob 已提交
1663

1664
				} else if ( object instanceof THREE.Sprite ) {
M
Mr.doob 已提交
1665

1666
					sprites.push( object );
M
Mr.doob 已提交
1667

1668
				} else if ( object instanceof THREE.LensFlare ) {
M
Mr.doob 已提交
1669

1670
					lensFlares.push( object );
M
Mr.doob 已提交
1671

1672
				} else {
M
Mr.doob 已提交
1673

1674
					var webglObject = objects.objects[ object.id ];
M
Mr.doob 已提交
1675

1676
					if ( webglObject && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {
M
Mr.doob 已提交
1677

1678
						var material = object.material;
1679

1680
						if ( material.transparent ) {
1681

1682
							transparentObjects.push( webglObject );
1683

1684
						} else {
1685

1686
							opaqueObjects.push( webglObject );
M
Mr.doob 已提交
1687

1688 1689 1690
						}

						if ( _this.sortObjects === true ) {
M
Mr.doob 已提交
1691

1692 1693
							_vector3.setFromMatrixPosition( object.matrixWorld );
							_vector3.applyProjection( _projScreenMatrix );
M
Mr.doob 已提交
1694

1695
							webglObject.z = _vector3.z;
M
Mr.doob 已提交
1696

1697
						}
O
OpenShift guest 已提交
1698

1699
					}
M
Mr.doob 已提交
1700

1701
				}
M
Mr.doob 已提交
1702

1703
			}
M
Mr.doob 已提交
1704

1705
			for ( var i = 0, l = object.children.length; i < l; i ++ ) {
M
Mr.doob 已提交
1706

1707
				projectObject( object.children[ i ] );
M
Mr.doob 已提交
1708

1709
			}
M
Mr.doob 已提交
1710

1711
		}
1712

1713
	}
M
Mr.doob 已提交
1714

1715
	function renderObjects( renderList, camera, lights, fog, overrideMaterial ) {
M
Mr.doob 已提交
1716

M
Mr.doob 已提交
1717
		var material = overrideMaterial;
M
Mr.doob 已提交
1718

M
Mr.doob 已提交
1719
		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
M
Mr.doob 已提交
1720

M
Mr.doob 已提交
1721
			var webglObject = renderList[ i ];
M
Mr.doob 已提交
1722

M
Mr.doob 已提交
1723
			var object = webglObject.object;
M
Mr.doob 已提交
1724

1725
			setupMatrices( object, camera );
M
Mr.doob 已提交
1726

M
Mr.doob 已提交
1727
			if ( overrideMaterial === null ) material = object.material;
M
Mr.doob 已提交
1728

M
Mr.doob 已提交
1729
			if ( material instanceof THREE.MeshFaceMaterial ) {
M
Mr.doob 已提交
1730

M
Mr.doob 已提交
1731
				var materials = material.materials;
M
Mr.doob 已提交
1732

M
Mr.doob 已提交
1733
				for ( var j = 0, jl = materials.length; j < jl; j ++ ) {
M
Mr.doob 已提交
1734

M
Mr.doob 已提交
1735
					_this.renderBufferDirect( camera, lights, fog, materials[ j ], object );
M
Mr.doob 已提交
1736

M
Mr.doob 已提交
1737 1738 1739
				}

				continue;
M
Mr.doob 已提交
1740

1741
			}
M
Mr.doob 已提交
1742

M
Mr.doob 已提交
1743
			_this.renderBufferDirect( camera, lights, fog, material, object );
M
Mr.doob 已提交
1744 1745 1746

		}

1747
	}
M
Mr.doob 已提交
1748

1749
	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, overrideMaterial ) {
M
Mr.doob 已提交
1750

M
Mr.doob 已提交
1751
		var material = overrideMaterial;
M
Mr.doob 已提交
1752

M
Mr.doob 已提交
1753
		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
M
Mr.doob 已提交
1754

M
Mr.doob 已提交
1755 1756
			var webglObject = renderList[ i ];
			var object = webglObject.object;
M
Mr.doob 已提交
1757

1758
			if ( object.visible === true ) {
M
Mr.doob 已提交
1759

M
Mr.doob 已提交
1760
				if ( overrideMaterial === null ) material = webglObject[ materialType ];
M
Mr.doob 已提交
1761 1762 1763 1764 1765 1766 1767

				_this.renderImmediateObject( camera, lights, fog, material, object );

			}

		}

1768
	}
M
Mr.doob 已提交
1769 1770 1771

	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {

M
Mr.doob 已提交
1772 1773
		setMaterial( material );

M
Mr.doob 已提交
1774 1775
		var program = setProgram( camera, lights, fog, material, object );

1776
		_currentGeometryProgram = '';
M
Mr.doob 已提交
1777 1778 1779 1780 1781 1782 1783

		if ( object.immediateRenderCallback ) {

			object.immediateRenderCallback( program, _gl, _frustum );

		} else {

1784
			object.render( function ( object ) { _this.renderBufferImmediate( object, program, material ); } );
M
Mr.doob 已提交
1785 1786 1787 1788 1789 1790 1791

		}

	};

	// Materials

1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802
	var shaderIDs = {
		MeshDepthMaterial: 'depth',
		MeshNormalMaterial: 'normal',
		MeshBasicMaterial: 'basic',
		MeshLambertMaterial: 'lambert',
		MeshPhongMaterial: 'phong',
		LineBasicMaterial: 'basic',
		LineDashedMaterial: 'dashed',
		PointCloudMaterial: 'particle_basic'
	};

1803
	function initMaterial( material, lights, fog, object ) {
M
Mr.doob 已提交
1804

1805
		var shaderID = shaderIDs[ material.type ];
M
Mr.doob 已提交
1806 1807 1808 1809

		// heuristics to create shader parameters according to lights in the scene
		// (not to blow over maxLights budget)

1810 1811 1812
		var maxLightCount = allocateLights( lights );
		var maxShadows = allocateShadows( lights );
		var maxBones = allocateBones( object );
M
Mr.doob 已提交
1813

1814
		var parameters = {
M
Mr.doob 已提交
1815

1816 1817 1818
			precision: _precision,
			supportsVertexTextures: _supportsVertexTextures,

1819 1820
			map: !! material.map,
			envMap: !! material.envMap,
M
Mr.doob 已提交
1821
			envMapMode: material.envMap && material.envMap.mapping,
1822
			lightMap: !! material.lightMap,
1823
			aoMap: !! material.aoMap,
1824
			emissiveMap: !! material.emissiveMap,
1825 1826 1827
			bumpMap: !! material.bumpMap,
			normalMap: !! material.normalMap,
			specularMap: !! material.specularMap,
1828
			alphaMap: !! material.alphaMap,
M
Mr.doob 已提交
1829

1830 1831
			combine: material.combine,

M
Mr.doob 已提交
1832 1833 1834 1835 1836 1837
			vertexColors: material.vertexColors,

			fog: fog,
			useFog: material.fog,
			fogExp: fog instanceof THREE.FogExp2,

1838 1839
			flatShading: material.shading === THREE.FlatShading,

M
Mr.doob 已提交
1840
			sizeAttenuation: material.sizeAttenuation,
1841
			logarithmicDepthBuffer: _logarithmicDepthBuffer,
M
Mr.doob 已提交
1842 1843 1844

			skinning: material.skinning,
			maxBones: maxBones,
1845
			useVertexTexture: _supportsBoneTextures && object && object.skeleton && object.skeleton.useVertexTexture,
M
Mr.doob 已提交
1846 1847 1848

			morphTargets: material.morphTargets,
			morphNormals: material.morphNormals,
1849 1850
			maxMorphTargets: _this.maxMorphTargets,
			maxMorphNormals: _this.maxMorphNormals,
M
Mr.doob 已提交
1851 1852 1853 1854 1855 1856 1857

			maxDirLights: maxLightCount.directional,
			maxPointLights: maxLightCount.point,
			maxSpotLights: maxLightCount.spot,
			maxHemiLights: maxLightCount.hemi,

			maxShadows: maxShadows,
1858 1859 1860 1861
			shadowMapEnabled: shadowMap.enabled && object.receiveShadow && maxShadows > 0,
			shadowMapType: shadowMap.type,
			shadowMapDebug: shadowMap.debug,
			shadowMapCascade: shadowMap.cascade,
M
Mr.doob 已提交
1862 1863 1864 1865 1866 1867 1868 1869

			alphaTest: material.alphaTest,
			metal: material.metal,
			doubleSided: material.side === THREE.DoubleSide,
			flipSided: material.side === THREE.BackSide

		};

1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884
		// Generate code

		var chunks = [];

		if ( shaderID ) {

			chunks.push( shaderID );

		} else {

			chunks.push( material.fragmentShader );
			chunks.push( material.vertexShader );

		}

1885 1886
		if ( material.defines !== undefined ) {

1887
			for ( var name in material.defines ) {
1888

1889 1890
				chunks.push( name );
				chunks.push( material.defines[ name ] );
1891 1892

			}
1893 1894 1895

		}

1896
		for ( var name in parameters ) {
1897

1898 1899
			chunks.push( name );
			chunks.push( parameters[ name ] );
1900 1901 1902 1903 1904

		}

		var code = chunks.join();

B
Ben Adams 已提交
1905 1906
		if ( !material.program ) {

M
Mr.doob 已提交
1907 1908
			// new material
			material.addEventListener( 'dispose', onMaterialDispose );
B
Ben Adams 已提交
1909 1910 1911

		} else if ( material.program.code !== code ) {

M
Mr.doob 已提交
1912 1913
			// changed glsl or parameters
			deallocateMaterial( material );
B
Ben Adams 已提交
1914

T
tschw 已提交
1915
		} else if ( shaderID !== undefined ) {
B
Ben Adams 已提交
1916

T
tschw 已提交
1917 1918 1919 1920
			// same glsl
			return;

		} else if ( material.__webglShader.uniforms === material.uniforms ) {
B
Ben Adams 已提交
1921

T
tschw 已提交
1922
			// same uniforms (container object)
M
Mr.doob 已提交
1923
			return;
B
Ben Adams 已提交
1924 1925 1926 1927 1928 1929 1930 1931

		}

		if ( shaderID ) {

			var shader = THREE.ShaderLib[ shaderID ];

			material.__webglShader = {
1932
				name: material.type,
B
Ben Adams 已提交
1933 1934 1935 1936 1937 1938 1939 1940
				uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
				vertexShader: shader.vertexShader,
				fragmentShader: shader.fragmentShader
			}

		} else {

			material.__webglShader = {
1941
				name: material.type,
B
Ben Adams 已提交
1942 1943 1944 1945 1946 1947 1948
				uniforms: material.uniforms,
				vertexShader: material.vertexShader,
				fragmentShader: material.fragmentShader
			}

		}

1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
		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 ) {

1970
			program = new THREE.WebGLProgram( _this, code, material, parameters );
1971 1972 1973 1974 1975 1976 1977
			_programs.push( program );

			_this.info.memory.programs = _programs.length;

		}

		material.program = program;
M
Mr.doob 已提交
1978

1979
		var attributes = program.getAttributes();
M
Mr.doob 已提交
1980 1981 1982 1983 1984

		if ( material.morphTargets ) {

			material.numSupportedMorphTargets = 0;

1985
			for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
M
Mr.doob 已提交
1986

M
Mr.doob 已提交
1987
				if ( attributes[ 'morphTarget' + i ] >= 0 ) {
M
Mr.doob 已提交
1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000

					material.numSupportedMorphTargets ++;

				}

			}

		}

		if ( material.morphNormals ) {

			material.numSupportedMorphNormals = 0;

2001
			for ( i = 0; i < _this.maxMorphNormals; i ++ ) {
M
Mr.doob 已提交
2002

M
Mr.doob 已提交
2003
				if ( attributes[ 'morphNormal' + i ] >= 0 ) {
M
Mr.doob 已提交
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014

					material.numSupportedMorphNormals ++;

				}

			}

		}

		material.uniformsList = [];

2015
		var uniformLocations = material.program.getUniforms();
2016
		for ( var u in material.__webglShader.uniforms ) {
M
Mr.doob 已提交
2017

2018
			var location = uniformLocations[ u ];
2019 2020 2021 2022

			if ( location ) {
				material.uniformsList.push( [ material.__webglShader.uniforms[ u ], location ] );
			}
M
Mr.doob 已提交
2023 2024 2025

		}

M
Mr.doob 已提交
2026
	}
M
Mr.doob 已提交
2027

2028 2029
	function setMaterial( material ) {

M
Mr.doob 已提交
2030 2031
		setMaterialFaces( material );

2032 2033
		if ( material.transparent === true ) {

M
Mr.doob 已提交
2034
			state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha );
2035

2036 2037 2038 2039
		} else {

			state.setBlending( THREE.NoBlending );

2040 2041
		}

B
Ben Adams 已提交
2042
		state.setDepthFunc( material.depthFunc );
M
Mr.doob 已提交
2043 2044
		state.setDepthTest( material.depthTest );
		state.setDepthWrite( material.depthWrite );
2045
		state.setColorWrite( material.colorWrite );
M
Mr.doob 已提交
2046
		state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
2047 2048 2049

	}

M
Mr.doob 已提交
2050 2051 2052 2053 2054 2055 2056
	function setMaterialFaces( material ) {

		state.setDoubleSided( material.side === THREE.DoubleSide );
		state.setFlipSided( material.side === THREE.BackSide );

	}

M
Mr.doob 已提交
2057 2058 2059 2060 2061 2062
	function setProgram( camera, lights, fog, material, object ) {

		_usedTextureUnits = 0;

		if ( material.needsUpdate ) {

2063
			initMaterial( material, lights, fog, object );
M
Mr.doob 已提交
2064 2065 2066 2067
			material.needsUpdate = false;

		}

2068
		var refreshProgram = false;
M
Mr.doob 已提交
2069
		var refreshMaterial = false;
2070
		var refreshLights = false;
M
Mr.doob 已提交
2071 2072

		var program = material.program,
2073
			p_uniforms = program.getUniforms(),
2074
			m_uniforms = material.__webglShader.uniforms;
M
Mr.doob 已提交
2075

2076
		if ( program.id !== _currentProgram ) {
M
Mr.doob 已提交
2077

2078 2079
			_gl.useProgram( program.program );
			_currentProgram = program.id;
M
Mr.doob 已提交
2080

2081
			refreshProgram = true;
M
Mr.doob 已提交
2082
			refreshMaterial = true;
2083
			refreshLights = true;
M
Mr.doob 已提交
2084 2085 2086 2087 2088

		}

		if ( material.id !== _currentMaterialId ) {

2089
			if ( _currentMaterialId === -1 ) refreshLights = true;
M
Mr.doob 已提交
2090
			_currentMaterialId = material.id;
2091

M
Mr.doob 已提交
2092 2093 2094 2095
			refreshMaterial = true;

		}

2096
		if ( refreshProgram || camera !== _currentCamera ) {
M
Mr.doob 已提交
2097 2098 2099

			_gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera.projectionMatrix.elements );

2100 2101
			if ( _logarithmicDepthBuffer ) {

2102
				_gl.uniform1f( p_uniforms.logDepthBufFC, 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
2103 2104 2105 2106

			}


M
Mr.doob 已提交
2107 2108
			if ( camera !== _currentCamera ) _currentCamera = camera;

2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126
			// load material specific uniforms
			// (shader material also gets them for the sake of genericity)

			if ( material instanceof THREE.ShaderMaterial ||
				 material instanceof THREE.MeshPhongMaterial ||
				 material.envMap ) {

				if ( p_uniforms.cameraPosition !== null ) {

					_vector3.setFromMatrixPosition( camera.matrixWorld );
					_gl.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );

				}

			}

			if ( material instanceof THREE.MeshPhongMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
2127
				 material instanceof THREE.MeshBasicMaterial ||
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138
				 material instanceof THREE.ShaderMaterial ||
				 material.skinning ) {

				if ( p_uniforms.viewMatrix !== null ) {

					_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera.matrixWorldInverse.elements );

				}

			}

M
Mr.doob 已提交
2139 2140 2141 2142 2143 2144 2145 2146
		}

		// skinning uniforms must be set even if material didn't change
		// auto-setting of texture unit for bone texture must go before other textures
		// not sure why, but otherwise weird things happen

		if ( material.skinning ) {

2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159
			if ( object.bindMatrix && p_uniforms.bindMatrix !== null ) {

				_gl.uniformMatrix4fv( p_uniforms.bindMatrix, false, object.bindMatrix.elements );

			}

			if ( object.bindMatrixInverse && p_uniforms.bindMatrixInverse !== null ) {

				_gl.uniformMatrix4fv( p_uniforms.bindMatrixInverse, false, object.bindMatrixInverse.elements );

			}

			if ( _supportsBoneTextures && object.skeleton && object.skeleton.useVertexTexture ) {
M
Mr.doob 已提交
2160 2161 2162 2163 2164 2165

				if ( p_uniforms.boneTexture !== null ) {

					var textureUnit = getTextureUnit();

					_gl.uniform1i( p_uniforms.boneTexture, textureUnit );
2166
					_this.setTexture( object.skeleton.boneTexture, textureUnit );
M
Mr.doob 已提交
2167 2168 2169

				}

2170 2171
				if ( p_uniforms.boneTextureWidth !== null ) {

2172
					_gl.uniform1i( p_uniforms.boneTextureWidth, object.skeleton.boneTextureWidth );
2173 2174 2175 2176 2177

				}

				if ( p_uniforms.boneTextureHeight !== null ) {

2178
					_gl.uniform1i( p_uniforms.boneTextureHeight, object.skeleton.boneTextureHeight );
2179 2180 2181

				}

2182
			} else if ( object.skeleton && object.skeleton.boneMatrices ) {
M
Mr.doob 已提交
2183 2184 2185

				if ( p_uniforms.boneGlobalMatrices !== null ) {

2186
					_gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.skeleton.boneMatrices );
M
Mr.doob 已提交
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209

				}

			}

		}

		if ( refreshMaterial ) {

			// refresh uniforms common to several materials

			if ( fog && material.fog ) {

				refreshUniformsFog( m_uniforms, fog );

			}

			if ( material instanceof THREE.MeshPhongMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
				 material.lights ) {

				if ( _lightsNeedUpdate ) {

2210
					refreshLights = true;
2211
					setupLights( lights );
M
Mr.doob 已提交
2212 2213 2214
					_lightsNeedUpdate = false;
				}

2215 2216
				if ( refreshLights ) {
					refreshUniformsLights( m_uniforms, _lights );
2217
					markUniformsLightsNeedsUpdate( m_uniforms, true );
2218
				} else {
2219
					markUniformsLightsNeedsUpdate( m_uniforms, false );
2220
				}
M
Mr.doob 已提交
2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242

			}

			if ( material instanceof THREE.MeshBasicMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
				 material instanceof THREE.MeshPhongMaterial ) {

				refreshUniformsCommon( m_uniforms, material );

			}

			// refresh single material specific uniforms

			if ( material instanceof THREE.LineBasicMaterial ) {

				refreshUniformsLine( m_uniforms, material );

			} else if ( material instanceof THREE.LineDashedMaterial ) {

				refreshUniformsLine( m_uniforms, material );
				refreshUniformsDash( m_uniforms, material );

2243
			} else if ( material instanceof THREE.PointCloudMaterial ) {
M
Mr.doob 已提交
2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254

				refreshUniformsParticle( m_uniforms, material );

			} else if ( material instanceof THREE.MeshPhongMaterial ) {

				refreshUniformsPhong( m_uniforms, material );

			} else if ( material instanceof THREE.MeshLambertMaterial ) {

				refreshUniformsLambert( m_uniforms, material );

2255 2256 2257 2258
			} else if ( material instanceof THREE.MeshBasicMaterial ) {

				refreshUniformsBasic( m_uniforms, material );

M
Mr.doob 已提交
2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
			} else if ( material instanceof THREE.MeshDepthMaterial ) {

				m_uniforms.mNear.value = camera.near;
				m_uniforms.mFar.value = camera.far;
				m_uniforms.opacity.value = material.opacity;

			} else if ( material instanceof THREE.MeshNormalMaterial ) {

				m_uniforms.opacity.value = material.opacity;

			}

			if ( object.receiveShadow && ! material._shadowPass ) {

				refreshUniformsShadow( m_uniforms, lights );

			}

			// load common uniforms

2279
			loadUniformsGeneric( material.uniformsList );
M
Mr.doob 已提交
2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292

		}

		loadUniformsMatrices( p_uniforms, object );

		if ( p_uniforms.modelMatrix !== null ) {

			_gl.uniformMatrix4fv( p_uniforms.modelMatrix, false, object.matrixWorld.elements );

		}

		return program;

M
Mr.doob 已提交
2293
	}
M
Mr.doob 已提交
2294 2295 2296 2297 2298 2299 2300

	// Uniforms (refresh uniforms objects)

	function refreshUniformsCommon ( uniforms, material ) {

		uniforms.opacity.value = material.opacity;

2301
		uniforms.diffuse.value = material.color;
M
Mr.doob 已提交
2302 2303 2304

		uniforms.map.value = material.map;
		uniforms.specularMap.value = material.specularMap;
2305
		uniforms.alphaMap.value = material.alphaMap;
M
Mr.doob 已提交
2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321

		if ( material.bumpMap ) {

			uniforms.bumpMap.value = material.bumpMap;
			uniforms.bumpScale.value = material.bumpScale;

		}

		if ( material.normalMap ) {

			uniforms.normalMap.value = material.normalMap;
			uniforms.normalScale.value.copy( material.normalScale );

		}

		// uv repeat and offset setting priorities
M
Mr.doob 已提交
2322 2323 2324 2325 2326
		// 1. color map
		// 2. specular map
		// 3. normal map
		// 4. bump map
		// 5. alpha map
2327
		// 6. emissive map
M
Mr.doob 已提交
2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346

		var uvScaleMap;

		if ( material.map ) {

			uvScaleMap = material.map;

		} else if ( material.specularMap ) {

			uvScaleMap = material.specularMap;

		} else if ( material.normalMap ) {

			uvScaleMap = material.normalMap;

		} else if ( material.bumpMap ) {

			uvScaleMap = material.bumpMap;

2347 2348 2349 2350
		} else if ( material.alphaMap ) {

			uvScaleMap = material.alphaMap;

2351 2352 2353 2354
		} else if ( material.emissiveMap ) {

			uvScaleMap = material.emissiveMap;

M
Mr.doob 已提交
2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366
		}

		if ( uvScaleMap !== undefined ) {

			var offset = uvScaleMap.offset;
			var repeat = uvScaleMap.repeat;

			uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );

		}

		uniforms.envMap.value = material.envMap;
2367
		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : - 1;
M
Mr.doob 已提交
2368

2369
		uniforms.reflectivity.value = material.reflectivity;
M
Mr.doob 已提交
2370 2371
		uniforms.refractionRatio.value = material.refractionRatio;

M
Mr.doob 已提交
2372
	}
M
Mr.doob 已提交
2373 2374 2375 2376 2377 2378

	function refreshUniformsLine ( uniforms, material ) {

		uniforms.diffuse.value = material.color;
		uniforms.opacity.value = material.opacity;

M
Mr.doob 已提交
2379
	}
M
Mr.doob 已提交
2380 2381 2382 2383 2384 2385 2386

	function refreshUniformsDash ( uniforms, material ) {

		uniforms.dashSize.value = material.dashSize;
		uniforms.totalSize.value = material.dashSize + material.gapSize;
		uniforms.scale.value = material.scale;

M
Mr.doob 已提交
2387
	}
M
Mr.doob 已提交
2388 2389 2390 2391 2392 2393 2394 2395 2396 2397

	function refreshUniformsParticle ( uniforms, material ) {

		uniforms.psColor.value = material.color;
		uniforms.opacity.value = material.opacity;
		uniforms.size.value = material.size;
		uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.

		uniforms.map.value = material.map;

2398 2399 2400 2401 2402 2403 2404 2405 2406
		if ( material.map !== null ) {

			var offset = material.map.offset;
			var repeat = material.map.repeat;

			uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );

		}

M
Mr.doob 已提交
2407
	}
M
Mr.doob 已提交
2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423

	function refreshUniformsFog ( uniforms, fog ) {

		uniforms.fogColor.value = fog.color;

		if ( fog instanceof THREE.Fog ) {

			uniforms.fogNear.value = fog.near;
			uniforms.fogFar.value = fog.far;

		} else if ( fog instanceof THREE.FogExp2 ) {

			uniforms.fogDensity.value = fog.density;

		}

M
Mr.doob 已提交
2424
	}
M
Mr.doob 已提交
2425 2426 2427 2428 2429

	function refreshUniformsPhong ( uniforms, material ) {

		uniforms.shininess.value = material.shininess;

2430 2431
		uniforms.emissive.value = material.emissive;
		uniforms.specular.value = material.specular;
M
Mr.doob 已提交
2432

2433 2434 2435 2436 2437 2438
		uniforms.lightMap.value = material.lightMap;
		uniforms.lightMapIntensity.value = material.lightMapIntensity;

		uniforms.aoMap.value = material.aoMap;
		uniforms.aoMapIntensity.value = material.aoMapIntensity;

2439 2440
		uniforms.emissiveMap.value = material.emissiveMap;

M
Mr.doob 已提交
2441
	}
M
Mr.doob 已提交
2442 2443 2444

	function refreshUniformsLambert ( uniforms, material ) {

2445
		uniforms.emissive.value = material.emissive;
M
Mr.doob 已提交
2446

M
Mr.doob 已提交
2447
	}
M
Mr.doob 已提交
2448

2449 2450 2451 2452 2453 2454 2455
	function refreshUniformsBasic ( uniforms, material ) {

		uniforms.aoMap.value = material.aoMap;
		uniforms.aoMapIntensity.value = material.aoMapIntensity;

	}

M
Mr.doob 已提交
2456 2457 2458 2459 2460 2461 2462 2463 2464 2465
	function refreshUniformsLights ( uniforms, lights ) {

		uniforms.ambientLightColor.value = lights.ambient;

		uniforms.directionalLightColor.value = lights.directional.colors;
		uniforms.directionalLightDirection.value = lights.directional.positions;

		uniforms.pointLightColor.value = lights.point.colors;
		uniforms.pointLightPosition.value = lights.point.positions;
		uniforms.pointLightDistance.value = lights.point.distances;
M
Mr.doob 已提交
2466
		uniforms.pointLightDecay.value = lights.point.decays;
M
Mr.doob 已提交
2467 2468 2469 2470 2471 2472 2473

		uniforms.spotLightColor.value = lights.spot.colors;
		uniforms.spotLightPosition.value = lights.spot.positions;
		uniforms.spotLightDistance.value = lights.spot.distances;
		uniforms.spotLightDirection.value = lights.spot.directions;
		uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
		uniforms.spotLightExponent.value = lights.spot.exponents;
M
Mr.doob 已提交
2474
		uniforms.spotLightDecay.value = lights.spot.decays;
M
Mr.doob 已提交
2475 2476 2477 2478 2479

		uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
		uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
		uniforms.hemisphereLightDirection.value = lights.hemi.positions;

M
Mr.doob 已提交
2480
	}
M
Mr.doob 已提交
2481

2482 2483
	// If uniforms are marked as clean, they don't need to be loaded to the GPU.

M
Mr.doob 已提交
2484
	function markUniformsLightsNeedsUpdate ( uniforms, value ) {
2485

M
Mr.doob 已提交
2486
		uniforms.ambientLightColor.needsUpdate = value;
2487

M
Mr.doob 已提交
2488 2489
		uniforms.directionalLightColor.needsUpdate = value;
		uniforms.directionalLightDirection.needsUpdate = value;
2490

M
Mr.doob 已提交
2491 2492 2493 2494
		uniforms.pointLightColor.needsUpdate = value;
		uniforms.pointLightPosition.needsUpdate = value;
		uniforms.pointLightDistance.needsUpdate = value;
		uniforms.pointLightDecay.needsUpdate = value;
2495

M
Mr.doob 已提交
2496 2497 2498 2499 2500 2501 2502
		uniforms.spotLightColor.needsUpdate = value;
		uniforms.spotLightPosition.needsUpdate = value;
		uniforms.spotLightDistance.needsUpdate = value;
		uniforms.spotLightDirection.needsUpdate = value;
		uniforms.spotLightAngleCos.needsUpdate = value;
		uniforms.spotLightExponent.needsUpdate = value;
		uniforms.spotLightDecay.needsUpdate = value;
2503

M
Mr.doob 已提交
2504 2505 2506
		uniforms.hemisphereLightSkyColor.needsUpdate = value;
		uniforms.hemisphereLightGroundColor.needsUpdate = value;
		uniforms.hemisphereLightDirection.needsUpdate = value;
2507

M
Mr.doob 已提交
2508
	}
2509

M
Mr.doob 已提交
2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539
	function refreshUniformsShadow ( uniforms, lights ) {

		if ( uniforms.shadowMatrix ) {

			var j = 0;

			for ( var i = 0, il = lights.length; i < il; i ++ ) {

				var light = lights[ i ];

				if ( ! light.castShadow ) continue;

				if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {

					uniforms.shadowMap.value[ j ] = light.shadowMap;
					uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;

					uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;

					uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
					uniforms.shadowBias.value[ j ] = light.shadowBias;

					j ++;

				}

			}

		}

M
Mr.doob 已提交
2540
	}
M
Mr.doob 已提交
2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553

	// Uniforms (load to GPU)

	function loadUniformsMatrices ( uniforms, object ) {

		_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrix.elements );

		if ( uniforms.normalMatrix ) {

			_gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrix.elements );

		}

M
Mr.doob 已提交
2554
	}
M
Mr.doob 已提交
2555 2556 2557 2558 2559 2560 2561

	function getTextureUnit() {

		var textureUnit = _usedTextureUnits;

		if ( textureUnit >= _maxTextures ) {

2562
			console.warn( 'WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + _maxTextures );
M
Mr.doob 已提交
2563 2564 2565 2566 2567 2568 2569

		}

		_usedTextureUnits += 1;

		return textureUnit;

M
Mr.doob 已提交
2570
	}
M
Mr.doob 已提交
2571

2572
	function loadUniformsGeneric ( uniforms ) {
M
Mr.doob 已提交
2573

M
Mr.doob 已提交
2574
		var texture, textureUnit, offset;
M
Mr.doob 已提交
2575

M
Mr.doob 已提交
2576 2577 2578
		for ( var j = 0, jl = uniforms.length; j < jl; j ++ ) {

			var uniform = uniforms[ j ][ 0 ];
M
Mr.doob 已提交
2579

2580 2581
			// needsUpdate property is not added to all uniforms.
			if ( uniform.needsUpdate === false ) continue;
2582

M
Mr.doob 已提交
2583 2584
			var type = uniform.type;
			var value = uniform.value;
2585
			var location = uniforms[ j ][ 1 ];
M
Mr.doob 已提交
2586

2587
			switch ( type ) {
M
Mr.doob 已提交
2588

2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642
				case '1i':
					_gl.uniform1i( location, value );
					break;

				case '1f':
					_gl.uniform1f( location, value );
					break;

				case '2f':
					_gl.uniform2f( location, value[ 0 ], value[ 1 ] );
					break;

				case '3f':
					_gl.uniform3f( location, value[ 0 ], value[ 1 ], value[ 2 ] );
					break;

				case '4f':
					_gl.uniform4f( location, value[ 0 ], value[ 1 ], value[ 2 ], value[ 3 ] );
					break;

				case '1iv':
					_gl.uniform1iv( location, value );
					break;

				case '3iv':
					_gl.uniform3iv( location, value );
					break;

				case '1fv':
					_gl.uniform1fv( location, value );
					break;

				case '2fv':
					_gl.uniform2fv( location, value );
					break;

				case '3fv':
					_gl.uniform3fv( location, value );
					break;

				case '4fv':
					_gl.uniform4fv( location, value );
					break;

				case 'Matrix3fv':
					_gl.uniformMatrix3fv( location, false, value );
					break;

				case 'Matrix4fv':
					_gl.uniformMatrix4fv( location, false, value );
					break;

				//

M
Mr.doob 已提交
2643
				case 'i':
M
Mr.doob 已提交
2644

2645 2646
					// single integer
					_gl.uniform1i( location, value );
M
Mr.doob 已提交
2647

2648
					break;
M
Mr.doob 已提交
2649

2650
				case 'f':
M
Mr.doob 已提交
2651

2652 2653
					// single float
					_gl.uniform1f( location, value );
M
Mr.doob 已提交
2654

2655
					break;
M
Mr.doob 已提交
2656

2657
				case 'v2':
M
Mr.doob 已提交
2658

2659 2660
					// single THREE.Vector2
					_gl.uniform2f( location, value.x, value.y );
M
Mr.doob 已提交
2661

2662
					break;
M
Mr.doob 已提交
2663

2664
				case 'v3':
M
Mr.doob 已提交
2665

2666 2667
					// single THREE.Vector3
					_gl.uniform3f( location, value.x, value.y, value.z );
M
Mr.doob 已提交
2668

2669
					break;
M
Mr.doob 已提交
2670

M
Mr.doob 已提交
2671
				case 'v4':
M
Mr.doob 已提交
2672

2673 2674
					// single THREE.Vector4
					_gl.uniform4f( location, value.x, value.y, value.z, value.w );
M
Mr.doob 已提交
2675

2676
					break;
M
Mr.doob 已提交
2677

2678
				case 'c':
M
Mr.doob 已提交
2679

2680 2681
					// single THREE.Color
					_gl.uniform3f( location, value.r, value.g, value.b );
M
Mr.doob 已提交
2682

2683
					break;
M
Mr.doob 已提交
2684

2685
				case 'iv1':
M
Mr.doob 已提交
2686

2687 2688
					// flat array of integers (JS or typed array)
					_gl.uniform1iv( location, value );
M
Mr.doob 已提交
2689

2690
					break;
M
Mr.doob 已提交
2691

2692
				case 'iv':
M
Mr.doob 已提交
2693

2694 2695
					// flat array of integers with 3 x N size (JS or typed array)
					_gl.uniform3iv( location, value );
M
Mr.doob 已提交
2696

2697
					break;
M
Mr.doob 已提交
2698

2699
				case 'fv1':
M
Mr.doob 已提交
2700

2701 2702
					// flat array of floats (JS or typed array)
					_gl.uniform1fv( location, value );
M
Mr.doob 已提交
2703

2704
					break;
M
Mr.doob 已提交
2705

2706
				case 'fv':
M
Mr.doob 已提交
2707

2708 2709
					// flat array of floats with 3 x N size (JS or typed array)
					_gl.uniform3fv( location, value );
M
Mr.doob 已提交
2710

2711
					break;
M
Mr.doob 已提交
2712

2713
				case 'v2v':
M
Mr.doob 已提交
2714

2715
					// array of THREE.Vector2
M
Mr.doob 已提交
2716

2717
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2718

2719
						uniform._array = new Float32Array( 2 * value.length );
M
Mr.doob 已提交
2720

2721
					}
M
Mr.doob 已提交
2722

2723
					for ( var i = 0, il = value.length; i < il; i ++ ) {
M
Mr.doob 已提交
2724

2725
						offset = i * 2;
M
Mr.doob 已提交
2726

M
Mr.doob 已提交
2727
						uniform._array[ offset + 0 ] = value[ i ].x;
2728
						uniform._array[ offset + 1 ] = value[ i ].y;
M
Mr.doob 已提交
2729

2730
					}
M
Mr.doob 已提交
2731

2732
					_gl.uniform2fv( location, uniform._array );
M
Mr.doob 已提交
2733

2734
					break;
M
Mr.doob 已提交
2735

2736
				case 'v3v':
M
Mr.doob 已提交
2737

2738
					// array of THREE.Vector3
M
Mr.doob 已提交
2739

2740
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2741

2742
						uniform._array = new Float32Array( 3 * value.length );
M
Mr.doob 已提交
2743

2744
					}
M
Mr.doob 已提交
2745

2746
					for ( var i = 0, il = value.length; i < il; i ++ ) {
R
Ryan Tsao 已提交
2747

2748
						offset = i * 3;
R
Ryan Tsao 已提交
2749

M
Mr.doob 已提交
2750
						uniform._array[ offset + 0 ] = value[ i ].x;
2751 2752
						uniform._array[ offset + 1 ] = value[ i ].y;
						uniform._array[ offset + 2 ] = value[ i ].z;
R
Ryan Tsao 已提交
2753

2754
					}
R
Ryan Tsao 已提交
2755

2756
					_gl.uniform3fv( location, uniform._array );
R
Ryan Tsao 已提交
2757

2758
					break;
R
Ryan Tsao 已提交
2759

2760
				case 'v4v':
R
Ryan Tsao 已提交
2761

2762
					// array of THREE.Vector4
R
Ryan Tsao 已提交
2763

2764
					if ( uniform._array === undefined ) {
R
Ryan Tsao 已提交
2765

2766
						uniform._array = new Float32Array( 4 * value.length );
R
Ryan Tsao 已提交
2767

2768
					}
M
Mr.doob 已提交
2769

2770
					for ( var i = 0, il = value.length; i < il; i ++ ) {
M
Mr.doob 已提交
2771

2772
						offset = i * 4;
M
Mr.doob 已提交
2773

M
Mr.doob 已提交
2774
						uniform._array[ offset + 0 ] = value[ i ].x;
2775 2776 2777
						uniform._array[ offset + 1 ] = value[ i ].y;
						uniform._array[ offset + 2 ] = value[ i ].z;
						uniform._array[ offset + 3 ] = value[ i ].w;
M
Mr.doob 已提交
2778

2779
					}
M
Mr.doob 已提交
2780

2781
					_gl.uniform4fv( location, uniform._array );
M
Mr.doob 已提交
2782

2783
					break;
M
Mr.doob 已提交
2784

2785
				case 'm3':
M
Mr.doob 已提交
2786

2787 2788
					// single THREE.Matrix3
					_gl.uniformMatrix3fv( location, false, value.elements );
M
Mr.doob 已提交
2789

2790
					break;
M
Mr.doob 已提交
2791

2792
				case 'm3v':
M
Mr.doob 已提交
2793

2794
					// array of THREE.Matrix3
M
Mr.doob 已提交
2795

2796
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2797

2798
						uniform._array = new Float32Array( 9 * value.length );
M
Mr.doob 已提交
2799

2800
					}
M
Mr.doob 已提交
2801

2802
					for ( var i = 0, il = value.length; i < il; i ++ ) {
M
Mr.doob 已提交
2803

2804
						value[ i ].flattenToArrayOffset( uniform._array, i * 9 );
M
Mr.doob 已提交
2805

2806
					}
M
Mr.doob 已提交
2807

2808
					_gl.uniformMatrix3fv( location, false, uniform._array );
M
Mr.doob 已提交
2809

2810
					break;
M
Mr.doob 已提交
2811

2812
				case 'm4':
M
Mr.doob 已提交
2813

2814 2815
					// single THREE.Matrix4
					_gl.uniformMatrix4fv( location, false, value.elements );
M
Mr.doob 已提交
2816

2817
					break;
M
Mr.doob 已提交
2818

2819
				case 'm4v':
M
Mr.doob 已提交
2820

2821
					// array of THREE.Matrix4
M
Mr.doob 已提交
2822

2823
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2824

2825
						uniform._array = new Float32Array( 16 * value.length );
M
Mr.doob 已提交
2826

2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837
					}

					for ( var i = 0, il = value.length; i < il; i ++ ) {

						value[ i ].flattenToArrayOffset( uniform._array, i * 16 );

					}

					_gl.uniformMatrix4fv( location, false, uniform._array );

					break;
M
Mr.doob 已提交
2838

2839
				case 't':
M
Mr.doob 已提交
2840

2841
					// single THREE.Texture (2d or cube)
M
Mr.doob 已提交
2842

2843 2844 2845 2846
					texture = value;
					textureUnit = getTextureUnit();

					_gl.uniform1i( location, textureUnit );
M
Mr.doob 已提交
2847

2848
					if ( ! texture ) continue;
M
Mr.doob 已提交
2849

2850
					if ( texture instanceof THREE.CubeTexture ||
2851
						 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) { // CompressedTexture can have Array in image :/
M
Mr.doob 已提交
2852

2853
						setCubeTexture( texture, textureUnit );
M
Mr.doob 已提交
2854

2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898
					} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {

						setCubeTextureDynamic( texture, textureUnit );

					} else {

						_this.setTexture( texture, textureUnit );

					}

					break;

				case 'tv':

					// array of THREE.Texture (2d)

					if ( uniform._array === undefined ) {

						uniform._array = [];

					}

					for ( var i = 0, il = uniform.value.length; i < il; i ++ ) {

						uniform._array[ i ] = getTextureUnit();

					}

					_gl.uniform1iv( location, uniform._array );

					for ( var i = 0, il = uniform.value.length; i < il; i ++ ) {

						texture = uniform.value[ i ];
						textureUnit = uniform._array[ i ];

						if ( ! texture ) continue;

						_this.setTexture( texture, textureUnit );

					}

					break;

				default:
2899

2900
					console.warn( 'THREE.WebGLRenderer: Unknown uniform type: ' + type );
2901

M
Mr.doob 已提交
2902 2903 2904 2905
			}

		}

M
Mr.doob 已提交
2906
	}
M
Mr.doob 已提交
2907 2908 2909 2910

	function setupMatrices ( object, camera ) {

		object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
2911
		object._normalMatrix.getNormalMatrix( object._modelViewMatrix );
M
Mr.doob 已提交
2912

M
Mr.doob 已提交
2913
	}
M
Mr.doob 已提交
2914 2915 2916

	function setColorLinear( array, offset, color, intensity ) {

M
Mr.doob 已提交
2917
		array[ offset + 0 ] = color.r * intensity;
M
Mr.doob 已提交
2918 2919 2920
		array[ offset + 1 ] = color.g * intensity;
		array[ offset + 2 ] = color.b * intensity;

M
Mr.doob 已提交
2921
	}
M
Mr.doob 已提交
2922

2923
	function setupLights ( lights ) {
M
Mr.doob 已提交
2924

B
brason 已提交
2925
		var l, ll, light,
M
Mr.doob 已提交
2926 2927
		r = 0, g = 0, b = 0,
		color, skyColor, groundColor,
B
brason 已提交
2928
		intensity,
M
Mr.doob 已提交
2929 2930 2931 2932 2933 2934 2935 2936 2937 2938
		distance,

		zlights = _lights,

		dirColors = zlights.directional.colors,
		dirPositions = zlights.directional.positions,

		pointColors = zlights.point.colors,
		pointPositions = zlights.point.positions,
		pointDistances = zlights.point.distances,
M
Mr.doob 已提交
2939
		pointDecays = zlights.point.decays,
M
Mr.doob 已提交
2940 2941 2942 2943 2944 2945 2946

		spotColors = zlights.spot.colors,
		spotPositions = zlights.spot.positions,
		spotDistances = zlights.spot.distances,
		spotDirections = zlights.spot.directions,
		spotAnglesCos = zlights.spot.anglesCos,
		spotExponents = zlights.spot.exponents,
M
Mr.doob 已提交
2947
		spotDecays = zlights.spot.decays,
M
Mr.doob 已提交
2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981

		hemiSkyColors = zlights.hemi.skyColors,
		hemiGroundColors = zlights.hemi.groundColors,
		hemiPositions = zlights.hemi.positions,

		dirLength = 0,
		pointLength = 0,
		spotLength = 0,
		hemiLength = 0,

		dirCount = 0,
		pointCount = 0,
		spotCount = 0,
		hemiCount = 0,

		dirOffset = 0,
		pointOffset = 0,
		spotOffset = 0,
		hemiOffset = 0;

		for ( l = 0, ll = lights.length; l < ll; l ++ ) {

			light = lights[ l ];

			if ( light.onlyShadow ) continue;

			color = light.color;
			intensity = light.intensity;
			distance = light.distance;

			if ( light instanceof THREE.AmbientLight ) {

				if ( ! light.visible ) continue;

2982 2983 2984
				r += color.r;
				g += color.g;
				b += color.b;
M
Mr.doob 已提交
2985 2986 2987 2988 2989 2990 2991

			} else if ( light instanceof THREE.DirectionalLight ) {

				dirCount += 1;

				if ( ! light.visible ) continue;

2992 2993
				_direction.setFromMatrixPosition( light.matrixWorld );
				_vector3.setFromMatrixPosition( light.target.matrixWorld );
M
Mr.doob 已提交
2994 2995 2996 2997 2998
				_direction.sub( _vector3 );
				_direction.normalize();

				dirOffset = dirLength * 3;

M
Mr.doob 已提交
2999
				dirPositions[ dirOffset + 0 ] = _direction.x;
M
Mr.doob 已提交
3000 3001 3002
				dirPositions[ dirOffset + 1 ] = _direction.y;
				dirPositions[ dirOffset + 2 ] = _direction.z;

3003
				setColorLinear( dirColors, dirOffset, color, intensity );
M
Mr.doob 已提交
3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014

				dirLength += 1;

			} else if ( light instanceof THREE.PointLight ) {

				pointCount += 1;

				if ( ! light.visible ) continue;

				pointOffset = pointLength * 3;

3015
				setColorLinear( pointColors, pointOffset, color, intensity );
M
Mr.doob 已提交
3016

3017
				_vector3.setFromMatrixPosition( light.matrixWorld );
M
Mr.doob 已提交
3018

M
Mr.doob 已提交
3019
				pointPositions[ pointOffset + 0 ] = _vector3.x;
M
Mr.doob 已提交
3020 3021 3022
				pointPositions[ pointOffset + 1 ] = _vector3.y;
				pointPositions[ pointOffset + 2 ] = _vector3.z;

M
Mr.doob 已提交
3023
				// distance is 0 if decay is 0, because there is no attenuation at all.
M
Mr.doob 已提交
3024
				pointDistances[ pointLength ] = distance;
M
Mr.doob 已提交
3025
				pointDecays[ pointLength ] = ( light.distance === 0 ) ? 0.0 : light.decay;
M
Mr.doob 已提交
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036

				pointLength += 1;

			} else if ( light instanceof THREE.SpotLight ) {

				spotCount += 1;

				if ( ! light.visible ) continue;

				spotOffset = spotLength * 3;

3037
				setColorLinear( spotColors, spotOffset, color, intensity );
M
Mr.doob 已提交
3038

G
gero3 已提交
3039
				_direction.setFromMatrixPosition( light.matrixWorld );
M
Mr.doob 已提交
3040

M
Mr.doob 已提交
3041
				spotPositions[ spotOffset + 0 ] = _direction.x;
G
gero3 已提交
3042 3043
				spotPositions[ spotOffset + 1 ] = _direction.y;
				spotPositions[ spotOffset + 2 ] = _direction.z;
M
Mr.doob 已提交
3044 3045 3046

				spotDistances[ spotLength ] = distance;

3047
				_vector3.setFromMatrixPosition( light.target.matrixWorld );
M
Mr.doob 已提交
3048 3049 3050
				_direction.sub( _vector3 );
				_direction.normalize();

M
Mr.doob 已提交
3051
				spotDirections[ spotOffset + 0 ] = _direction.x;
M
Mr.doob 已提交
3052 3053 3054 3055 3056
				spotDirections[ spotOffset + 1 ] = _direction.y;
				spotDirections[ spotOffset + 2 ] = _direction.z;

				spotAnglesCos[ spotLength ] = Math.cos( light.angle );
				spotExponents[ spotLength ] = light.exponent;
M
Mr.doob 已提交
3057
				spotDecays[ spotLength ] = ( light.distance === 0 ) ? 0.0 : light.decay;
M
Mr.doob 已提交
3058 3059 3060 3061 3062 3063 3064 3065 3066

				spotLength += 1;

			} else if ( light instanceof THREE.HemisphereLight ) {

				hemiCount += 1;

				if ( ! light.visible ) continue;

3067
				_direction.setFromMatrixPosition( light.matrixWorld );
M
Mr.doob 已提交
3068 3069 3070 3071
				_direction.normalize();

				hemiOffset = hemiLength * 3;

M
Mr.doob 已提交
3072
				hemiPositions[ hemiOffset + 0 ] = _direction.x;
M
Mr.doob 已提交
3073 3074 3075 3076 3077 3078
				hemiPositions[ hemiOffset + 1 ] = _direction.y;
				hemiPositions[ hemiOffset + 2 ] = _direction.z;

				skyColor = light.color;
				groundColor = light.groundColor;

3079 3080
				setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
				setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
M
Mr.doob 已提交
3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105

				hemiLength += 1;

			}

		}

		// null eventual remains from removed lights
		// (this is to avoid if in shader)

		for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
		for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
		for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
		for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
		for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;

		zlights.directional.length = dirLength;
		zlights.point.length = pointLength;
		zlights.spot.length = spotLength;
		zlights.hemi.length = hemiLength;

		zlights.ambient[ 0 ] = r;
		zlights.ambient[ 1 ] = g;
		zlights.ambient[ 2 ] = b;

M
Mr.doob 已提交
3106
	}
M
Mr.doob 已提交
3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147

	// GL state setting

	this.setFaceCulling = function ( cullFace, frontFaceDirection ) {

		if ( cullFace === THREE.CullFaceNone ) {

			_gl.disable( _gl.CULL_FACE );

		} else {

			if ( frontFaceDirection === THREE.FrontFaceDirectionCW ) {

				_gl.frontFace( _gl.CW );

			} else {

				_gl.frontFace( _gl.CCW );

			}

			if ( cullFace === THREE.CullFaceBack ) {

				_gl.cullFace( _gl.BACK );

			} else if ( cullFace === THREE.CullFaceFront ) {

				_gl.cullFace( _gl.FRONT );

			} else {

				_gl.cullFace( _gl.FRONT_AND_BACK );

			}

			_gl.enable( _gl.CULL_FACE );

		}

	};

M
Mr.doob 已提交
3148
	this.setMaterialFaces = setMaterialFaces;
M
Mr.doob 已提交
3149 3150 3151 3152 3153

	// Textures

	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {

3154 3155
		var extension;

M
Mr.doob 已提交
3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167
		if ( isImagePowerOfTwo ) {

			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );

			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );

		} else {

			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
M
Mr.doob 已提交
3168 3169 3170

			if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) {

3171
				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping. ( ' + texture.sourceFile + ' )' );
M
Mr.doob 已提交
3172

3173
			}
M
Mr.doob 已提交
3174 3175 3176 3177

			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );

M
Mr.doob 已提交
3178 3179
			if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) {

3180
				console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter. ( ' + texture.sourceFile + ' )' );
M
Mr.doob 已提交
3181

3182
			}
M
Mr.doob 已提交
3183

M
Mr.doob 已提交
3184 3185
		}

3186 3187
		extension = extensions.get( 'EXT_texture_filter_anisotropic' );

3188
		if ( extension && texture.type !== THREE.FloatType && texture.type !== THREE.HalfFloatType ) {
M
Mr.doob 已提交
3189

M
Mr.doob 已提交
3190
			if ( texture.anisotropy > 1 || texture.__currentAnisotropy ) {
M
Mr.doob 已提交
3191

3192
				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) );
M
Mr.doob 已提交
3193
				texture.__currentAnisotropy = texture.anisotropy;
M
Mr.doob 已提交
3194 3195 3196 3197 3198

			}

		}

M
Mr.doob 已提交
3199
	}
M
Mr.doob 已提交
3200

3201
	this.uploadTexture = function ( texture, slot ) {
M
Mr.doob 已提交
3202

3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213
		if ( texture.__webglInit === undefined ) {

			texture.__webglInit = true;

			texture.addEventListener( 'dispose', onTextureDispose );

			texture.__webglTexture = _gl.createTexture();

			_this.info.memory.textures ++;

		}
M
Mr.doob 已提交
3214

B
Ben Adams 已提交
3215 3216
		state.activeTexture( _gl.TEXTURE0 + slot );
		state.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
M
Mr.doob 已提交
3217

H
Henri Astre 已提交
3218 3219 3220 3221
		_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 );

3222 3223
		texture.image = clampToMaxSize( texture.image, _maxTextureSize );

H
Henri Astre 已提交
3224 3225 3226 3227
		var image = texture.image,
		isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
		glFormat = paramThreeToGL( texture.format ),
		glType = paramThreeToGL( texture.type );
M
Mr.doob 已提交
3228

H
Henri Astre 已提交
3229
		setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
M
Mr.doob 已提交
3230

H
Henri Astre 已提交
3231
		var mipmap, mipmaps = texture.mipmaps;
M
Mr.doob 已提交
3232

H
Henri Astre 已提交
3233
		if ( texture instanceof THREE.DataTexture ) {
M
Mr.doob 已提交
3234

H
Henri Astre 已提交
3235 3236 3237
			// 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
M
Mr.doob 已提交
3238

H
Henri Astre 已提交
3239 3240 3241
			if ( mipmaps.length > 0 && isImagePowerOfTwo ) {

				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
M
Mr.doob 已提交
3242

H
Henri Astre 已提交
3243
					mipmap = mipmaps[ i ];
3244
					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
M
Mr.doob 已提交
3245

H
Henri Astre 已提交
3246
				}
M
Mr.doob 已提交
3247

H
Henri Astre 已提交
3248
				texture.generateMipmaps = false;
M
Mr.doob 已提交
3249

H
Henri Astre 已提交
3250
			} else {
M
Mr.doob 已提交
3251

3252
				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
M
Mr.doob 已提交
3253

H
Henri Astre 已提交
3254
			}
M
Mr.doob 已提交
3255

H
Henri Astre 已提交
3256
		} else if ( texture instanceof THREE.CompressedTexture ) {
M
Mr.doob 已提交
3257

H
Henri Astre 已提交
3258
			for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
M
Mr.doob 已提交
3259

H
Henri Astre 已提交
3260
				mipmap = mipmaps[ i ];
M
Mr.doob 已提交
3261

3262
				if ( texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat ) {
M
Mr.doob 已提交
3263

3264
					if ( getCompressedTextureFormats().indexOf( glFormat ) > -1 ) {
M
Mr.doob 已提交
3265

3266
						state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
M
Mr.doob 已提交
3267

3268
					} else {
M
Mr.doob 已提交
3269

3270
						console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()" );
M
Mr.doob 已提交
3271

3272
					}
M
Mr.doob 已提交
3273

H
Henri Astre 已提交
3274
				} else {
M
Mr.doob 已提交
3275

3276
					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
M
Mr.doob 已提交
3277

M
Mr.doob 已提交
3278 3279
				}

H
Henri Astre 已提交
3280 3281 3282 3283 3284 3285 3286 3287 3288
			}

		} 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

			if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
M
Mr.doob 已提交
3289

3290
				for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
M
Mr.doob 已提交
3291 3292

					mipmap = mipmaps[ i ];
3293
					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
M
Mr.doob 已提交
3294 3295 3296

				}

H
Henri Astre 已提交
3297
				texture.generateMipmaps = false;
M
Mr.doob 已提交
3298

H
Henri Astre 已提交
3299
			} else {
M
Mr.doob 已提交
3300

3301
				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
M
Mr.doob 已提交
3302

H
Henri Astre 已提交
3303
			}
M
Mr.doob 已提交
3304

H
Henri Astre 已提交
3305
		}
M
Mr.doob 已提交
3306

H
Henri Astre 已提交
3307
		if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
M
Mr.doob 已提交
3308

H
Henri Astre 已提交
3309
		texture.needsUpdate = false;
M
Mr.doob 已提交
3310

B
Ben Adams 已提交
3311
		if ( texture.onUpdate ) texture.onUpdate( texture );
M
Mr.doob 已提交
3312

H
Henri Astre 已提交
3313
	};
M
Mr.doob 已提交
3314

H
Henri Astre 已提交
3315
	this.setTexture = function ( texture, slot ) {
M
Mr.doob 已提交
3316

3317
		if ( texture.needsUpdate === true ) {
M
Mr.doob 已提交
3318

3319
			var image = texture.image;
M
Mr.doob 已提交
3320

3321 3322
			if ( image === undefined ) {

3323
				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
3324 3325 3326 3327
				return;

			}

3328
			if ( image.complete === false ) {
M
Mr.doob 已提交
3329

3330
				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
3331 3332 3333 3334
				return;

			}

3335
			_this.uploadTexture( texture, slot );
3336
			return;
M
Mr.doob 已提交
3337 3338 3339

		}

B
Ben Adams 已提交
3340 3341
		state.activeTexture( _gl.TEXTURE0 + slot );
		state.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
3342

M
Mr.doob 已提交
3343 3344 3345 3346
	};

	function clampToMaxSize ( image, maxSize ) {

3347
		if ( image.width > maxSize || image.height > maxSize ) {
M
Mr.doob 已提交
3348

3349 3350
			// Warning: Scaling through the canvas will only work with images that use
			// premultiplied alpha.
M
Mr.doob 已提交
3351

3352
			var scale = maxSize / Math.max( image.width, image.height );
M
Mr.doob 已提交
3353

3354 3355 3356
			var canvas = document.createElement( 'canvas' );
			canvas.width = Math.floor( image.width * scale );
			canvas.height = Math.floor( image.height * scale );
M
Mr.doob 已提交
3357

3358 3359
			var context = canvas.getContext( '2d' );
			context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
M
Mr.doob 已提交
3360

3361
			console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
M
Mr.doob 已提交
3362

3363 3364 3365
			return canvas;

		}
M
Mr.doob 已提交
3366

3367
		return image;
M
Mr.doob 已提交
3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378

	}

	function setCubeTexture ( texture, slot ) {

		if ( texture.image.length === 6 ) {

			if ( texture.needsUpdate ) {

				if ( ! texture.image.__webglTextureCube ) {

3379 3380
					texture.addEventListener( 'dispose', onTextureDispose );

M
Mr.doob 已提交
3381 3382 3383 3384 3385 3386
					texture.image.__webglTextureCube = _gl.createTexture();

					_this.info.memory.textures ++;

				}

B
Ben Adams 已提交
3387 3388
				state.activeTexture( _gl.TEXTURE0 + slot );
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
M
Mr.doob 已提交
3389 3390 3391

				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );

M
Mr.doob 已提交
3392 3393
				var isCompressed = texture instanceof THREE.CompressedTexture;
				var isDataTexture = texture.image[ 0 ] instanceof THREE.DataTexture;
M
Mr.doob 已提交
3394 3395 3396 3397 3398

				var cubeImage = [];

				for ( var i = 0; i < 6; i ++ ) {

3399
					if ( _this.autoScaleCubemaps && ! isCompressed && ! isDataTexture ) {
M
Mr.doob 已提交
3400 3401 3402 3403 3404

						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );

					} else {

3405
						cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
M
Mr.doob 已提交
3406 3407 3408 3409 3410 3411

					}

				}

				var image = cubeImage[ 0 ],
3412
				isImagePowerOfTwo = THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height ),
M
Mr.doob 已提交
3413 3414 3415 3416 3417 3418 3419
				glFormat = paramThreeToGL( texture.format ),
				glType = paramThreeToGL( texture.type );

				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );

				for ( var i = 0; i < 6; i ++ ) {

3420
					if ( ! isCompressed ) {
M
Mr.doob 已提交
3421

M
Mr.doob 已提交
3422
						if ( isDataTexture ) {
3423

3424
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
3425

M
Mr.doob 已提交
3426
						} else {
3427

3428
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
3429

M
Mr.doob 已提交
3430 3431
						}

3432
					} else {
3433

M
Mr.doob 已提交
3434 3435
						var mipmap, mipmaps = cubeImage[ i ].mipmaps;

3436
						for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
M
Mr.doob 已提交
3437 3438

							mipmap = mipmaps[ j ];
M
Mr.doob 已提交
3439

3440
							if ( texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat ) {
M
Mr.doob 已提交
3441

3442
								if ( getCompressedTextureFormats().indexOf( glFormat ) > -1 ) {
M
Mr.doob 已提交
3443

3444
									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
M
Mr.doob 已提交
3445

3446
								} else {
M
Mr.doob 已提交
3447

3448
									console.warn( "THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setCubeTexture()" );
M
Mr.doob 已提交
3449

3450
								}
M
Mr.doob 已提交
3451

3452
							} else {
M
Mr.doob 已提交
3453

3454
								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
M
Mr.doob 已提交
3455

3456
							}
M
Mr.doob 已提交
3457

3458
						}
M
Mr.doob 已提交
3459

M
Mr.doob 已提交
3460
					}
M
Mr.doob 已提交
3461

M
Mr.doob 已提交
3462 3463 3464 3465 3466 3467 3468 3469 3470 3471
				}

				if ( texture.generateMipmaps && isImagePowerOfTwo ) {

					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );

				}

				texture.needsUpdate = false;

B
Ben Adams 已提交
3472
				if ( texture.onUpdate ) texture.onUpdate( texture );
M
Mr.doob 已提交
3473 3474 3475

			} else {

B
Ben Adams 已提交
3476 3477
				state.activeTexture( _gl.TEXTURE0 + slot );
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
M
Mr.doob 已提交
3478 3479 3480 3481 3482

			}

		}

M
Mr.doob 已提交
3483
	}
M
Mr.doob 已提交
3484 3485 3486

	function setCubeTextureDynamic ( texture, slot ) {

B
Ben Adams 已提交
3487 3488
		state.activeTexture( _gl.TEXTURE0 + slot );
		state.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
M
Mr.doob 已提交
3489

M
Mr.doob 已提交
3490
	}
M
Mr.doob 已提交
3491 3492 3493 3494 3495 3496 3497 3498

	// Render targets

	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {

		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );

M
Mr.doob 已提交
3499
	}
M
Mr.doob 已提交
3500

M
Mr.doob 已提交
3501
	function setupRenderBuffer ( renderbuffer, renderTarget ) {
M
Mr.doob 已提交
3502 3503 3504 3505 3506 3507 3508 3509 3510

		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );

		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {

			_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.
3511
		} else if ( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
M
Mr.doob 已提交
3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526

			_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 );

		} else {

			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );

		}

M
Mr.doob 已提交
3527
	}
M
Mr.doob 已提交
3528 3529 3530 3531 3532

	this.setRenderTarget = function ( renderTarget ) {

		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );

M
Mr.doob 已提交
3533
		if ( renderTarget && renderTarget.__webglFramebuffer === undefined ) {
M
Mr.doob 已提交
3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545

			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;

			renderTarget.addEventListener( 'dispose', onRenderTargetDispose );

			renderTarget.__webglTexture = _gl.createTexture();

			_this.info.memory.textures ++;

			// Setup texture, create render and frame buffers

3546
			var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height ),
M
Mr.doob 已提交
3547 3548 3549 3550 3551 3552 3553 3554
				glFormat = paramThreeToGL( renderTarget.format ),
				glType = paramThreeToGL( renderTarget.type );

			if ( isCube ) {

				renderTarget.__webglFramebuffer = [];
				renderTarget.__webglRenderbuffer = [];

B
Ben Adams 已提交
3555 3556
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );

M
Mr.doob 已提交
3557 3558 3559 3560 3561 3562 3563
				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );

				for ( var i = 0; i < 6; i ++ ) {

					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();

3564
					state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
M
Mr.doob 已提交
3565 3566 3567 3568 3569 3570

					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );

				}

3571
				if ( renderTarget.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
M
Mr.doob 已提交
3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586

			} else {

				renderTarget.__webglFramebuffer = _gl.createFramebuffer();

				if ( renderTarget.shareDepthFrom ) {

					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;

				} else {

					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();

				}

B
Ben Adams 已提交
3587
				state.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
M
Mr.doob 已提交
3588 3589
				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );

3590
				state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
M
Mr.doob 已提交
3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611

				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );

				if ( renderTarget.shareDepthFrom ) {

					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {

						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );

					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {

						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );

					}

				} else {

					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );

				}

3612
				if ( renderTarget.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
M
Mr.doob 已提交
3613 3614 3615 3616 3617 3618 3619

			}

			// Release everything

			if ( isCube ) {

B
Ben Adams 已提交
3620
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
M
Mr.doob 已提交
3621 3622 3623

			} else {

B
Ben Adams 已提交
3624
				state.bindTexture( _gl.TEXTURE_2D, null );
M
Mr.doob 已提交
3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678

			}

			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );

		}

		var framebuffer, width, height, vx, vy;

		if ( renderTarget ) {

			if ( isCube ) {

				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];

			} else {

				framebuffer = renderTarget.__webglFramebuffer;

			}

			width = renderTarget.width;
			height = renderTarget.height;

			vx = 0;
			vy = 0;

		} else {

			framebuffer = null;

			width = _viewportWidth;
			height = _viewportHeight;

			vx = _viewportX;
			vy = _viewportY;

		}

		if ( framebuffer !== _currentFramebuffer ) {

			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
			_gl.viewport( vx, vy, width, height );

			_currentFramebuffer = framebuffer;

		}

		_currentWidth = width;
		_currentHeight = height;

	};

3679
	this.readRenderTargetPixels = function( renderTarget, x, y, width, height, buffer ) {
3680

G
gero3 已提交
3681
		if ( ! ( renderTarget instanceof THREE.WebGLRenderTarget ) ) {
3682

3683
			console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
G
gero3 已提交
3684
			return;
3685

G
gero3 已提交
3686
		}
3687

G
gero3 已提交
3688
		if ( renderTarget.__webglFramebuffer ) {
3689

G
gero3 已提交
3690
			if ( renderTarget.format !== THREE.RGBAFormat ) {
3691

3692
				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA format. readPixels can read only RGBA format.' );
G
gero3 已提交
3693
				return;
3694

G
gero3 已提交
3695
			}
3696

G
gero3 已提交
3697
			var restore = false;
3698

G
gero3 已提交
3699
			if ( renderTarget.__webglFramebuffer !== _currentFramebuffer ) {
3700

G
gero3 已提交
3701
				_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTarget.__webglFramebuffer );
3702

G
gero3 已提交
3703
				restore = true;
3704

G
gero3 已提交
3705
			}
3706

G
gero3 已提交
3707
			if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
3708

G
gero3 已提交
3709
				_gl.readPixels( x, y, width, height, _gl.RGBA, _gl.UNSIGNED_BYTE, buffer );
3710

G
gero3 已提交
3711
			} else {
3712

3713
				console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );
3714

G
gero3 已提交
3715
			}
3716

G
gero3 已提交
3717
			if ( restore ) {
3718

G
gero3 已提交
3719
				_gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
3720

G
gero3 已提交
3721
			}
3722

G
gero3 已提交
3723
		}
3724 3725 3726

	};

M
Mr.doob 已提交
3727 3728 3729 3730
	function updateRenderTargetMipmap ( renderTarget ) {

		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {

B
Ben Adams 已提交
3731
			state.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
M
Mr.doob 已提交
3732
			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
B
Ben Adams 已提交
3733
			state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
M
Mr.doob 已提交
3734 3735 3736

		} else {

B
Ben Adams 已提交
3737
			state.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
M
Mr.doob 已提交
3738
			_gl.generateMipmap( _gl.TEXTURE_2D );
B
Ben Adams 已提交
3739
			state.bindTexture( _gl.TEXTURE_2D, null );
M
Mr.doob 已提交
3740 3741 3742

		}

M
Mr.doob 已提交
3743
	}
M
Mr.doob 已提交
3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756

	// Fallback filters for non-power-of-2 textures

	function filterFallback ( f ) {

		if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {

			return _gl.NEAREST;

		}

		return _gl.LINEAR;

M
Mr.doob 已提交
3757
	}
M
Mr.doob 已提交
3758 3759 3760 3761 3762

	// Map three.js constants to WebGL constants

	function paramThreeToGL ( p ) {

3763 3764
		var extension;

M
Mr.doob 已提交
3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
		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;

		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;

3789 3790 3791 3792 3793 3794 3795 3796
		extension = extensions.get( 'OES_texture_half_float' );

		if ( extension !== null ) {

			if ( p === THREE.HalfFloatType ) return extension.HALF_FLOAT_OES;

		}

M
Mr.doob 已提交
3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819
		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;

3820
		extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
M
Mr.doob 已提交
3821

3822 3823 3824 3825 3826 3827
		if ( extension !== null ) {

			if ( p === THREE.RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
			if ( p === THREE.RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
			if ( p === THREE.RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
			if ( p === THREE.RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
M
Mr.doob 已提交
3828 3829 3830

		}

3831 3832 3833
		extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );

		if ( extension !== null ) {
P
Pierre Lepers 已提交
3834

3835 3836 3837 3838
			if ( p === THREE.RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
			if ( p === THREE.RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
			if ( p === THREE.RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
			if ( p === THREE.RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
P
Pierre Lepers 已提交
3839 3840 3841

		}

3842 3843 3844
		extension = extensions.get( 'EXT_blend_minmax' );

		if ( extension !== null ) {
3845

3846 3847
			if ( p === THREE.MinEquation ) return extension.MIN_EXT;
			if ( p === THREE.MaxEquation ) return extension.MAX_EXT;
3848 3849 3850

		}

M
Mr.doob 已提交
3851 3852
		return 0;

M
Mr.doob 已提交
3853
	}
M
Mr.doob 已提交
3854 3855 3856 3857 3858

	// Allocations

	function allocateBones ( object ) {

3859
		if ( _supportsBoneTextures && object && object.skeleton && object.skeleton.useVertexTexture ) {
M
Mr.doob 已提交
3860 3861 3862 3863 3864 3865

			return 1024;

		} else {

			// default for when object is not specified
M
Mr.doob 已提交
3866
			// ( for example when prebuilding shader to be used with multiple objects )
M
Mr.doob 已提交
3867
			//
3868
			//  - leave some extra space for other uniforms
M
Mr.doob 已提交
3869 3870 3871 3872 3873 3874 3875 3876 3877 3878
			//  - limit here is ANGLE's 254 max uniform vectors
			//    (up to 54 should be safe)

			var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );

			var maxBones = nVertexMatrices;

			if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {

3879
				maxBones = Math.min( object.skeleton.bones.length, maxBones );
M
Mr.doob 已提交
3880

3881
				if ( maxBones < object.skeleton.bones.length ) {
M
Mr.doob 已提交
3882

3883
					console.warn( 'WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)' );
M
Mr.doob 已提交
3884 3885 3886 3887 3888 3889 3890 3891 3892

				}

			}

			return maxBones;

		}

M
Mr.doob 已提交
3893
	}
M
Mr.doob 已提交
3894

M
Mr.doob 已提交
3895
	function allocateLights( lights ) {
M
Mr.doob 已提交
3896

M
Mr.doob 已提交
3897 3898 3899 3900
		var dirLights = 0;
		var pointLights = 0;
		var spotLights = 0;
		var hemiLights = 0;
M
Mr.doob 已提交
3901

M
Mr.doob 已提交
3902
		for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
M
Mr.doob 已提交
3903

M
Mr.doob 已提交
3904
			var light = lights[ l ];
M
Mr.doob 已提交
3905

3906
			if ( light.onlyShadow || light.visible === false ) continue;
M
Mr.doob 已提交
3907 3908 3909 3910 3911 3912 3913 3914

			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
			if ( light instanceof THREE.PointLight ) pointLights ++;
			if ( light instanceof THREE.SpotLight ) spotLights ++;
			if ( light instanceof THREE.HemisphereLight ) hemiLights ++;

		}

3915
		return { 'directional': dirLights, 'point': pointLights, 'spot': spotLights, 'hemi': hemiLights };
M
Mr.doob 已提交
3916

M
Mr.doob 已提交
3917
	}
M
Mr.doob 已提交
3918

M
Mr.doob 已提交
3919
	function allocateShadows( lights ) {
M
Mr.doob 已提交
3920

M
Mr.doob 已提交
3921
		var maxShadows = 0;
M
Mr.doob 已提交
3922

3923
		for ( var l = 0, ll = lights.length; l < ll; l ++ ) {
M
Mr.doob 已提交
3924

M
Mr.doob 已提交
3925
			var light = lights[ l ];
M
Mr.doob 已提交
3926 3927 3928 3929 3930 3931 3932 3933 3934 3935

			if ( ! light.castShadow ) continue;

			if ( light instanceof THREE.SpotLight ) maxShadows ++;
			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;

		}

		return maxShadows;

3936
	}
M
Mr.doob 已提交
3937

M
Mr.doob 已提交
3938
	// DEPRECATED
3939

M
Mr.doob 已提交
3940 3941
	this.initMaterial = function () {

3942
		console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );
M
Mr.doob 已提交
3943 3944

	};
M
Mr.doob 已提交
3945

M
Mr.doob 已提交
3946
	this.addPrePlugin = function () {
M
Mr.doob 已提交
3947

3948
		console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );
M
Mr.doob 已提交
3949 3950 3951 3952 3953

	};

	this.addPostPlugin = function () {

3954
		console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );
M
Mr.doob 已提交
3955 3956

	};
M
Mr.doob 已提交
3957

M
Mr.doob 已提交
3958 3959
	this.updateShadowMap = function () {

3960
		console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );
M
Mr.doob 已提交
3961 3962 3963

	};

3964 3965 3966
	Object.defineProperties( this, {
		shadowMapEnabled: {
			get: function () {
M
Mr.doob 已提交
3967
				return shadowMap.enabled;
3968 3969
			},
			set: function ( value ) {
3970
				console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );
M
Mr.doob 已提交
3971
				shadowMap.enabled = value;
3972 3973 3974 3975
			}
		},
		shadowMapType: {
			get: function () {
M
Mr.doob 已提交
3976
				return shadowMap.type;
3977 3978
			},
			set: function ( value ) {
3979
				console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );
M
Mr.doob 已提交
3980
				shadowMap.type = value;
3981 3982 3983 3984
			}
		},
		shadowMapCullFace: {
			get: function () {
M
Mr.doob 已提交
3985
				return shadowMap.cullFace;
3986 3987
			},
			set: function ( value ) {
3988
				console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.' );
M
Mr.doob 已提交
3989
				shadowMap.cullFace = value;
3990 3991 3992 3993
			}
		},
		shadowMapDebug: {
			get: function () {
M
Mr.doob 已提交
3994
				return shadowMap.debug;
3995 3996
			},
			set: function ( value ) {
3997
				console.warn( 'THREE.WebGLRenderer: .shadowMapDebug is now .shadowMap.debug.' );
M
Mr.doob 已提交
3998
				shadowMap.debug = value;
3999 4000 4001 4002
			}
		},
		shadowMapCascade: {
			get: function () {
M
Mr.doob 已提交
4003
				return shadowMap.cascade;
4004 4005
			},
			set: function ( value ) {
4006
				console.warn( 'THREE.WebGLRenderer: .shadowMapCascade is now .shadowMap.cascade.' );
M
Mr.doob 已提交
4007
				shadowMap.cascade = value;
4008 4009 4010 4011
			}
		}
	} );

M
Mr.doob 已提交
4012
};