WebGLRenderer.js 82.8 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,

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

29 30
	_clearColor = new THREE.Color( 0x000000 ),
	_clearAlpha = 0;
M
Mr.doob 已提交
31

M
Mr.doob 已提交
32
	var lights = [];
M
Mr.doob 已提交
33

O
OpenShift guest 已提交
34
	var opaqueObjects = [];
M
Mr.doob 已提交
35
	var opaqueObjectsLastIndex = - 1;
36
	var transparentObjects = [];
M
Mr.doob 已提交
37
	var transparentObjectsLastIndex = - 1;
38

39 40
	var morphInfluences = new Float32Array( 8 );

41

M
Mr.doob 已提交
42 43 44
	var sprites = [];
	var lensFlares = [];

M
Mr.doob 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
	// 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

63
	this.gammaFactor = 2.0;	// for backwards compatibility
M
Mr.doob 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
	this.gammaInput = false;
	this.gammaOutput = false;

	// morphs

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

	// flags

	this.autoScaleCubemaps = true;

	// internal properties

	var _this = this,

	// internal state cache

	_currentProgram = null,
83
	_currentRenderTarget = null,
M
Mr.doob 已提交
84
	_currentFramebuffer = null,
85
	_currentMaterialId = - 1,
86
	_currentGeometryProgram = '',
M
Mr.doob 已提交
87 88 89 90 91 92
	_currentCamera = null,

	_usedTextureUnits = 0,

	_viewportX = 0,
	_viewportY = 0,
93 94
	_viewportWidth = _canvas.width,
	_viewportHeight = _canvas.height,
M
Mr.doob 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	_currentWidth = 0,
	_currentHeight = 0,

	// frustum

	_frustum = new THREE.Frustum(),

	 // camera matrices cache

	_projScreenMatrix = new THREE.Matrix4(),

	_vector3 = new THREE.Vector3(),

	// light arrays cache

	_lights = {

112 113
		hash: '',

M
Mr.doob 已提交
114
		ambient: [ 0, 0, 0 ],
M
Mr.doob 已提交
115 116 117
		directional: [],
		point: [],
		spot: [],
118 119
		hemi: [],

120
		shadows: [],
121
		shadowsPointLight: 0
M
Mr.doob 已提交
122

123 124
	},

M
Mr.doob 已提交
125 126
	// info

127
	_infoMemory = {
128 129

		geometries: 0,
T
tschw 已提交
130
		textures: 0
131 132 133

	},

134
	_infoRender = {
135 136 137 138 139 140

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

M
Mr.doob 已提交
141 142
	};

M
Mr.doob 已提交
143
	this.info = {
144

M
Mr.doob 已提交
145 146
		render: _infoRender,
		memory: _infoMemory,
147
		programs: null
M
Mr.doob 已提交
148 149

	};
150

151

M
Mr.doob 已提交
152 153 154 155
	// initialize

	var _gl;

M
Mr.doob 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
	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 ) {

G
gero3 已提交
171
			if ( _canvas.getContext( 'webgl' ) !== null ) {
172 173 174 175 176 177 178 179

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

			} else {

				throw 'Error creating WebGL context.';

			}
M
Mr.doob 已提交
180 181 182

		}

D
dubejf 已提交
183
		_canvas.addEventListener( 'webglcontextlost', onContextLost, false );
184

M
Mr.doob 已提交
185 186
	} catch ( error ) {

187
		console.error( 'THREE.WebGLRenderer: ' + error );
M
Mr.doob 已提交
188 189 190

	}

191 192
	var extensions = new THREE.WebGLExtensions( _gl );

193 194
	extensions.get( 'OES_texture_float' );
	extensions.get( 'OES_texture_float_linear' );
195 196
	extensions.get( 'OES_texture_half_float' );
	extensions.get( 'OES_texture_half_float_linear' );
197
	extensions.get( 'OES_standard_derivatives' );
B
Ben Adams 已提交
198
	extensions.get( 'ANGLE_instanced_arrays' );
199

200 201
	if ( extensions.get( 'OES_element_index_uint' ) ) {

202
		THREE.BufferGeometry.MaxIndex = 4294967296;
203 204 205

	}

M
Mr.doob 已提交
206
	var capabilities = new THREE.WebGLCapabilities( _gl, extensions, parameters );
M
Mr.doob 已提交
207

208 209 210
	var state = new THREE.WebGLState( _gl, extensions, paramThreeToGL );
	var properties = new THREE.WebGLProperties();
	var objects = new THREE.WebGLObjects( _gl, properties, this.info );
G
gero3 已提交
211
	var programCache = new THREE.WebGLPrograms( this, capabilities );
M
Mr.doob 已提交
212
	var lightCache = new THREE.WebGLLights();
213

214 215
	this.info.programs = programCache.programs;

216 217
	var bufferRenderer = new THREE.WebGLBufferRenderer( _gl, extensions, _infoRender );
	var indexedBufferRenderer = new THREE.WebGLIndexedBufferRenderer( _gl, extensions, _infoRender );
218

M
Mr.doob 已提交
219 220
	//

221 222 223 224 225 226
	function getTargetPixelRatio() {

		return _currentRenderTarget === null ? pixelRatio : 1;

	}

227
	function glClearColor( r, g, b, a ) {
228 229 230

		if ( _premultipliedAlpha === true ) {

231
			r *= a; g *= a; b *= a;
232 233 234

		}

235 236
		_gl.clearColor( r, g, b, a );

237
	}
238

239
	function setDefaultGLState() {
M
Mr.doob 已提交
240

M
Mr.doob 已提交
241
		state.init();
M
Mr.doob 已提交
242 243 244

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

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

247
	}
248

249
	function resetGLState() {
250 251 252 253

		_currentProgram = null;
		_currentCamera = null;

254
		_currentGeometryProgram = '';
255 256
		_currentMaterialId = - 1;

M
Mr.doob 已提交
257 258
		state.reset();

259
	}
M
Mr.doob 已提交
260 261 262 263

	setDefaultGLState();

	this.context = _gl;
M
Mr.doob 已提交
264
	this.capabilities = capabilities;
265
	this.extensions = extensions;
M
Mr.doob 已提交
266
	this.state = state;
M
Mr.doob 已提交
267

M
Mr.doob 已提交
268 269
	// shadow map

M
Mr.doob 已提交
270
	var shadowMap = new THREE.WebGLShadowMap( this, _lights, objects );
M
Mr.doob 已提交
271

272
	this.shadowMap = shadowMap;
M
Mr.doob 已提交
273

M
Mr.doob 已提交
274

M
Mr.doob 已提交
275 276 277 278 279
	// Plugins

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

M
Mr.doob 已提交
280 281 282 283 284 285 286 287
	// API

	this.getContext = function () {

		return _gl;

	};

288 289 290 291 292 293
	this.getContextAttributes = function () {

		return _gl.getContextAttributes();

	};

294 295 296 297 298 299
	this.forceContextLoss = function () {

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

	};

300
	this.getMaxAnisotropy = ( function () {
M
Mr.doob 已提交
301

302
		var value;
M
Mr.doob 已提交
303

304
		return function getMaxAnisotropy() {
305

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

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

M
Mr.doob 已提交
310
			if ( extension !== null ) {
311

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

M
Mr.doob 已提交
314 315 316 317 318
			} else {

				value = 0;

			}
319 320 321

			return value;

M
Mr.doob 已提交
322
		};
323 324

	} )();
M
Mr.doob 已提交
325 326 327

	this.getPrecision = function () {

G
gero3 已提交
328
		return capabilities.precision;
M
Mr.doob 已提交
329 330 331

	};

332 333 334 335 336 337 338 339
	this.getPixelRatio = function () {

		return pixelRatio;

	};

	this.setPixelRatio = function ( value ) {

340
		if ( value !== undefined ) pixelRatio = value;
341 342 343

	};

344 345 346 347 348 349 350 351 352
	this.getSize = function () {

		return {
			width: _width,
			height: _height
		};

	};

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

355 356 357
		_width = width;
		_height = height;

358 359
		_canvas.width = width * pixelRatio;
		_canvas.height = height * pixelRatio;
360

361
		if ( updateStyle !== false ) {
362

G
gero3 已提交
363 364
			_canvas.style.width = width + 'px';
			_canvas.style.height = height + 'px';
365

G
gero3 已提交
366
		}
M
Mr.doob 已提交
367

368
		this.setViewport( 0, 0, width, height );
M
Mr.doob 已提交
369 370 371 372 373

	};

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

374 375
		_viewportX = x * pixelRatio;
		_viewportY = y * pixelRatio;
M
Mr.doob 已提交
376

377 378
		_viewportWidth = width * pixelRatio;
		_viewportHeight = height * pixelRatio;
M
Mr.doob 已提交
379 380 381 382 383

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

	};

M
Mr.doob 已提交
384 385 386 387 388 389 390 391 392 393
	this.getViewport = function ( dimensions ) {

		dimensions.x = _viewportX / pixelRatio;
		dimensions.y = _viewportY / pixelRatio;

		dimensions.z = _viewportWidth / pixelRatio;
		dimensions.w = _viewportHeight / pixelRatio;

	};

M
Mr.doob 已提交
394 395
	this.setScissor = function ( x, y, width, height ) {

396
		_gl.scissor(
397 398 399 400
			x * pixelRatio,
			y * pixelRatio,
			width * pixelRatio,
			height * pixelRatio
401
		);
M
Mr.doob 已提交
402 403 404

	};

405
	this.enableScissorTest = function ( boolean ) {
M
Mr.doob 已提交
406

M
Mr.doob 已提交
407
		state.setScissorTest( boolean );
M
Mr.doob 已提交
408 409 410 411 412

	};

	// Clearing

M
Mr.doob 已提交
413
	this.getClearColor = function () {
M
Mr.doob 已提交
414

M
Mr.doob 已提交
415
		return _clearColor;
M
Mr.doob 已提交
416 417 418

	};

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

M
Mr.doob 已提交
421
		_clearColor.set( color );
422

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

425
		glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
M
Mr.doob 已提交
426 427 428

	};

M
Mr.doob 已提交
429
	this.getClearAlpha = function () {
M
Mr.doob 已提交
430

M
Mr.doob 已提交
431
		return _clearAlpha;
M
Mr.doob 已提交
432 433 434

	};

M
Mr.doob 已提交
435
	this.setClearAlpha = function ( alpha ) {
M
Mr.doob 已提交
436

M
Mr.doob 已提交
437
		_clearAlpha = alpha;
M
Mr.doob 已提交
438

439
		glClearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
M
Mr.doob 已提交
440 441 442 443 444 445 446 447 448 449 450 451

	};

	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 );
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469

	};

	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 已提交
470 471 472 473 474 475 476 477 478 479

	};

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

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

	};

M
Mr.doob 已提交
480 481
	// Reset

482
	this.resetGLState = resetGLState;
M
Mr.doob 已提交
483

D
dubejf 已提交
484 485 486 487 488 489
	this.dispose = function() {

		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );

	};

M
Mr.doob 已提交
490
	// Events
M
Mr.doob 已提交
491

D
dubejf 已提交
492 493 494 495 496 497 498 499 500 501 502
	function onContextLost( event ) {

		event.preventDefault();

		resetGLState();
		setDefaultGLState();

		properties.clear();

	};

503
	function onTextureDispose( event ) {
M
Mr.doob 已提交
504 505 506 507 508 509 510

		var texture = event.target;

		texture.removeEventListener( 'dispose', onTextureDispose );

		deallocateTexture( texture );

511
		_infoMemory.textures --;
M
Mr.doob 已提交
512 513


514
	}
M
Mr.doob 已提交
515

516
	function onRenderTargetDispose( event ) {
M
Mr.doob 已提交
517 518 519 520 521 522 523

		var renderTarget = event.target;

		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );

		deallocateRenderTarget( renderTarget );

524
		_infoMemory.textures --;
M
Mr.doob 已提交
525

526
	}
M
Mr.doob 已提交
527

528
	function onMaterialDispose( event ) {
M
Mr.doob 已提交
529 530 531 532 533 534 535

		var material = event.target;

		material.removeEventListener( 'dispose', onMaterialDispose );

		deallocateMaterial( material );

536
	}
M
Mr.doob 已提交
537 538 539

	// Buffer deallocation

540
	function deallocateTexture( texture ) {
M
Mr.doob 已提交
541

542
		var textureProperties = properties.get( texture );
M
Mr.doob 已提交
543

544
		if ( texture.image && textureProperties.__image__webglTextureCube ) {
M
Mr.doob 已提交
545 546 547

			// cube texture

548
			_gl.deleteTexture( textureProperties.__image__webglTextureCube );
M
Mr.doob 已提交
549

550 551 552 553
		} else {

			// 2D texture

554
			if ( textureProperties.__webglInit === undefined ) return;
555

556
			_gl.deleteTexture( textureProperties.__webglTexture );
557

M
Mr.doob 已提交
558 559
		}

560
		// remove all webgl properties
561
		properties.delete( texture );
562

563
	}
M
Mr.doob 已提交
564

565
	function deallocateRenderTarget( renderTarget ) {
M
Mr.doob 已提交
566

567
		var renderTargetProperties = properties.get( renderTarget );
M
Mr.doob 已提交
568
		var textureProperties = properties.get( renderTarget.texture );
M
Mr.doob 已提交
569

M
Mr.doob 已提交
570
		if ( ! renderTarget || textureProperties.__webglTexture === undefined ) return;
M
Mr.doob 已提交
571

M
Mr.doob 已提交
572
		_gl.deleteTexture( textureProperties.__webglTexture );
M
Mr.doob 已提交
573

M
Mr.doob 已提交
574 575 576 577
		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {

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

578
				_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );
579
				_gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );
M
Mr.doob 已提交
580 581 582 583 584

			}

		} else {

585
			_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
586
			_gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
M
Mr.doob 已提交
587 588 589

		}

M
Mr.doob 已提交
590
		properties.delete( renderTarget.texture );
D
Daosheng Mu 已提交
591
		properties.delete( renderTarget );
M
Mr.doob 已提交
592

593
	}
M
Mr.doob 已提交
594

595
	function deallocateMaterial( material ) {
M
Mr.doob 已提交
596

597 598 599 600
		releaseMaterialProgramReference( material );

		properties.delete( material );

601
	}
602 603


604
	function releaseMaterialProgramReference( material ) {
605

606
		var programInfo = properties.get( material ).program;
M
Mr.doob 已提交
607 608 609

		material.program = undefined;

610
		if ( programInfo !== undefined ) {
M
Mr.doob 已提交
611

612
			programCache.releaseProgram( programInfo );
M
Mr.doob 已提交
613

M
Mr.doob 已提交
614 615
		}

616
	}
M
Mr.doob 已提交
617 618 619 620 621

	// Buffer rendering

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

622
		state.initAttributes();
623

624
		var buffers = properties.get( object );
625

626 627 628 629
		if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();
		if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();
		if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
		if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
M
Mr.doob 已提交
630

631
		var attributes = program.getAttributes();
632

M
Mr.doob 已提交
633 634
		if ( object.hasPositions ) {

635
			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
M
Mr.doob 已提交
636
			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
637

638 639
			state.enableAttribute( attributes.position );
			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
640 641 642 643 644

		}

		if ( object.hasNormals ) {

645
			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );
M
Mr.doob 已提交
646

647
			if ( material.type !== 'MeshPhongMaterial' && material.type !== 'MeshStandardMaterial' && material.shading === THREE.FlatShading ) {
M
Mr.doob 已提交
648

649
				for ( var i = 0, l = object.count * 3; i < l; i += 9 ) {
M
Mr.doob 已提交
650

651
					var array = object.normalArray;
M
Mr.doob 已提交
652

653 654 655
					var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3;
					var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3;
					var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3;
M
Mr.doob 已提交
656

657 658 659
					array[ i + 0 ] = nx;
					array[ i + 1 ] = ny;
					array[ i + 2 ] = nz;
M
Mr.doob 已提交
660

661 662 663
					array[ i + 3 ] = nx;
					array[ i + 4 ] = ny;
					array[ i + 5 ] = nz;
M
Mr.doob 已提交
664

665 666 667
					array[ i + 6 ] = nx;
					array[ i + 7 ] = ny;
					array[ i + 8 ] = nz;
M
Mr.doob 已提交
668 669 670 671 672 673

				}

			}

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

675
			state.enableAttribute( attributes.normal );
676

677
			_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
678 679 680 681 682

		}

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

683
			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
M
Mr.doob 已提交
684
			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
685

686
			state.enableAttribute( attributes.uv );
687

688
			_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
689 690 691 692 693

		}

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

694
			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
M
Mr.doob 已提交
695
			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
696

697
			state.enableAttribute( attributes.color );
698

699
			_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
M
Mr.doob 已提交
700 701 702

		}

703
		state.disableUnusedAttributes();
704

M
Mr.doob 已提交
705 706 707 708 709 710
		_gl.drawArrays( _gl.TRIANGLES, 0, object.count );

		object.count = 0;

	};

711
	this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
712

M
Mr.doob 已提交
713 714
		setMaterial( material );

715
		var program = setProgram( camera, fog, material, object );
M
Mr.doob 已提交
716

M
Mr.doob 已提交
717 718
		var updateBuffers = false;
		var geometryProgram = geometry.id + '_' + program.id + '_' + material.wireframe;
M
Mr.doob 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741

		if ( geometryProgram !== _currentGeometryProgram ) {

			_currentGeometryProgram = geometryProgram;
			updateBuffers = true;

		}

		// morph targets

		var morphTargetInfluences = object.morphTargetInfluences;

		if ( morphTargetInfluences !== undefined ) {

			var activeInfluences = [];

			for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) {

				var influence = morphTargetInfluences[ i ];
				activeInfluences.push( [ influence, i ] );

			}

742
			activeInfluences.sort( absNumericalSort );
M
Mr.doob 已提交
743 744 745 746 747 748 749

			if ( activeInfluences.length > 8 ) {

				activeInfluences.length = 8;

			}

750 751
			var morphAttributes = geometry.morphAttributes;

M
Mr.doob 已提交
752 753 754 755 756 757 758
			for ( var i = 0, l = activeInfluences.length; i < l; i ++ ) {

				var influence = activeInfluences[ i ];
				morphInfluences[ i ] = influence[ 0 ];

				if ( influence[ 0 ] !== 0 ) {

759
					var index = influence[ 1 ];
M
Mr.doob 已提交
760

761 762
					if ( material.morphTargets === true && morphAttributes.position ) geometry.addAttribute( 'morphTarget' + i, morphAttributes.position[ index ] );
					if ( material.morphNormals === true && morphAttributes.normal ) geometry.addAttribute( 'morphNormal' + i, morphAttributes.normal[ index ] );
M
Mr.doob 已提交
763 764 765

				} else {

766 767
					if ( material.morphTargets === true ) geometry.removeAttribute( 'morphTarget' + i );
					if ( material.morphNormals === true ) geometry.removeAttribute( 'morphNormal' + i );
M
Mr.doob 已提交
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784

				}

			}

			var uniforms = program.getUniforms();

			if ( uniforms.morphTargetInfluences !== null ) {

				_gl.uniform1fv( uniforms.morphTargetInfluences, morphInfluences );

			}

			updateBuffers = true;

		}

M
Mr.doob 已提交
785 786
		//

787
		var index = geometry.index;
788 789
		var position = geometry.attributes.position;

790 791
		if ( material.wireframe === true ) {

792
			index = objects.getWireframeAttribute( geometry );
793 794 795

		}

796 797
		var renderer;

798
		if ( index !== null ) {
799

800 801
			renderer = indexedBufferRenderer;
			renderer.setIndex( index );
802

803
		} else {
804

805
			renderer = bufferRenderer;
806

807
		}
M
Mr.doob 已提交
808

809
		if ( updateBuffers ) {
M
Mr.doob 已提交
810

811
			setupVertexAttributes( material, program, geometry );
M
Mr.doob 已提交
812

813
			if ( index !== null ) {
814

815
				_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, objects.getAttributeBuffer( index ) );
816 817 818

			}

819
		}
820

M
Mr.doob 已提交
821
		//
822

M
Mr.doob 已提交
823 824
		var dataStart = 0;
		var dataCount = Infinity;
825

M
Mr.doob 已提交
826
		if ( index !== null ) {
827

M
Mr.doob 已提交
828
			dataCount = index.count
829

M
Mr.doob 已提交
830
		} else if ( position !== undefined ) {
831

M
Mr.doob 已提交
832
			dataCount = position.count;
833

M
Mr.doob 已提交
834
		}
835

M
Mr.doob 已提交
836 837
		var rangeStart = geometry.drawRange.start;
		var rangeCount = geometry.drawRange.count;
838

M
Mr.doob 已提交
839 840
		var groupStart = group !== null ? group.start : 0;
		var groupCount = group !== null ? group.count : Infinity;
841

M
Mr.doob 已提交
842 843 844 845 846 847
		var drawStart = Math.max( dataStart, rangeStart, groupStart );
		var drawEnd = Math.min( dataStart + dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;

		var drawCount = Math.max( 0, drawEnd - drawStart + 1 );

		//
848

849
		if ( object instanceof THREE.Mesh ) {
850

851
			if ( material.wireframe === true ) {
852

853
				state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
854
				renderer.setMode( _gl.LINES );
855

856
			} else {
M
Mr.doob 已提交
857 858

				switch ( object.drawMode ) {
859

B
Ben Adams 已提交
860 861 862 863 864 865 866 867 868 869 870 871 872
					case THREE.TrianglesDrawMode:
						renderer.setMode( _gl.TRIANGLES );
						break;

					case THREE.TriangleStripDrawMode:
						renderer.setMode( _gl.TRIANGLE_STRIP );
						break;

					case THREE.TriangleFanDrawMode:
						renderer.setMode( _gl.TRIANGLE_FAN );
						break;

				}
873

874
			}
875

876

877
		} else if ( object instanceof THREE.Line ) {
878

879
			var lineWidth = material.linewidth;
880

881
			if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material
882

883
			state.setLineWidth( lineWidth * getTargetPixelRatio() );
884

885
			if ( object instanceof THREE.LineSegments ) {
886

887
				renderer.setMode( _gl.LINES );
888

889
			} else {
890

891
				renderer.setMode( _gl.LINE_STRIP );
892 893

			}
M
Mr.doob 已提交
894

895
		} else if ( object instanceof THREE.Points ) {
896 897

			renderer.setMode( _gl.POINTS );
898 899

		}
900

901 902 903 904 905 906
		if ( geometry instanceof THREE.InstancedBufferGeometry && geometry.maxInstancedCount > 0 ) {

			renderer.renderInstances( geometry, drawStart, drawCount );

		} else {

M
Mr.doob 已提交
907
			renderer.render( drawStart, drawCount );
908

M
Mr.doob 已提交
909 910 911 912
		}

	};

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

M
Mr.doob 已提交
915
		var extension;
B
Ben Adams 已提交
916

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

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

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

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

M
Mr.doob 已提交
926 927 928
			}

		}
B
Ben Adams 已提交
929

930 931
		if ( startIndex === undefined ) startIndex = 0;

932 933
		state.initAttributes();

934
		var geometryAttributes = geometry.attributes;
935

936
		var programAttributes = program.getAttributes();
937

938
		var materialDefaultAttributeValues = material.defaultAttributeValues;
939

940
		for ( var name in programAttributes ) {
941

942
			var programAttribute = programAttributes[ name ];
M
Mr.doob 已提交
943

M
Mr.doob 已提交
944
			if ( programAttribute >= 0 ) {
M
Mr.doob 已提交
945

946
				var geometryAttribute = geometryAttributes[ name ];
947

M
Mr.doob 已提交
948
				if ( geometryAttribute !== undefined ) {
M
Mr.doob 已提交
949

950
					var size = geometryAttribute.itemSize;
G
gero3 已提交
951
					var buffer = objects.getAttributeBuffer( geometryAttribute );
952

B
Ben Adams 已提交
953
					if ( geometryAttribute instanceof THREE.InterleavedBufferAttribute ) {
954

M
Mr.doob 已提交
955 956 957 958 959
						var data = geometryAttribute.data;
						var stride = data.stride;
						var offset = geometryAttribute.offset;

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

M
Mr.doob 已提交
961
							state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute, extension );
B
Ben Adams 已提交
962

M
Mr.doob 已提交
963
							if ( geometry.maxInstancedCount === undefined ) {
964

D
dubejf 已提交
965
								geometry.maxInstancedCount = data.meshPerAttribute * data.count;
B
Ben Adams 已提交
966

M
Mr.doob 已提交
967
							}
B
Ben Adams 已提交
968

M
Mr.doob 已提交
969
						} else {
B
Ben Adams 已提交
970

M
Mr.doob 已提交
971
							state.enableAttribute( programAttribute );
B
Ben Adams 已提交
972

M
Mr.doob 已提交
973
						}
B
Ben Adams 已提交
974

M
Mr.doob 已提交
975 976
						_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, stride * data.array.BYTES_PER_ELEMENT, ( startIndex * stride + offset ) * data.array.BYTES_PER_ELEMENT );
B
Ben Adams 已提交
977

M
Mr.doob 已提交
978
					} else {
B
Ben Adams 已提交
979

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

M
Mr.doob 已提交
982
							state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute, extension );
B
Ben Adams 已提交
983

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

D
dubejf 已提交
986
								geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
B
Ben Adams 已提交
987

M
Mr.doob 已提交
988
							}
B
Ben Adams 已提交
989

M
Mr.doob 已提交
990 991 992 993
						} else {

							state.enableAttribute( programAttribute );

M
Mr.doob 已提交
994
						}
B
Ben Adams 已提交
995

M
Mr.doob 已提交
996 997 998
						_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
						_gl.vertexAttribPointer( programAttribute, size, _gl.FLOAT, false, 0, startIndex * size * 4 ); // 4 bytes per Float32

B
Ben Adams 已提交
999
					}
M
Mr.doob 已提交
1000

1001 1002
				} else if ( materialDefaultAttributeValues !== undefined ) {

T
tschw 已提交
1003
					var value = materialDefaultAttributeValues[ name ];
1004

1005
					if ( value !== undefined ) {
M
Mr.doob 已提交
1006

1007
						switch ( value.length ) {
M
Mr.doob 已提交
1008

1009 1010 1011
							case 2:
								_gl.vertexAttrib2fv( programAttribute, value );
								break;
M
Mr.doob 已提交
1012

1013 1014 1015
							case 3:
								_gl.vertexAttrib3fv( programAttribute, value );
								break;
M
Mr.doob 已提交
1016

1017 1018 1019
							case 4:
								_gl.vertexAttrib4fv( programAttribute, value );
								break;
1020

1021 1022
							default:
								_gl.vertexAttrib1fv( programAttribute, value );
1023 1024

						}
M
Mr.doob 已提交
1025 1026 1027 1028 1029 1030 1031 1032

					}

				}

			}

		}
1033

1034
		state.disableUnusedAttributes();
1035

M
Mr.doob 已提交
1036 1037
	}

M
Mr.doob 已提交
1038 1039
	// Sorting

1040
	function absNumericalSort( a, b ) {
1041

1042
		return Math.abs( b[ 0 ] ) - Math.abs( a[ 0 ] );
1043 1044 1045

	}

M
Mr.doob 已提交
1046 1047
	function painterSortStable ( a, b ) {

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

U
unconed 已提交
1050
			return a.object.renderOrder - b.object.renderOrder;
1051

M
Mr.doob 已提交
1052
		} else if ( a.material.id !== b.material.id ) {
M
Mr.doob 已提交
1053

M
Mr.doob 已提交
1054
			return a.material.id - b.material.id;
1055 1056

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

M
Mr.doob 已提交
1058
			return a.z - b.z;
M
Mr.doob 已提交
1059 1060 1061

		} else {

1062
			return a.id - b.id;
M
Mr.doob 已提交
1063 1064 1065

		}

1066
	}
M
Mr.doob 已提交
1067

1068 1069
	function reversePainterSortStable ( a, b ) {

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

U
unconed 已提交
1072
			return a.object.renderOrder - b.object.renderOrder;
1073 1074

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

M
Mr.doob 已提交
1076
			return b.z - a.z;
1077 1078 1079 1080 1081 1082 1083

		} else {

			return a.id - b.id;

		}

1084
	}
1085

M
Mr.doob 已提交
1086 1087 1088 1089 1090 1091
	// Rendering

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

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

1092
			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
M
Mr.doob 已提交
1093 1094 1095 1096
			return;

		}

M
Mr.doob 已提交
1097
		var fog = scene.fog;
M
Mr.doob 已提交
1098 1099 1100

		// reset caching for this frame

1101
		_currentGeometryProgram = '';
1102
		_currentMaterialId = - 1;
1103
		_currentCamera = null;
M
Mr.doob 已提交
1104 1105 1106

		// update scene graph

1107
		if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
M
Mr.doob 已提交
1108 1109 1110

		// update camera matrices and frustum

1111
		if ( camera.parent === null ) camera.updateMatrixWorld();
M
Mr.doob 已提交
1112 1113 1114 1115 1116 1117

		camera.matrixWorldInverse.getInverse( camera.matrixWorld );

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

M
Mr.doob 已提交
1118
		lights.length = 0;
1119

M
Mr.doob 已提交
1120 1121
		opaqueObjectsLastIndex = - 1;
		transparentObjectsLastIndex = - 1;
1122

M
Mr.doob 已提交
1123 1124 1125
		sprites.length = 0;
		lensFlares.length = 0;

1126
		projectObject( scene, camera );
M
Mr.doob 已提交
1127

1128 1129 1130
		opaqueObjects.length = opaqueObjectsLastIndex + 1;
		transparentObjects.length = transparentObjectsLastIndex + 1;

M
Mr.doob 已提交
1131
		if ( _this.sortObjects === true ) {
1132 1133 1134

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

1136 1137
		}

1138 1139
		setupLights( lights, camera );

M
Mr.doob 已提交
1140
		//
M
Mr.doob 已提交
1141

M
Mr.doob 已提交
1142
		shadowMap.render( scene, camera );
M
Mr.doob 已提交
1143 1144 1145

		//

1146 1147 1148 1149
		_infoRender.calls = 0;
		_infoRender.vertices = 0;
		_infoRender.faces = 0;
		_infoRender.points = 0;
M
Mr.doob 已提交
1150 1151 1152 1153 1154 1155 1156 1157 1158

		this.setRenderTarget( renderTarget );

		if ( this.autoClear || forceClear ) {

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

		}

1159
		//
M
Mr.doob 已提交
1160 1161 1162

		if ( scene.overrideMaterial ) {

1163
			var overrideMaterial = scene.overrideMaterial;
M
Mr.doob 已提交
1164

1165 1166
			renderObjects( opaqueObjects, camera, fog, overrideMaterial );
			renderObjects( transparentObjects, camera, fog, overrideMaterial );
1167

M
Mr.doob 已提交
1168 1169 1170 1171
		} else {

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

M
Mr.doob 已提交
1172
			state.setBlending( THREE.NoBlending );
1173
			renderObjects( opaqueObjects, camera, fog );
M
Mr.doob 已提交
1174 1175 1176

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

1177
			renderObjects( transparentObjects, camera, fog );
M
Mr.doob 已提交
1178 1179 1180 1181 1182

		}

		// custom render plugins (post pass)

M
Mr.doob 已提交
1183 1184
		spritePlugin.render( scene, camera );
		lensFlarePlugin.render( scene, camera, _currentWidth, _currentHeight );
M
Mr.doob 已提交
1185 1186 1187

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

M
Mr.doob 已提交
1188 1189 1190
		if ( renderTarget ) {

			var texture = renderTarget.texture;
M
Mr.doob 已提交
1191

M
Mr.doob 已提交
1192 1193 1194 1195 1196
			if ( texture.generateMipmaps && isPowerOfTwo( renderTarget ) &&
					texture.minFilter !== THREE.NearestFilter &&
					texture.minFilter !== THREE.LinearFilter ) {

				updateRenderTargetMipmap( renderTarget );
M
Mr.doob 已提交
1197 1198

			}
M
Mr.doob 已提交
1199 1200 1201 1202 1203

		}

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

M
Mr.doob 已提交
1204 1205
		state.setDepthTest( true );
		state.setDepthWrite( true );
1206
		state.setColorWrite( true );
M
Mr.doob 已提交
1207 1208 1209 1210

		// _gl.finish();

	};
M
Mr.doob 已提交
1211

M
Mr.doob 已提交
1212 1213
	function pushRenderItem( object, geometry, material, z, group ) {

1214
		var array, index;
M
Mr.doob 已提交
1215

1216
		// allocate the next position in the appropriate array
M
Mr.doob 已提交
1217 1218 1219

		if ( material.transparent ) {

1220 1221
			array = transparentObjects;
			index = ++ transparentObjectsLastIndex;
M
Mr.doob 已提交
1222 1223 1224

		} else {

1225 1226 1227 1228 1229
			array = opaqueObjects;
			index = ++ opaqueObjectsLastIndex;

		}

1230 1231
		// recycle existing render item or grow the array

1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
		var renderItem = array[ index ];

		if ( renderItem !== undefined ) {

			renderItem.id = object.id;
			renderItem.object = object;
			renderItem.geometry = geometry;
			renderItem.material = material;
			renderItem.z = _vector3.z;
			renderItem.group = group;
M
Mr.doob 已提交
1242 1243 1244

		} else {

1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255
			renderItem = {
				id: object.id,
				object: object,
				geometry: geometry,
				material: material,
				z: _vector3.z,
				group: group
			};

			// assert( index === array.length );
			array.push( renderItem );
M
Mr.doob 已提交
1256 1257 1258 1259 1260

		}

	}

1261
	function projectObject( object, camera ) {
M
Mr.doob 已提交
1262

M
Mr.doob 已提交
1263
		if ( object.visible === false ) return;
M
Mr.doob 已提交
1264

1265
		if ( object.layers.test( camera.layers ) ) {
M
Mr.doob 已提交
1266

1267
			if ( object instanceof THREE.Light ) {
M
Mr.doob 已提交
1268

1269
				lights.push( object );
M
Mr.doob 已提交
1270

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

1273 1274 1275 1276 1277
				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {

					sprites.push( object );

				}
M
Mr.doob 已提交
1278

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

1281
				lensFlares.push( object );
M
Mr.doob 已提交
1282

1283
			} else if ( object instanceof THREE.ImmediateRenderObject ) {
M
Mr.doob 已提交
1284

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

1287 1288
					_vector3.setFromMatrixPosition( object.matrixWorld );
					_vector3.applyProjection( _projScreenMatrix );
M
Mr.doob 已提交
1289

1290
				}
1291

1292
				pushRenderItem( object, null, object.material, _vector3.z, null );
M
Mr.doob 已提交
1293

1294
			} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points ) {
M
Mr.doob 已提交
1295

1296
				if ( object instanceof THREE.SkinnedMesh ) {
M
Mr.doob 已提交
1297

1298
					object.skeleton.update();
1299

1300
				}
1301

1302
				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
1303

1304
					var material = object.material;
1305

1306
					if ( material.visible === true ) {
M
Mr.doob 已提交
1307

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

1310 1311 1312 1313
							_vector3.setFromMatrixPosition( object.matrixWorld );
							_vector3.applyProjection( _projScreenMatrix );

						}
M
Mr.doob 已提交
1314

1315
						var geometry = objects.update( object );
M
Mr.doob 已提交
1316

S
SUNAG 已提交
1317
						if ( material instanceof THREE.MultiMaterial ) {
1318

1319 1320
							var groups = geometry.groups;
							var materials = material.materials;
1321

1322
							for ( var i = 0, l = groups.length; i < l; i ++ ) {
1323

1324 1325
								var group = groups[ i ];
								var groupMaterial = materials[ group.materialIndex ];
1326

1327
								if ( groupMaterial.visible === true ) {
1328

1329 1330 1331
									pushRenderItem( object, geometry, groupMaterial, _vector3.z, group );

								}
M
Mr.doob 已提交
1332

M
Mr.doob 已提交
1333
							}
M
Mr.doob 已提交
1334

1335
						} else {
M
Mr.doob 已提交
1336

1337
							pushRenderItem( object, geometry, material, _vector3.z, null );
1338

1339
						}
O
OpenShift guest 已提交
1340

1341
					}
M
Mr.doob 已提交
1342

1343
				}
M
Mr.doob 已提交
1344

1345
			}
M
Mr.doob 已提交
1346

M
Mr.doob 已提交
1347
		}
M
Mr.doob 已提交
1348

M
Mr.doob 已提交
1349
		var children = object.children;
M
Mr.doob 已提交
1350

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

1353
			projectObject( children[ i ], camera );
M
Mr.doob 已提交
1354

1355
		}
1356

1357
	}
M
Mr.doob 已提交
1358

1359
	function renderObjects( renderList, camera, fog, overrideMaterial ) {
M
Mr.doob 已提交
1360

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

1363
			var renderItem = renderList[ i ];
M
Mr.doob 已提交
1364

1365
			var object = renderItem.object;
M
Mr.doob 已提交
1366 1367 1368
			var geometry = renderItem.geometry;
			var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
			var group = renderItem.group;
M
Mr.doob 已提交
1369

1370 1371
			object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
			object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
M
Mr.doob 已提交
1372

M
Mr.doob 已提交
1373
			if ( object instanceof THREE.ImmediateRenderObject ) {
M
Mr.doob 已提交
1374

M
Mr.doob 已提交
1375
				setMaterial( material );
M
Mr.doob 已提交
1376

1377
				var program = setProgram( camera, fog, material, object );
M
Mr.doob 已提交
1378

M
Mr.doob 已提交
1379
				_currentGeometryProgram = '';
M
Mr.doob 已提交
1380

M
Mr.doob 已提交
1381
				object.render( function ( object ) {
M
Mr.doob 已提交
1382

M
Mr.doob 已提交
1383
					_this.renderBufferImmediate( object, program, material );
M
Mr.doob 已提交
1384

M
Mr.doob 已提交
1385
				} );
1386

M
Mr.doob 已提交
1387
			} else {
M
Mr.doob 已提交
1388

1389
				_this.renderBufferDirect( camera, fog, geometry, material, object, group );
M
Mr.doob 已提交
1390

M
Mr.doob 已提交
1391
			}
M
Mr.doob 已提交
1392

1393
		}
M
Mr.doob 已提交
1394

1395
	}
G
gero3 已提交
1396

1397
	function initMaterial( material, fog, object ) {
M
Mr.doob 已提交
1398

1399
		var materialProperties = properties.get( material );
G
gero3 已提交
1400

1401
		var parameters = programCache.getParameters( material, _lights, fog, object );
G
gero3 已提交
1402
		var code = programCache.getProgramCode( material, parameters );
G
gero3 已提交
1403

1404
		var program = materialProperties.program;
T
tschw 已提交
1405
		var programChange = true;
1406

1407
		if ( program === undefined ) {
B
Ben Adams 已提交
1408

M
Mr.doob 已提交
1409 1410
			// new material
			material.addEventListener( 'dispose', onMaterialDispose );
B
Ben Adams 已提交
1411

1412
		} else if ( program.code !== code ) {
B
Ben Adams 已提交
1413

M
Mr.doob 已提交
1414
			// changed glsl or parameters
1415
			releaseMaterialProgramReference( material );
B
Ben Adams 已提交
1416

G
gero3 已提交
1417
		} else if ( parameters.shaderID !== undefined ) {
B
Ben Adams 已提交
1418

T
tschw 已提交
1419
			// same glsl and uniform list
T
tschw 已提交
1420 1421
			return;

T
tschw 已提交
1422
		} else {
B
Ben Adams 已提交
1423

T
tschw 已提交
1424 1425
			// only rebuild uniform list
			programChange = false;
B
Ben Adams 已提交
1426 1427 1428

		}

1429
		if ( programChange ) {
B
Ben Adams 已提交
1430

1431
			if ( parameters.shaderID ) {
B
Ben Adams 已提交
1432

1433
				var shader = THREE.ShaderLib[ parameters.shaderID ];
B
Ben Adams 已提交
1434

1435 1436 1437 1438 1439 1440
				materialProperties.__webglShader = {
					name: material.type,
					uniforms: THREE.UniformsUtils.clone( shader.uniforms ),
					vertexShader: shader.vertexShader,
					fragmentShader: shader.fragmentShader
				};
B
Ben Adams 已提交
1441

1442
			} else {
B
Ben Adams 已提交
1443

1444 1445 1446 1447 1448 1449
				materialProperties.__webglShader = {
					name: material.type,
					uniforms: material.uniforms,
					vertexShader: material.vertexShader,
					fragmentShader: material.fragmentShader
				};
G
gero3 已提交
1450

1451
			}
G
gero3 已提交
1452

1453
			material.__webglShader = materialProperties.__webglShader;
G
gero3 已提交
1454

1455
			program = programCache.acquireProgram( material, parameters, code );
B
Ben Adams 已提交
1456

1457 1458
			materialProperties.program = program;
			material.program = program;
1459 1460 1461

		}

1462
		var attributes = program.getAttributes();
M
Mr.doob 已提交
1463 1464 1465 1466 1467

		if ( material.morphTargets ) {

			material.numSupportedMorphTargets = 0;

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

M
Mr.doob 已提交
1470
				if ( attributes[ 'morphTarget' + i ] >= 0 ) {
M
Mr.doob 已提交
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483

					material.numSupportedMorphTargets ++;

				}

			}

		}

		if ( material.morphNormals ) {

			material.numSupportedMorphNormals = 0;

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

M
Mr.doob 已提交
1486
				if ( attributes[ 'morphNormal' + i ] >= 0 ) {
M
Mr.doob 已提交
1487 1488 1489 1490 1491 1492 1493 1494 1495

					material.numSupportedMorphNormals ++;

				}

			}

		}

1496
		materialProperties.uniformsList = [];
M
Mr.doob 已提交
1497

1498 1499
		var uniforms = materialProperties.__webglShader.uniforms,
			uniformLocations = materialProperties.program.getUniforms();
M
Mr.doob 已提交
1500

1501
		for ( var u in uniforms ) {
M
Mr.doob 已提交
1502

1503
			var location = uniformLocations[ u ];
1504 1505

			if ( location ) {
G
gero3 已提交
1506

1507
				materialProperties.uniformsList.push( [ materialProperties.__webglShader.uniforms[ u ], location ] );
G
gero3 已提交
1508

1509
			}
M
Mr.doob 已提交
1510 1511 1512

		}

1513 1514
		if ( material instanceof THREE.MeshPhongMaterial ||
				material instanceof THREE.MeshLambertMaterial ||
1515
				material instanceof THREE.MeshStandardMaterial ||
1516 1517
				material.lights ) {

1518 1519
			// store the light setup it was created for

1520 1521
			materialProperties.lightsHash = _lights.hash;

1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
			// wire up the material to this renderer's lighting state

			uniforms.ambientLightColor.value = _lights.ambient;
			uniforms.directionalLights.value = _lights.directional;
			uniforms.pointLights.value = _lights.point;
			uniforms.spotLights.value = _lights.spot;
			uniforms.hemisphereLights.value = _lights.hemi;

		}

A
arose 已提交
1532 1533 1534 1535 1536 1537 1538 1539
		// detect dynamic uniforms

		materialProperties.hasDynamicUniforms = false;

		for ( var j = 0, jl = materialProperties.uniformsList.length; j < jl; j ++ ) {

			var uniform = materialProperties.uniformsList[ j ][ 0 ];

1540
			if ( uniform.dynamic === true ) {
A
arose 已提交
1541 1542 1543 1544 1545 1546 1547 1548

				materialProperties.hasDynamicUniforms = true;
				break;

			}

		}

M
Mr.doob 已提交
1549
	}
M
Mr.doob 已提交
1550

1551 1552
	function setMaterial( material ) {

M
Mr.doob 已提交
1553 1554
		setMaterialFaces( material );

1555 1556
		if ( material.transparent === true ) {

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

1559 1560 1561 1562
		} else {

			state.setBlending( THREE.NoBlending );

1563 1564
		}

B
Ben Adams 已提交
1565
		state.setDepthFunc( material.depthFunc );
M
Mr.doob 已提交
1566 1567
		state.setDepthTest( material.depthTest );
		state.setDepthWrite( material.depthWrite );
1568
		state.setColorWrite( material.colorWrite );
M
Mr.doob 已提交
1569
		state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
1570 1571 1572

	}

M
Mr.doob 已提交
1573 1574
	function setMaterialFaces( material ) {

1575
		material.side !== THREE.DoubleSide ? state.enable( _gl.CULL_FACE ) : state.disable( _gl.CULL_FACE );
M
Mr.doob 已提交
1576 1577 1578 1579
		state.setFlipSided( material.side === THREE.BackSide );

	}

1580
	function setProgram( camera, fog, material, object ) {
M
Mr.doob 已提交
1581 1582 1583

		_usedTextureUnits = 0;

1584
		var materialProperties = properties.get( material );
1585

1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599
		if ( materialProperties.program === undefined ) {

			material.needsUpdate = true;

		}

		if ( materialProperties.lightsHash !== undefined &&
			materialProperties.lightsHash !== _lights.hash ) {

			material.needsUpdate = true;

		}

		if ( material.needsUpdate ) {
M
Mr.doob 已提交
1600

1601
			initMaterial( material, fog, object );
M
Mr.doob 已提交
1602 1603 1604 1605
			material.needsUpdate = false;

		}

1606
		var refreshProgram = false;
M
Mr.doob 已提交
1607
		var refreshMaterial = false;
1608
		var refreshLights = false;
M
Mr.doob 已提交
1609

1610
		var program = materialProperties.program,
1611
			p_uniforms = program.getUniforms(),
1612
			m_uniforms = materialProperties.__webglShader.uniforms;
M
Mr.doob 已提交
1613

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

1616 1617
			_gl.useProgram( program.program );
			_currentProgram = program.id;
M
Mr.doob 已提交
1618

1619
			refreshProgram = true;
M
Mr.doob 已提交
1620
			refreshMaterial = true;
1621
			refreshLights = true;
M
Mr.doob 已提交
1622 1623 1624 1625 1626 1627

		}

		if ( material.id !== _currentMaterialId ) {

			_currentMaterialId = material.id;
1628

M
Mr.doob 已提交
1629 1630 1631 1632
			refreshMaterial = true;

		}

1633
		if ( refreshProgram || camera !== _currentCamera ) {
M
Mr.doob 已提交
1634 1635 1636

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

G
gero3 已提交
1637
			if ( capabilities.logarithmicDepthBuffer ) {
1638

1639
				_gl.uniform1f( p_uniforms.logDepthBufFC, 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );
1640 1641 1642 1643

			}


1644 1645 1646 1647 1648 1649 1650 1651 1652
			if ( camera !== _currentCamera ) {

				_currentCamera = camera;

				// lighting uniforms depend on the camera so enforce an update
				// now, in case this material supports lights - or later, when
				// the next material that does gets activated:

				refreshMaterial = true;		// set to true on material change
T
tschw 已提交
1653
				refreshLights = true;		// remains set until update done
1654 1655

			}
M
Mr.doob 已提交
1656

1657 1658 1659 1660 1661
			// load material specific uniforms
			// (shader material also gets them for the sake of genericity)

			if ( material instanceof THREE.ShaderMaterial ||
				 material instanceof THREE.MeshPhongMaterial ||
1662
				 material instanceof THREE.MeshStandardMaterial ||
1663 1664
				 material.envMap ) {

1665
				if ( p_uniforms.cameraPosition !== undefined ) {
1666 1667 1668 1669 1670 1671 1672 1673 1674 1675

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

				}

			}

			if ( material instanceof THREE.MeshPhongMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
1676
				 material instanceof THREE.MeshBasicMaterial ||
1677
				 material instanceof THREE.MeshStandardMaterial ||
1678 1679 1680
				 material instanceof THREE.ShaderMaterial ||
				 material.skinning ) {

1681
				if ( p_uniforms.viewMatrix !== undefined ) {
1682 1683

					_gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera.matrixWorldInverse.elements );
M
Mr.doob 已提交
1684

1685 1686 1687 1688
				}

			}

M
Mr.doob 已提交
1689 1690 1691 1692 1693 1694 1695 1696
		}

		// 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 ) {

1697
			if ( object.bindMatrix && p_uniforms.bindMatrix !== undefined ) {
1698 1699 1700 1701 1702

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

			}

1703
			if ( object.bindMatrixInverse && p_uniforms.bindMatrixInverse !== undefined ) {
1704 1705 1706 1707 1708

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

			}

1709
			if ( capabilities.floatVertexTextures && object.skeleton && object.skeleton.useVertexTexture ) {
M
Mr.doob 已提交
1710

1711
				if ( p_uniforms.boneTexture !== undefined ) {
M
Mr.doob 已提交
1712 1713 1714 1715

					var textureUnit = getTextureUnit();

					_gl.uniform1i( p_uniforms.boneTexture, textureUnit );
1716
					_this.setTexture( object.skeleton.boneTexture, textureUnit );
M
Mr.doob 已提交
1717 1718 1719

				}

1720
				if ( p_uniforms.boneTextureWidth !== undefined ) {
1721

1722
					_gl.uniform1i( p_uniforms.boneTextureWidth, object.skeleton.boneTextureWidth );
1723 1724 1725

				}

1726
				if ( p_uniforms.boneTextureHeight !== undefined ) {
1727

1728
					_gl.uniform1i( p_uniforms.boneTextureHeight, object.skeleton.boneTextureHeight );
1729 1730 1731

				}

1732
			} else if ( object.skeleton && object.skeleton.boneMatrices ) {
M
Mr.doob 已提交
1733

1734
				if ( p_uniforms.boneGlobalMatrices !== undefined ) {
M
Mr.doob 已提交
1735

1736
					_gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.skeleton.boneMatrices );
M
Mr.doob 已提交
1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747

				}

			}

		}

		if ( refreshMaterial ) {

			if ( material instanceof THREE.MeshPhongMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
1748
				 material instanceof THREE.MeshStandardMaterial ||
M
Mr.doob 已提交
1749 1750
				 material.lights ) {

1751
				// the current material requires lighting info
M
Mr.doob 已提交
1752

T
tschw 已提交
1753 1754 1755 1756 1757 1758
				// note: all lighting uniforms are always set correctly
				// they simply reference the renderer's state for their
				// values
				//
				// use the current material's .needsUpdate flags to set
				// the GL state when required
M
Mr.doob 已提交
1759

T
tschw 已提交
1760
				markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
G
gero3 已提交
1761

T
tschw 已提交
1762
			}
G
gero3 已提交
1763

T
tschw 已提交
1764
			// refresh uniforms common to several materials
G
gero3 已提交
1765

T
tschw 已提交
1766
			if ( fog && material.fog ) {
G
gero3 已提交
1767

T
tschw 已提交
1768
				refreshUniformsFog( m_uniforms, fog );
M
Mr.doob 已提交
1769 1770 1771 1772 1773

			}

			if ( material instanceof THREE.MeshBasicMaterial ||
				 material instanceof THREE.MeshLambertMaterial ||
W
WestLangley 已提交
1774
				 material instanceof THREE.MeshPhongMaterial ||
1775
				 material instanceof THREE.MeshStandardMaterial ) {
M
Mr.doob 已提交
1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791

				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 );

1792
			} else if ( material instanceof THREE.PointsMaterial ) {
M
Mr.doob 已提交
1793

M
Mr.doob 已提交
1794
				refreshUniformsPoints( m_uniforms, material );
M
Mr.doob 已提交
1795 1796 1797 1798 1799

			} else if ( material instanceof THREE.MeshPhongMaterial ) {

				refreshUniformsPhong( m_uniforms, material );

1800
			} else if ( material instanceof THREE.MeshStandardMaterial ) {
W
WestLangley 已提交
1801

1802
				refreshUniformsStandard( m_uniforms, material );
W
WestLangley 已提交
1803

M
Mr.doob 已提交
1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
			} 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;

			}

M
Mr.doob 已提交
1816
			if ( shadowMap.enabled ) {
M
Mr.doob 已提交
1817

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

1820
					refreshUniformsShadow( m_uniforms, camera );
1821 1822

				}
M
Mr.doob 已提交
1823 1824 1825 1826 1827

			}

			// load common uniforms

1828
			loadUniformsGeneric( materialProperties.uniformsList );
M
Mr.doob 已提交
1829 1830 1831 1832 1833

		}

		loadUniformsMatrices( p_uniforms, object );

1834
		if ( p_uniforms.modelMatrix !== undefined ) {
M
Mr.doob 已提交
1835 1836

			_gl.uniformMatrix4fv( p_uniforms.modelMatrix, false, object.matrixWorld.elements );
M
Mr.doob 已提交
1837

M
Mr.doob 已提交
1838 1839
		}

1840
		if ( materialProperties.hasDynamicUniforms === true ) {
A
arose 已提交
1841

1842
			updateDynamicUniforms( materialProperties.uniformsList, object, camera );
A
arose 已提交
1843 1844 1845

		}

M
Mr.doob 已提交
1846 1847
		return program;

M
Mr.doob 已提交
1848
	}
M
Mr.doob 已提交
1849

1850
	function updateDynamicUniforms ( uniforms, object, camera ) {
A
arose 已提交
1851 1852 1853 1854 1855 1856

		var dynamicUniforms = [];

		for ( var j = 0, jl = uniforms.length; j < jl; j ++ ) {

			var uniform = uniforms[ j ][ 0 ];
1857
			var onUpdateCallback = uniform.onUpdateCallback;
A
arose 已提交
1858

1859
			if ( onUpdateCallback !== undefined ) {
A
arose 已提交
1860

1861
				onUpdateCallback.bind( uniform )( object, camera );
A
arose 已提交
1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
				dynamicUniforms.push( uniforms[ j ] );

			}

		}

		loadUniformsGeneric( dynamicUniforms );

	}

M
Mr.doob 已提交
1872 1873 1874 1875 1876 1877
	// Uniforms (refresh uniforms objects)

	function refreshUniformsCommon ( uniforms, material ) {

		uniforms.opacity.value = material.opacity;

1878
		uniforms.diffuse.value = material.color;
M
Mr.doob 已提交
1879

1880
		if ( material.emissive ) {
M
Mr.doob 已提交
1881

1882
			uniforms.emissive.value = material.emissive;
M
Mr.doob 已提交
1883 1884 1885

		}

1886 1887 1888
		uniforms.map.value = material.map;
		uniforms.specularMap.value = material.specularMap;
		uniforms.alphaMap.value = material.alphaMap;
M
Mr.doob 已提交
1889

1890
		if ( material.aoMap ) {
1891

1892 1893
			uniforms.aoMap.value = material.aoMap;
			uniforms.aoMapIntensity.value = material.aoMapIntensity;
1894 1895 1896

		}

M
Mr.doob 已提交
1897
		// uv repeat and offset setting priorities
M
Mr.doob 已提交
1898 1899 1900 1901 1902
		// 1. color map
		// 2. specular map
		// 3. normal map
		// 4. bump map
		// 5. alpha map
1903
		// 6. emissive map
M
Mr.doob 已提交
1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914

		var uvScaleMap;

		if ( material.map ) {

			uvScaleMap = material.map;

		} else if ( material.specularMap ) {

			uvScaleMap = material.specularMap;

1915 1916 1917 1918
		} else if ( material.displacementMap ) {

			uvScaleMap = material.displacementMap;

M
Mr.doob 已提交
1919 1920 1921 1922 1923 1924 1925 1926
		} else if ( material.normalMap ) {

			uvScaleMap = material.normalMap;

		} else if ( material.bumpMap ) {

			uvScaleMap = material.bumpMap;

1927 1928 1929 1930 1931 1932 1933 1934
		} else if ( material.roughnessMap ) {

			uvScaleMap = material.roughnessMap;

		} else if ( material.metalnessMap ) {

			uvScaleMap = material.metalnessMap;

1935 1936 1937 1938
		} else if ( material.alphaMap ) {

			uvScaleMap = material.alphaMap;

1939 1940 1941 1942
		} else if ( material.emissiveMap ) {

			uvScaleMap = material.emissiveMap;

M
Mr.doob 已提交
1943 1944 1945 1946
		}

		if ( uvScaleMap !== undefined ) {

M
Mr.doob 已提交
1947 1948 1949 1950 1951 1952
			if ( uvScaleMap instanceof THREE.WebGLRenderTarget ) {

				uvScaleMap = uvScaleMap.texture;

			}

M
Mr.doob 已提交
1953 1954 1955 1956 1957 1958 1959 1960
			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;
1961
		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : - 1;
M
Mr.doob 已提交
1962

1963
		uniforms.reflectivity.value = material.reflectivity;
M
Mr.doob 已提交
1964 1965
		uniforms.refractionRatio.value = material.refractionRatio;

M
Mr.doob 已提交
1966
	}
M
Mr.doob 已提交
1967 1968 1969 1970 1971 1972

	function refreshUniformsLine ( uniforms, material ) {

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

M
Mr.doob 已提交
1973
	}
M
Mr.doob 已提交
1974 1975 1976 1977 1978 1979 1980

	function refreshUniformsDash ( uniforms, material ) {

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

M
Mr.doob 已提交
1981
	}
M
Mr.doob 已提交
1982

M
Mr.doob 已提交
1983
	function refreshUniformsPoints ( uniforms, material ) {
M
Mr.doob 已提交
1984

1985
		uniforms.diffuse.value = material.color;
M
Mr.doob 已提交
1986
		uniforms.opacity.value = material.opacity;
1987
		uniforms.size.value = material.size * getTargetPixelRatio();
M
Mr.doob 已提交
1988 1989 1990 1991
		uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.

		uniforms.map.value = material.map;

1992 1993 1994 1995 1996 1997 1998 1999 2000
		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 已提交
2001
	}
M
Mr.doob 已提交
2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017

	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 已提交
2018
	}
M
Mr.doob 已提交
2019 2020 2021

	function refreshUniformsPhong ( uniforms, material ) {

2022
		uniforms.specular.value = material.specular;
M
Mr.doob 已提交
2023
		uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )
M
Mr.doob 已提交
2024

2025 2026 2027 2028
		if ( material.lightMap ) {

			uniforms.lightMap.value = material.lightMap;
			uniforms.lightMapIntensity.value = material.lightMapIntensity;
M
Mr.doob 已提交
2029

2030
		}
2031

2032
		if ( material.emissiveMap ) {
2033

2034
			uniforms.emissiveMap.value = material.emissiveMap;
2035

2036
		}
M
Mr.doob 已提交
2037

2038 2039 2040 2041
		if ( material.bumpMap ) {

			uniforms.bumpMap.value = material.bumpMap;
			uniforms.bumpScale.value = material.bumpScale;
M
Mr.doob 已提交
2042

2043
		}
M
Mr.doob 已提交
2044

2045 2046 2047 2048 2049 2050
		if ( material.normalMap ) {

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

		}
M
Mr.doob 已提交
2051

2052 2053 2054 2055 2056
		if ( material.displacementMap ) {

			uniforms.displacementMap.value = material.displacementMap;
			uniforms.displacementScale.value = material.displacementScale;
			uniforms.displacementBias.value = material.displacementBias;
2057

2058
		}
2059 2060 2061

	}

2062
	function refreshUniformsStandard ( uniforms, material ) {
W
WestLangley 已提交
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122

		uniforms.roughness.value = material.roughness;
		uniforms.metalness.value = material.metalness;

		if ( material.roughnessMap ) {

			uniforms.roughnessMap.value = material.roughnessMap;

		}

		if ( material.metalnessMap ) {

			uniforms.metalnessMap.value = material.metalnessMap;

		}

		if ( material.lightMap ) {

			uniforms.lightMap.value = material.lightMap;
			uniforms.lightMapIntensity.value = material.lightMapIntensity;

		}

		if ( material.emissiveMap ) {

			uniforms.emissiveMap.value = material.emissiveMap;

		}

		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 );

		}

		if ( material.displacementMap ) {

			uniforms.displacementMap.value = material.displacementMap;
			uniforms.displacementScale.value = material.displacementScale;
			uniforms.displacementBias.value = material.displacementBias;

		}

		if ( material.envMap ) {

			//uniforms.envMap.value = material.envMap; // part of uniforms common
			uniforms.envMapIntensity.value = material.envMapIntensity;

		}

	}

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

M
Mr.doob 已提交
2125
	function markUniformsLightsNeedsUpdate ( uniforms, value ) {
2126

M
Mr.doob 已提交
2127
		uniforms.ambientLightColor.needsUpdate = value;
2128

B
Ben Houston 已提交
2129 2130 2131 2132
		uniforms.directionalLights.needsUpdate = value;
		uniforms.pointLights.needsUpdate = value;
		uniforms.spotLights.needsUpdate = value;
		uniforms.hemisphereLights.needsUpdate = value;
2133

M
Mr.doob 已提交
2134
	}
2135

2136
	function refreshUniformsShadow ( uniforms, camera ) {
M
Mr.doob 已提交
2137 2138 2139

		if ( uniforms.shadowMatrix ) {

2140
			var shadows = _lights.shadows;
M
Mr.doob 已提交
2141

2142
			for ( var i = 0, l = shadows.length; i < l; i ++ ) {
M
Mr.doob 已提交
2143

2144
				var light = shadows[ i ];
2145
				var shadow = light.shadow;
M
Mr.doob 已提交
2146

2147
				if ( light instanceof THREE.PointLight ) {
M
Mr.doob 已提交
2148

2149 2150 2151 2152
					// for point lights we set the shadow matrix to be a translation-only matrix
					// equal to inverse of the light's position
					_vector3.setFromMatrixPosition( light.matrixWorld ).negate();
					shadow.matrix.identity().setPosition( _vector3 );
M
Mr.doob 已提交
2153

2154 2155
					// for point lights we set the sign of the shadowDarkness uniform to be negative
					uniforms.shadowDarkness.value[ i ] = - shadow.darkness;
M
Mr.doob 已提交
2156

2157
				} else {
M
Mr.doob 已提交
2158

2159
					uniforms.shadowDarkness.value[ i ] = shadow.darkness;
M
Mr.doob 已提交
2160 2161 2162

				}

2163 2164 2165 2166 2167
				uniforms.shadowBias.value[ i ] = shadow.bias;
				uniforms.shadowMap.value[ i ] = shadow.map;
				uniforms.shadowMapSize.value[ i ] = shadow.mapSize;
				uniforms.shadowMatrix.value[ i ] = shadow.matrix;

M
Mr.doob 已提交
2168 2169 2170 2171
			}

		}

M
Mr.doob 已提交
2172
	}
M
Mr.doob 已提交
2173 2174 2175 2176 2177

	// Uniforms (load to GPU)

	function loadUniformsMatrices ( uniforms, object ) {

2178
		_gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object.modelViewMatrix.elements );
M
Mr.doob 已提交
2179 2180 2181

		if ( uniforms.normalMatrix ) {

2182
			_gl.uniformMatrix3fv( uniforms.normalMatrix, false, object.normalMatrix.elements );
M
Mr.doob 已提交
2183 2184 2185

		}

M
Mr.doob 已提交
2186
	}
M
Mr.doob 已提交
2187 2188 2189 2190 2191

	function getTextureUnit() {

		var textureUnit = _usedTextureUnits;

G
gero3 已提交
2192
		if ( textureUnit >= capabilities.maxTextures ) {
M
Mr.doob 已提交
2193

G
gero3 已提交
2194
			console.warn( 'WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures );
M
Mr.doob 已提交
2195 2196 2197 2198 2199 2200 2201

		}

		_usedTextureUnits += 1;

		return textureUnit;

M
Mr.doob 已提交
2202
	}
M
Mr.doob 已提交
2203

2204
	function loadUniformsGeneric ( uniforms ) {
M
Mr.doob 已提交
2205

M
Mr.doob 已提交
2206
		var texture, textureUnit;
M
Mr.doob 已提交
2207

M
Mr.doob 已提交
2208 2209 2210
		for ( var j = 0, jl = uniforms.length; j < jl; j ++ ) {

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

2212 2213
			// needsUpdate property is not added to all uniforms.
			if ( uniform.needsUpdate === false ) continue;
2214

M
Mr.doob 已提交
2215 2216
			var type = uniform.type;
			var value = uniform.value;
2217
			var location = uniforms[ j ][ 1 ];
M
Mr.doob 已提交
2218

2219
			switch ( type ) {
M
Mr.doob 已提交
2220

2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
				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;

2265 2266 2267 2268
				case 'Matrix2fv':
					_gl.uniformMatrix2fv( location, false, value );
					break;

2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
				case 'Matrix3fv':
					_gl.uniformMatrix3fv( location, false, value );
					break;

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

				//

M
Mr.doob 已提交
2279
				case 'i':
M
Mr.doob 已提交
2280

2281 2282
					// single integer
					_gl.uniform1i( location, value );
M
Mr.doob 已提交
2283

2284
					break;
M
Mr.doob 已提交
2285

2286
				case 'f':
M
Mr.doob 已提交
2287

2288 2289
					// single float
					_gl.uniform1f( location, value );
M
Mr.doob 已提交
2290

2291
					break;
M
Mr.doob 已提交
2292

2293
				case 'v2':
M
Mr.doob 已提交
2294

2295 2296
					// single THREE.Vector2
					_gl.uniform2f( location, value.x, value.y );
M
Mr.doob 已提交
2297

2298
					break;
M
Mr.doob 已提交
2299

2300
				case 'v3':
M
Mr.doob 已提交
2301

2302 2303
					// single THREE.Vector3
					_gl.uniform3f( location, value.x, value.y, value.z );
M
Mr.doob 已提交
2304

2305
					break;
M
Mr.doob 已提交
2306

M
Mr.doob 已提交
2307
				case 'v4':
M
Mr.doob 已提交
2308

2309 2310
					// single THREE.Vector4
					_gl.uniform4f( location, value.x, value.y, value.z, value.w );
M
Mr.doob 已提交
2311

2312
					break;
M
Mr.doob 已提交
2313

2314
				case 'c':
M
Mr.doob 已提交
2315

2316 2317
					// single THREE.Color
					_gl.uniform3f( location, value.r, value.g, value.b );
M
Mr.doob 已提交
2318

2319
					break;
M
Mr.doob 已提交
2320

2321
				/*
2322 2323 2324
				case 's':

					// TODO: Optimize this.
B
Ben Houston 已提交
2325
					for( var propertyName in uniform.properties ) {
M
Mr.doob 已提交
2326

B
Ben Houston 已提交
2327 2328 2329
						var property = uniform.properties[ propertyName ];
						var locationProperty =  location[ propertyName ];
						var valueProperty = value[ propertyName ];
M
Mr.doob 已提交
2330

2331
						switch( property.type ) {
2332 2333 2334
							case 'i':
								_gl.uniform1i( locationProperty, valueProperty );
								break;
2335
							case 'f':
B
Ben Houston 已提交
2336
								_gl.uniform1f( locationProperty, valueProperty );
2337 2338
								break;
							case 'v2':
B
Ben Houston 已提交
2339
								_gl.uniform2f( locationProperty, valueProperty.x, valueProperty.y );
2340 2341
								break;
							case 'v3':
B
Ben Houston 已提交
2342
								_gl.uniform3f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z );
2343 2344
								break;
							case 'v4':
B
Ben Houston 已提交
2345
								_gl.uniform4f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z, valueProperty.w );
2346 2347
								break;
							case 'c':
B
Ben Houston 已提交
2348
								_gl.uniform3f( locationProperty, valueProperty.r, valueProperty.g, valueProperty.b );
2349 2350
								break;
						};
2351 2352 2353 2354

					}

					break;
2355
				*/
2356

2357
				case 'sa':
2358

2359
					// TODO: Optimize this.
M
Mr.doob 已提交
2360
					for ( var i = 0; i < value.length; i ++ ) {
2361

M
Mr.doob 已提交
2362
						for ( var propertyName in uniform.properties ) {
M
Mr.doob 已提交
2363

B
Ben Houston 已提交
2364 2365
							var property = uniform.properties[ propertyName ];
							var locationProperty =  location[ i ][ propertyName ];
2366
							var valueProperty = value[ i ][ propertyName ];
M
Mr.doob 已提交
2367

2368
							switch ( property.type ) {
2369 2370 2371
								case 'i':
									_gl.uniform1i( locationProperty, valueProperty );
									break;
2372
								case 'f':
B
Ben Houston 已提交
2373
									_gl.uniform1f( locationProperty, valueProperty );
2374 2375
									break;
								case 'v2':
B
Ben Houston 已提交
2376
									_gl.uniform2f( locationProperty, valueProperty.x, valueProperty.y );
2377 2378
									break;
								case 'v3':
B
Ben Houston 已提交
2379
									_gl.uniform3f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z );
2380 2381
									break;
								case 'v4':
B
Ben Houston 已提交
2382
									_gl.uniform4f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z, valueProperty.w );
2383 2384
									break;
								case 'c':
B
Ben Houston 已提交
2385
									_gl.uniform3f( locationProperty, valueProperty.r, valueProperty.g, valueProperty.b );
2386 2387
									break;
							};
2388

2389
						}
2390 2391

					}
M
Mr.doob 已提交
2392

2393 2394
					break;

2395
				case 'iv1':
M
Mr.doob 已提交
2396

2397 2398
					// flat array of integers (JS or typed array)
					_gl.uniform1iv( location, value );
M
Mr.doob 已提交
2399

2400
					break;
M
Mr.doob 已提交
2401

2402
				case 'iv':
M
Mr.doob 已提交
2403

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

2407
					break;
M
Mr.doob 已提交
2408

2409
				case 'fv1':
M
Mr.doob 已提交
2410

2411 2412
					// flat array of floats (JS or typed array)
					_gl.uniform1fv( location, value );
M
Mr.doob 已提交
2413

2414
					break;
M
Mr.doob 已提交
2415

2416
				case 'fv':
M
Mr.doob 已提交
2417

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

2421
					break;
M
Mr.doob 已提交
2422

2423
				case 'v2v':
M
Mr.doob 已提交
2424

2425
					// array of THREE.Vector2
M
Mr.doob 已提交
2426

2427
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2428

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

2431
					}
M
Mr.doob 已提交
2432

M
Mr.doob 已提交
2433
					for ( var i = 0, i2 = 0, il = value.length; i < il; i ++, i2 += 2 ) {
M
Mr.doob 已提交
2434

M
Mr.doob 已提交
2435 2436
						uniform._array[ i2 + 0 ] = value[ i ].x;
						uniform._array[ i2 + 1 ] = value[ i ].y;
M
Mr.doob 已提交
2437

2438
					}
M
Mr.doob 已提交
2439

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

2442
					break;
M
Mr.doob 已提交
2443

2444
				case 'v3v':
M
Mr.doob 已提交
2445

2446
					// array of THREE.Vector3
M
Mr.doob 已提交
2447

2448
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2449

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

2452
					}
M
Mr.doob 已提交
2453

M
Mr.doob 已提交
2454
					for ( var i = 0, i3 = 0, il = value.length; i < il; i ++, i3 += 3 ) {
R
Ryan Tsao 已提交
2455

M
Mr.doob 已提交
2456 2457 2458
						uniform._array[ i3 + 0 ] = value[ i ].x;
						uniform._array[ i3 + 1 ] = value[ i ].y;
						uniform._array[ i3 + 2 ] = value[ i ].z;
R
Ryan Tsao 已提交
2459

2460
					}
R
Ryan Tsao 已提交
2461

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

2464
					break;
R
Ryan Tsao 已提交
2465

2466
				case 'v4v':
R
Ryan Tsao 已提交
2467

2468
					// array of THREE.Vector4
R
Ryan Tsao 已提交
2469

2470
					if ( uniform._array === undefined ) {
R
Ryan Tsao 已提交
2471

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

2474
					}
M
Mr.doob 已提交
2475

M
Mr.doob 已提交
2476
					for ( var i = 0, i4 = 0, il = value.length; i < il; i ++, i4 += 4 ) {
M
Mr.doob 已提交
2477

M
Mr.doob 已提交
2478 2479 2480 2481
						uniform._array[ i4 + 0 ] = value[ i ].x;
						uniform._array[ i4 + 1 ] = value[ i ].y;
						uniform._array[ i4 + 2 ] = value[ i ].z;
						uniform._array[ i4 + 3 ] = value[ i ].w;
M
Mr.doob 已提交
2482

2483
					}
M
Mr.doob 已提交
2484

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

2487
					break;
M
Mr.doob 已提交
2488

2489 2490 2491 2492 2493 2494 2495
				case 'm2':

					// single THREE.Matrix2
					_gl.uniformMatrix2fv( location, false, value.elements );

					break;

2496
				case 'm3':
M
Mr.doob 已提交
2497

2498 2499
					// single THREE.Matrix3
					_gl.uniformMatrix3fv( location, false, value.elements );
M
Mr.doob 已提交
2500

2501
					break;
M
Mr.doob 已提交
2502

2503
				case 'm3v':
M
Mr.doob 已提交
2504

2505
					// array of THREE.Matrix3
M
Mr.doob 已提交
2506

2507
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2508

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

2511
					}
M
Mr.doob 已提交
2512

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

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

2517
					}
M
Mr.doob 已提交
2518

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

2521
					break;
M
Mr.doob 已提交
2522

2523
				case 'm4':
M
Mr.doob 已提交
2524

2525 2526
					// single THREE.Matrix4
					_gl.uniformMatrix4fv( location, false, value.elements );
M
Mr.doob 已提交
2527

2528
					break;
M
Mr.doob 已提交
2529

2530
				case 'm4v':
M
Mr.doob 已提交
2531

2532
					// array of THREE.Matrix4
M
Mr.doob 已提交
2533

2534
					if ( uniform._array === undefined ) {
M
Mr.doob 已提交
2535

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

2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548
					}

					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 已提交
2549

2550
				case 't':
M
Mr.doob 已提交
2551

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

2554 2555 2556 2557
					texture = value;
					textureUnit = getTextureUnit();

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

2559
					if ( ! texture ) continue;
M
Mr.doob 已提交
2560

2561
					if ( texture instanceof THREE.CubeTexture ||
G
gero3 已提交
2562 2563 2564
						 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {

						// CompressedTexture can have Array in image :/
M
Mr.doob 已提交
2565

2566
						setCubeTexture( texture, textureUnit );
M
Mr.doob 已提交
2567

2568 2569
					} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {

M
Mr.doob 已提交
2570 2571 2572 2573 2574
						setCubeTextureDynamic( texture.texture, textureUnit );

					} else if ( texture instanceof THREE.WebGLRenderTarget ) {

						_this.setTexture( texture.texture, textureUnit );
2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585

					} else {

						_this.setTexture( texture, textureUnit );

					}

					break;

				case 'tv':

M
Mr.doob 已提交
2586
					// array of THREE.Texture (2d or cube)
2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608

					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;

M
Mr.doob 已提交
2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628
						if ( texture instanceof THREE.CubeTexture ||
							 ( texture.image instanceof Array && texture.image.length === 6 ) ) {

							// CompressedTexture can have Array in image :/

							setCubeTexture( texture, textureUnit );

						} else if ( texture instanceof THREE.WebGLRenderTarget ) {

							_this.setTexture( texture.texture, textureUnit );

						} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {

							setCubeTextureDynamic( texture.texture, textureUnit );

						} else {

							_this.setTexture( texture, textureUnit );

						}
2629 2630 2631 2632 2633 2634

					}

					break;

				default:
2635

2636
					console.warn( 'THREE.WebGLRenderer: Unknown uniform type: ' + type );
2637

M
Mr.doob 已提交
2638 2639 2640 2641
			}

		}

M
Mr.doob 已提交
2642
	}
M
Mr.doob 已提交
2643

T
tschw 已提交
2644
	function setupLights ( lights, camera ) {
M
Mr.doob 已提交
2645

B
brason 已提交
2646
		var l, ll, light,
M
Mr.doob 已提交
2647
		r = 0, g = 0, b = 0,
B
Ben Houston 已提交
2648
		color,
B
brason 已提交
2649
		intensity,
M
Mr.doob 已提交
2650 2651
		distance,

2652
		viewMatrix = camera.matrixWorldInverse,
M
Mr.doob 已提交
2653

M
Mr.doob 已提交
2654
		directionalLength = 0,
M
Mr.doob 已提交
2655 2656
		pointLength = 0,
		spotLength = 0,
2657 2658 2659
		hemiLength = 0,

		shadowsLength = 0;
M
Mr.doob 已提交
2660

2661 2662
		_lights.shadowsPointLight = 0;

M
Mr.doob 已提交
2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
		for ( l = 0, ll = lights.length; l < ll; l ++ ) {

			light = lights[ l ];

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

			if ( light instanceof THREE.AmbientLight ) {

2673 2674 2675
				r += color.r * intensity;
				g += color.g * intensity;
				b += color.b * intensity;
M
Mr.doob 已提交
2676 2677 2678

			} else if ( light instanceof THREE.DirectionalLight ) {

M
Mr.doob 已提交
2679
				var uniforms = lightCache.get( light );
M
Mr.doob 已提交
2680

M
Mr.doob 已提交
2681
				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
2682
				_vector3.setFromMatrixPosition( light.target.matrixWorld );
M
Mr.doob 已提交
2683 2684 2685 2686
				uniforms.direction.sub( _vector3 );
				uniforms.direction.transformDirection( viewMatrix );
				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );

2687
				if ( light.castShadow ) {
M
Mr.doob 已提交
2688

2689 2690
					uniforms.shadow = shadowsLength;

2691
					_lights.shadows[ shadowsLength ++ ] = light;
2692

2693 2694
				} else {

M
Mr.doob 已提交
2695
					uniforms.shadow = - 1;
2696

2697 2698 2699
				}

				_lights.directional[ directionalLength ++ ] = uniforms;
M
Mr.doob 已提交
2700 2701 2702

			} else if ( light instanceof THREE.PointLight ) {

M
Mr.doob 已提交
2703
				var uniforms = lightCache.get( light );
M
Mr.doob 已提交
2704 2705 2706

				uniforms.position.setFromMatrixPosition( light.matrixWorld );
				uniforms.position.applyMatrix4( viewMatrix );
M
Mr.doob 已提交
2707

M
Mr.doob 已提交
2708 2709 2710
				uniforms.color.copy( light.color ).multiplyScalar( light.intensity );
				uniforms.distance = light.distance;
				uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
M
Mr.doob 已提交
2711

2712 2713
				if ( light.castShadow ) {

2714 2715
					uniforms.shadow = shadowsLength;

2716
					_lights.shadows[ shadowsLength ++ ] = light;
2717 2718
					_lights.shadowsPointLight ++;

2719 2720
				} else {

M
Mr.doob 已提交
2721
					uniforms.shadow = - 1;
2722

2723 2724
				}

2725 2726
				_lights.point[ pointLength ++ ] = uniforms;

M
Mr.doob 已提交
2727 2728
			} else if ( light instanceof THREE.SpotLight ) {

M
Mr.doob 已提交
2729
				var uniforms = lightCache.get( light );
M
Mr.doob 已提交
2730

M
Mr.doob 已提交
2731 2732
				uniforms.position.setFromMatrixPosition( light.matrixWorld );
				uniforms.position.applyMatrix4( viewMatrix );
M
Mr.doob 已提交
2733

M
Mr.doob 已提交
2734 2735
				uniforms.color.copy( color ).multiplyScalar( intensity );
				uniforms.distance = distance;
M
Mr.doob 已提交
2736

M
Mr.doob 已提交
2737
				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
2738
				_vector3.setFromMatrixPosition( light.target.matrixWorld );
M
Mr.doob 已提交
2739 2740
				uniforms.direction.sub( _vector3 );
				uniforms.direction.transformDirection( viewMatrix );
M
Mr.doob 已提交
2741

M
Mr.doob 已提交
2742 2743 2744 2745
				uniforms.angleCos = Math.cos( light.angle );
				uniforms.exponent = light.exponent;
				uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;

2746 2747
				if ( light.castShadow ) {

2748 2749
					uniforms.shadow = shadowsLength;

2750
					_lights.shadows[ shadowsLength ++ ] = light;
M
Mr.doob 已提交
2751

2752 2753
				} else {

M
Mr.doob 已提交
2754
					uniforms.shadow = - 1;
2755

2756 2757 2758
				}

				_lights.spot[ spotLength ++ ] = uniforms;
2759

M
Mr.doob 已提交
2760 2761
			} else if ( light instanceof THREE.HemisphereLight ) {

M
Mr.doob 已提交
2762
				var uniforms = lightCache.get( light );
M
Mr.doob 已提交
2763 2764 2765 2766

				uniforms.direction.setFromMatrixPosition( light.matrixWorld );
				uniforms.direction.transformDirection( viewMatrix );
				uniforms.direction.normalize();
M
Mr.doob 已提交
2767

M
Mr.doob 已提交
2768 2769
				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
M
Mr.doob 已提交
2770

M
Mr.doob 已提交
2771
				_lights.hemi[ hemiLength ++ ] = uniforms;
M
Mr.doob 已提交
2772 2773 2774 2775 2776

			}

		}

M
Mr.doob 已提交
2777 2778 2779
		_lights.ambient[ 0 ] = r;
		_lights.ambient[ 1 ] = g;
		_lights.ambient[ 2 ] = b;
M
Mr.doob 已提交
2780

M
Mr.doob 已提交
2781 2782 2783 2784
		_lights.directional.length = directionalLength;
		_lights.point.length = pointLength;
		_lights.spot.length = spotLength;
		_lights.hemi.length = hemiLength;
2785

2786 2787
		_lights.shadows.length = shadowsLength;

2788
		_lights.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + hemiLength + ',' + shadowsLength;
2789

M
Mr.doob 已提交
2790
	}
M
Mr.doob 已提交
2791 2792 2793 2794 2795 2796 2797

	// GL state setting

	this.setFaceCulling = function ( cullFace, frontFaceDirection ) {

		if ( cullFace === THREE.CullFaceNone ) {

2798
			state.disable( _gl.CULL_FACE );
M
Mr.doob 已提交
2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825

		} 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 );

			}

2826
			state.enable( _gl.CULL_FACE );
M
Mr.doob 已提交
2827 2828 2829 2830 2831 2832 2833 2834 2835

		}

	};

	// Textures

	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {

2836 2837
		var extension;

M
Mr.doob 已提交
2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849
		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 已提交
2850 2851 2852

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

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

2855
			}
M
Mr.doob 已提交
2856 2857 2858 2859

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

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

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

2864
			}
M
Mr.doob 已提交
2865

M
Mr.doob 已提交
2866 2867
		}

2868 2869
		extension = extensions.get( 'EXT_texture_filter_anisotropic' );

2870
		if ( extension ) {
M
Mr.doob 已提交
2871

2872 2873
			if ( texture.type === THREE.FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;
			if ( texture.type === THREE.HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return;
M
Mr.doob 已提交
2874

2875
			if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
M
Mr.doob 已提交
2876

2877
				_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _this.getMaxAnisotropy() ) );
2878
				properties.get( texture ).__currentAnisotropy = texture.anisotropy;
M
Mr.doob 已提交
2879 2880 2881 2882 2883

			}

		}

M
Mr.doob 已提交
2884
	}
M
Mr.doob 已提交
2885

2886
	function uploadTexture( textureProperties, texture, slot ) {
2887

2888
		if ( textureProperties.__webglInit === undefined ) {
2889

2890
			textureProperties.__webglInit = true;
2891 2892 2893

			texture.addEventListener( 'dispose', onTextureDispose );

2894
			textureProperties.__webglTexture = _gl.createTexture();
2895

2896
			_infoMemory.textures ++;
2897 2898

		}
M
Mr.doob 已提交
2899

B
Ben Adams 已提交
2900
		state.activeTexture( _gl.TEXTURE0 + slot );
2901
		state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
M
Mr.doob 已提交
2902

H
Henri Astre 已提交
2903 2904 2905 2906
		_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 );

G
gero3 已提交
2907
		texture.image = clampToMaxSize( texture.image, capabilities.maxTextureSize );
2908

M
Mr.doob 已提交
2909 2910 2911 2912 2913 2914
		if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false ) {

			texture.image = makePowerOfTwo( texture.image );

		}

H
Henri Astre 已提交
2915
		var image = texture.image,
M
Mr.doob 已提交
2916
		isImagePowerOfTwo = isPowerOfTwo( image ),
H
Henri Astre 已提交
2917 2918
		glFormat = paramThreeToGL( texture.format ),
		glType = paramThreeToGL( texture.type );
M
Mr.doob 已提交
2919

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

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

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

H
Henri Astre 已提交
2926 2927 2928
			// 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 已提交
2929

H
Henri Astre 已提交
2930 2931 2932
			if ( mipmaps.length > 0 && isImagePowerOfTwo ) {

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

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

H
Henri Astre 已提交
2937
				}
M
Mr.doob 已提交
2938

H
Henri Astre 已提交
2939
				texture.generateMipmaps = false;
M
Mr.doob 已提交
2940

H
Henri Astre 已提交
2941
			} else {
M
Mr.doob 已提交
2942

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

H
Henri Astre 已提交
2945
			}
M
Mr.doob 已提交
2946

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

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

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

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

2955
					if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
M
Mr.doob 已提交
2956

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

2959
					} else {
M
Mr.doob 已提交
2960

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

2963
					}
M
Mr.doob 已提交
2964

H
Henri Astre 已提交
2965
				} else {
M
Mr.doob 已提交
2966

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

M
Mr.doob 已提交
2969 2970
				}

H
Henri Astre 已提交
2971 2972
			}

G
gero3 已提交
2973 2974 2975
		} else {

			// regular Texture (image, video, canvas)
H
Henri Astre 已提交
2976 2977 2978 2979 2980 2981

			// 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 已提交
2982

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

					mipmap = mipmaps[ i ];
2986
					state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
M
Mr.doob 已提交
2987 2988 2989

				}

H
Henri Astre 已提交
2990
				texture.generateMipmaps = false;
M
Mr.doob 已提交
2991

H
Henri Astre 已提交
2992
			} else {
M
Mr.doob 已提交
2993

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

H
Henri Astre 已提交
2996
			}
M
Mr.doob 已提交
2997

H
Henri Astre 已提交
2998
		}
M
Mr.doob 已提交
2999

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

3002
		textureProperties.__version = texture.version;
M
Mr.doob 已提交
3003

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

3006
	}
M
Mr.doob 已提交
3007

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

3010 3011 3012
		var textureProperties = properties.get( texture );

		if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
M
Mr.doob 已提交
3013

3014
			var image = texture.image;
M
Mr.doob 已提交
3015

3016 3017
			if ( image === undefined ) {

3018
				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture );
3019 3020 3021 3022
				return;

			}

3023
			if ( image.complete === false ) {
M
Mr.doob 已提交
3024

3025
				console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture );
3026 3027 3028 3029
				return;

			}

3030
			uploadTexture( textureProperties, texture, slot );
3031

3032
			return;
M
Mr.doob 已提交
3033 3034 3035

		}

B
Ben Adams 已提交
3036
		state.activeTexture( _gl.TEXTURE0 + slot );
3037
		state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
3038

M
Mr.doob 已提交
3039 3040 3041 3042
	};

	function clampToMaxSize ( image, maxSize ) {

3043
		if ( image.width > maxSize || image.height > maxSize ) {
M
Mr.doob 已提交
3044

3045 3046
			// Warning: Scaling through the canvas will only work with images that use
			// premultiplied alpha.
M
Mr.doob 已提交
3047

3048
			var scale = maxSize / Math.max( image.width, image.height );
M
Mr.doob 已提交
3049

3050 3051 3052
			var canvas = document.createElement( 'canvas' );
			canvas.width = Math.floor( image.width * scale );
			canvas.height = Math.floor( image.height * scale );
M
Mr.doob 已提交
3053

3054 3055
			var context = canvas.getContext( '2d' );
			context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
M
Mr.doob 已提交
3056

3057
			console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );
M
Mr.doob 已提交
3058

3059 3060 3061
			return canvas;

		}
M
Mr.doob 已提交
3062

3063
		return image;
M
Mr.doob 已提交
3064 3065 3066

	}

M
Mr.doob 已提交
3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102
	function isPowerOfTwo( image ) {

		return THREE.Math.isPowerOfTwo( image.width ) && THREE.Math.isPowerOfTwo( image.height );

	}

	function textureNeedsPowerOfTwo( texture ) {

		if ( texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping ) return true;
		if ( texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter ) return true;

		return false;

	}

	function makePowerOfTwo( image ) {

		if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement ) {

			var canvas = document.createElement( 'canvas' );
			canvas.width = THREE.Math.nearestPowerOfTwo( image.width );
			canvas.height = THREE.Math.nearestPowerOfTwo( image.height );

			var context = canvas.getContext( '2d' );
			context.drawImage( image, 0, 0, canvas.width, canvas.height );

			console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image );

			return canvas;

		}

		return image;

	}

M
Mr.doob 已提交
3103 3104
	function setCubeTexture ( texture, slot ) {

3105
		var textureProperties = properties.get( texture );
3106

M
Mr.doob 已提交
3107 3108
		if ( texture.image.length === 6 ) {

3109
			if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
M
Mr.doob 已提交
3110

3111
				if ( ! textureProperties.__image__webglTextureCube ) {
M
Mr.doob 已提交
3112

3113 3114
					texture.addEventListener( 'dispose', onTextureDispose );

3115
					textureProperties.__image__webglTextureCube = _gl.createTexture();
M
Mr.doob 已提交
3116

3117
					_infoMemory.textures ++;
M
Mr.doob 已提交
3118 3119 3120

				}

B
Ben Adams 已提交
3121
				state.activeTexture( _gl.TEXTURE0 + slot );
3122
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
M
Mr.doob 已提交
3123 3124 3125

				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );

M
Mr.doob 已提交
3126 3127
				var isCompressed = texture instanceof THREE.CompressedTexture;
				var isDataTexture = texture.image[ 0 ] instanceof THREE.DataTexture;
M
Mr.doob 已提交
3128 3129 3130 3131 3132

				var cubeImage = [];

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

3133
					if ( _this.autoScaleCubemaps && ! isCompressed && ! isDataTexture ) {
M
Mr.doob 已提交
3134

G
gero3 已提交
3135
						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize );
M
Mr.doob 已提交
3136 3137 3138

					} else {

3139
						cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];
M
Mr.doob 已提交
3140 3141 3142 3143 3144 3145

					}

				}

				var image = cubeImage[ 0 ],
M
Mr.doob 已提交
3146
				isImagePowerOfTwo = isPowerOfTwo( image ),
M
Mr.doob 已提交
3147 3148 3149 3150 3151 3152 3153
				glFormat = paramThreeToGL( texture.format ),
				glType = paramThreeToGL( texture.type );

				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );

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

3154
					if ( ! isCompressed ) {
M
Mr.doob 已提交
3155

M
Mr.doob 已提交
3156
						if ( isDataTexture ) {
3157

3158
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );
3159

M
Mr.doob 已提交
3160
						} else {
3161

3162
							state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
3163

M
Mr.doob 已提交
3164 3165
						}

3166
					} else {
3167

M
Mr.doob 已提交
3168 3169
						var mipmap, mipmaps = cubeImage[ i ].mipmaps;

3170
						for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
M
Mr.doob 已提交
3171 3172

							mipmap = mipmaps[ j ];
M
Mr.doob 已提交
3173

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

3176
								if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) {
M
Mr.doob 已提交
3177

3178
									state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
M
Mr.doob 已提交
3179

3180
								} else {
M
Mr.doob 已提交
3181

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

3184
								}
M
Mr.doob 已提交
3185

3186
							} else {
M
Mr.doob 已提交
3187

3188
								state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
M
Mr.doob 已提交
3189

3190
							}
M
Mr.doob 已提交
3191

3192
						}
M
Mr.doob 已提交
3193

M
Mr.doob 已提交
3194
					}
M
Mr.doob 已提交
3195

M
Mr.doob 已提交
3196 3197 3198 3199 3200 3201 3202 3203
				}

				if ( texture.generateMipmaps && isImagePowerOfTwo ) {

					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );

				}

3204
				textureProperties.__version = texture.version;
M
Mr.doob 已提交
3205

B
Ben Adams 已提交
3206
				if ( texture.onUpdate ) texture.onUpdate( texture );
M
Mr.doob 已提交
3207 3208 3209

			} else {

B
Ben Adams 已提交
3210
				state.activeTexture( _gl.TEXTURE0 + slot );
3211
				state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube );
M
Mr.doob 已提交
3212 3213 3214 3215 3216

			}

		}

M
Mr.doob 已提交
3217
	}
M
Mr.doob 已提交
3218 3219 3220

	function setCubeTextureDynamic ( texture, slot ) {

B
Ben Adams 已提交
3221
		state.activeTexture( _gl.TEXTURE0 + slot );
3222
		state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );
M
Mr.doob 已提交
3223

M
Mr.doob 已提交
3224
	}
M
Mr.doob 已提交
3225 3226 3227

	// Render targets

3228 3229
	// Setup storage for target texture and bind it to correct framebuffer
	function setupFrameBufferTexture ( framebuffer, renderTarget, attachment, textureTarget ) {
M
Mr.doob 已提交
3230

3231 3232 3233
		var glFormat = paramThreeToGL( renderTarget.texture.format );
		var glType = paramThreeToGL( renderTarget.texture.type );
		state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
M
Mr.doob 已提交
3234
		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
3235 3236
		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );
		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
M
Mr.doob 已提交
3237

M
Mr.doob 已提交
3238
	}
M
Mr.doob 已提交
3239

3240 3241
	// Setup storage for internal depth/stencil buffers and bind to correct framebuffer
	function setupRenderBufferStorage ( renderbuffer, renderTarget ) {
M
Mr.doob 已提交
3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256

		_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 );

		} 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 {

3257
			// FIXME: We don't support !depth !stencil
M
Mr.doob 已提交
3258 3259 3260 3261
			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );

		}

3262
		_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
M
Mr.doob 已提交
3263

M
Mr.doob 已提交
3264
	}
M
Mr.doob 已提交
3265

3266
	// Setup GL resources for a non-texture depth buffer
M
Marius Kintel 已提交
3267
	function setupDepthRenderbuffer( renderTarget ) {
M
Mr.doob 已提交
3268

3269
		var renderTargetProperties = properties.get( renderTarget );
M
Mr.doob 已提交
3270 3271

		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
M
Mr.doob 已提交
3272

3273
		if ( isCube ) {
M
Mr.doob 已提交
3274

3275
			renderTargetProperties.__webglDepthbuffer = [];
M
Mr.doob 已提交
3276

3277
			for ( var i = 0; i < 6; i ++ ) {
M
Mr.doob 已提交
3278

M
Marius Kintel 已提交
3279
				_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );
3280 3281
				renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();
				setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );
M
Mr.doob 已提交
3282 3283

			}
B
Ben Adams 已提交
3284

M
Mr.doob 已提交
3285
		} else {
M
Mr.doob 已提交
3286

M
Marius Kintel 已提交
3287
			_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
3288 3289
			renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
			setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );
M
Mr.doob 已提交
3290

3291
		}
M
Mr.doob 已提交
3292

M
Marius Kintel 已提交
3293
		_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
M
Mr.doob 已提交
3294

M
Mr.doob 已提交
3295
	}
M
Mr.doob 已提交
3296

3297
	// Set up GL resources for the render target
M
Marius Kintel 已提交
3298
	function setupRenderTarget( renderTarget ) {
M
Mr.doob 已提交
3299

3300 3301
		var renderTargetProperties = properties.get( renderTarget );
		var textureProperties = properties.get( renderTarget.texture );
M
Mr.doob 已提交
3302

3303
		renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
M
Mr.doob 已提交
3304

3305
		textureProperties.__webglTexture = _gl.createTexture();
M
Mr.doob 已提交
3306

3307
		_infoMemory.textures ++;
M
Mr.doob 已提交
3308

3309 3310
		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
		var isTargetPowerOfTwo = THREE.Math.isPowerOfTwo( renderTarget.width ) && THREE.Math.isPowerOfTwo( renderTarget.height );
M
Mr.doob 已提交
3311

3312
		// Setup framebuffer
M
Mr.doob 已提交
3313

3314
		if ( isCube ) {
M
Mr.doob 已提交
3315

3316
			renderTargetProperties.__webglFramebuffer = [];
M
Mr.doob 已提交
3317

3318
			for ( var i = 0; i < 6; i ++ ) {
M
Mr.doob 已提交
3319

3320
				renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();
M
Mr.doob 已提交
3321

3322
			}
M
Mr.doob 已提交
3323

3324
		} else {
M
Mr.doob 已提交
3325

3326
			renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
M
Mr.doob 已提交
3327

3328
		}
M
Mr.doob 已提交
3329

3330
		// Setup color buffer
M
Mr.doob 已提交
3331

3332
		if ( isCube ) {
M
Mr.doob 已提交
3333

3334 3335 3336
			state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
			setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo );
			for ( var i = 0; i < 6; i ++ ) {
M
Mr.doob 已提交
3337

3338
				setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
M
Mr.doob 已提交
3339 3340 3341

			}

3342 3343
			if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
			state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
M
Mr.doob 已提交
3344

3345
		} else {
M
Mr.doob 已提交
3346

3347 3348 3349
			state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
			setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo );
			setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );
M
Mr.doob 已提交
3350

3351 3352
			if ( renderTarget.texture.generateMipmaps && isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
			state.bindTexture( _gl.TEXTURE_2D, null );
M
Mr.doob 已提交
3353

3354
		}
M
Mr.doob 已提交
3355

3356
		// Setup depth and stencil buffers
3357

3358
		if ( renderTarget.depthBuffer ) {
M
Mr.doob 已提交
3359

M
Marius Kintel 已提交
3360
			setupDepthRenderbuffer( renderTarget );
M
Mr.doob 已提交
3361

3362
		}
M
Mr.doob 已提交
3363

3364
	}
M
Mr.doob 已提交
3365

3366
	this.setRenderTarget = function ( renderTarget ) {
M
Mr.doob 已提交
3367

3368 3369
		_currentRenderTarget = renderTarget;

3370
		if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {
M
Mr.doob 已提交
3371

M
Marius Kintel 已提交
3372
			setupRenderTarget( renderTarget );
M
Mr.doob 已提交
3373 3374 3375

		}

3376
		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
M
Mr.doob 已提交
3377 3378 3379 3380
		var framebuffer, width, height, vx, vy;

		if ( renderTarget ) {

3381
			var renderTargetProperties = properties.get( renderTarget );
F
Fordy 已提交
3382

M
Mr.doob 已提交
3383 3384
			if ( isCube ) {

3385
				framebuffer = renderTargetProperties.__webglFramebuffer[ renderTarget.activeCubeFace ];
M
Mr.doob 已提交
3386 3387 3388

			} else {

3389
				framebuffer = renderTargetProperties.__webglFramebuffer;
M
Mr.doob 已提交
3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419

			}

			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;

		}

M
Mr.doob 已提交
3420 3421 3422 3423 3424 3425 3426
		if ( isCube ) {

			var textureProperties = properties.get( renderTarget.texture );
			_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, 0 );

		}

M
Mr.doob 已提交
3427 3428 3429 3430 3431
		_currentWidth = width;
		_currentHeight = height;

	};

M
Mr.doob 已提交
3432
	this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) {
3433

M
Mr.doob 已提交
3434
		if ( renderTarget instanceof THREE.WebGLRenderTarget === false ) {
3435

3436
			console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
G
gero3 已提交
3437
			return;
3438

G
gero3 已提交
3439
		}
3440

M
Mr.doob 已提交
3441
		var framebuffer = properties.get( renderTarget ).__webglFramebuffer;
3442

M
Mr.doob 已提交
3443
		if ( framebuffer ) {
3444

G
gero3 已提交
3445
			var restore = false;
3446

M
Mr.doob 已提交
3447
			if ( framebuffer !== _currentFramebuffer ) {
3448

M
Mr.doob 已提交
3449
				_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
3450

G
gero3 已提交
3451
				restore = true;
3452

G
gero3 已提交
3453
			}
3454

M
Mr.doob 已提交
3455
			try {
3456

M
Mr.doob 已提交
3457
				var texture = renderTarget.texture;
3458

M
Mr.doob 已提交
3459 3460
				if ( texture.format !== THREE.RGBAFormat
					&& paramThreeToGL( texture.format ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
3461

M
Mr.doob 已提交
3462 3463
					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
					return;
3464

M
Mr.doob 已提交
3465
				}
3466

M
Mr.doob 已提交
3467 3468 3469 3470
				if ( texture.type !== THREE.UnsignedByteType
					&& paramThreeToGL( texture.type ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE )
					&& ! ( texture.type === THREE.FloatType && extensions.get( 'WEBGL_color_buffer_float' ) )
					&& ! ( texture.type === THREE.HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) {
3471

M
Mr.doob 已提交
3472 3473
					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
					return;
3474

M
Mr.doob 已提交
3475
				}
3476

M
Mr.doob 已提交
3477
				if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {
3478

M
Mr.doob 已提交
3479
					_gl.readPixels( x, y, width, height, paramThreeToGL( texture.format ), paramThreeToGL( texture.type ), buffer );
3480

M
Mr.doob 已提交
3481
				} else {
M
Mr.doob 已提交
3482

M
Mr.doob 已提交
3483 3484 3485
					console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );

				}
M
Mr.doob 已提交
3486

M
Mr.doob 已提交
3487
			} finally {
M
Mr.doob 已提交
3488

M
Mr.doob 已提交
3489 3490 3491
				if ( restore ) {

					_gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );
M
Mr.doob 已提交
3492

M
Mr.doob 已提交
3493 3494 3495
				}

			}
M
Mr.doob 已提交
3496 3497 3498

		}

M
Mr.doob 已提交
3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509
	};

	function updateRenderTargetMipmap( renderTarget ) {

		var target = renderTarget instanceof THREE.WebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
		var texture = properties.get( renderTarget.texture ).__webglTexture;

		state.bindTexture( target, texture );
		_gl.generateMipmap( target );
		state.bindTexture( target, null );

M
Mr.doob 已提交
3510
	}
M
Mr.doob 已提交
3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523

	// 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 已提交
3524
	}
M
Mr.doob 已提交
3525 3526 3527 3528 3529

	// Map three.js constants to WebGL constants

	function paramThreeToGL ( p ) {

3530 3531
		var extension;

M
Mr.doob 已提交
3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
		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;

3556 3557 3558 3559 3560 3561 3562 3563
		extension = extensions.get( 'OES_texture_half_float' );

		if ( extension !== null ) {

			if ( p === THREE.HalfFloatType ) return extension.HALF_FLOAT_OES;

		}

M
Mr.doob 已提交
3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586
		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;

3587
		extension = extensions.get( 'WEBGL_compressed_texture_s3tc' );
M
Mr.doob 已提交
3588

3589 3590 3591 3592 3593 3594
		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 已提交
3595 3596 3597

		}

3598 3599 3600
		extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );

		if ( extension !== null ) {
P
Pierre Lepers 已提交
3601

3602 3603 3604 3605
			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 已提交
3606 3607 3608

		}

3609 3610 3611
		extension = extensions.get( 'EXT_blend_minmax' );

		if ( extension !== null ) {
3612

3613 3614
			if ( p === THREE.MinEquation ) return extension.MIN_EXT;
			if ( p === THREE.MaxEquation ) return extension.MAX_EXT;
3615 3616 3617

		}

M
Mr.doob 已提交
3618 3619
		return 0;

M
Mr.doob 已提交
3620
	}
M
Mr.doob 已提交
3621 3622

};